Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 68 additions & 56 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# CMakeList.txt : Top-level CMake project file, do global configuration
# and include sub-projects here.
#
cmake_minimum_required (VERSION 3.15)
cmake_minimum_required(VERSION 3.15)

project ("LightningScanner" VERSION 1.0.1 LANGUAGES CXX)
project("LightningScanner" VERSION 1.0.1 LANGUAGES CXX)

set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")

Expand All @@ -16,71 +16,83 @@ set(LIGHTNING_SCANNER_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/cmake/Lightni

if (MSVC)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()
endif ()

add_library(LightningScanner "include/LightningScanner/LightningScanner.hpp" "include/LightningScanner/backends/Avx2.hpp" "include/LightningScanner/Pattern.hpp" "src/backends/Avx2.cpp" "src/CpuInfo.cpp" "src/backends/Sse42.cpp" "include/LightningScanner/allocator/AlignedAllocator.hpp" "src/backends/Scalar.cpp")
add_library(LightningScanner "include/LightningScanner/LightningScanner.hpp"
"include/LightningScanner/Pattern.hpp"
"src/CpuInfo.cpp"
"include/LightningScanner/allocator/AlignedAllocator.hpp"
"src/backends/Scalar.cpp"
"src/backends/StdFind.cpp")

if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set_source_files_properties("src/backends/Avx2.cpp" PROPERTIES COMPILE_FLAGS /arch:AVX2)
else ()
set_source_files_properties("src/backends/Avx2.cpp" PROPERTIES COMPILE_FLAGS -mavx2)
set_source_files_properties("src/backends/Sse42.cpp" PROPERTIES COMPILE_FLAGS -msse4.2)
endif()
if (NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
target_sources(LightningScanner PRIVATE
"src/backends/Avx2.cpp"
"src/backends/Sse42.cpp"
)

if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set_source_files_properties("src/backends/Avx2.cpp" PROPERTIES COMPILE_FLAGS /arch:AVX2)
else ()
set_source_files_properties("src/backends/Avx2.cpp" PROPERTIES COMPILE_FLAGS -mavx2)
set_source_files_properties("src/backends/Sse42.cpp" PROPERTIES COMPILE_FLAGS -msse4.2)
endif ()
endif ()

target_compile_features(LightningScanner PUBLIC cxx_std_17)
target_include_directories(LightningScanner PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${LIGHTNING_SCANNER_INCLUDE_INSTALL_DIR}>)
target_include_directories(LightningScanner PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${LIGHTNING_SCANNER_INCLUDE_INSTALL_DIR}>)

option(LIGHTNING_SCANNER_BUILD_BENCH "Build Benchmarks" OFF)
if (LIGHTNING_SCANNER_BUILD_BENCH)
add_subdirectory("bench")
endif()
if (LIGHTNING_SCANNER_BUILD_BENCH)
add_subdirectory("bench")
endif ()

option(LIGHTNING_SCANNER_BUILD_DOCS "Build Docs" OFF)
if (LIGHTNING_SCANNER_BUILD_DOCS)
add_subdirectory("docs")
endif()
add_subdirectory("docs")
endif ()

option(LIGHTNING_SCANNER_BUILD_TESTS "Build Tests" OFF)
option(LIGHTNING_SCANNER_BUILD_TESTS "Build Tests" ON)
if (LIGHTNING_SCANNER_BUILD_TESTS)
add_subdirectory("tests")
endif()
add_subdirectory("tests")
endif ()

## Install
if (LIGHTNING_SCANNER_INSTALL)
include(CMakePackageConfigHelpers)

install(
DIRECTORY "${PROJECT_SOURCE_DIR}/include/LightningScanner"
DESTINATION "${LIGHTNING_SCANNER_INCLUDE_INSTALL_DIR}"
)
install(
TARGETS LightningScanner
EXPORT LightningScannerTargets
INCLUDES DESTINATION "${LIGHTNING_SCANNER_INCLUDE_INSTALL_DIR}"
LIBRARY DESTINATION "${LIGHTNING_SCANNER_LIBRARY_INSTALL_DIR}"
ARCHIVE DESTINATION "${LIGHTNING_SCANNER_LIBRARY_INSTALL_DIR}"
RUNTIME DESTINATION "${LIGHTNING_SCANNER_BINARY_INSTALL_DIR}"
)
export(
TARGETS LightningScanner
NAMESPACE LightningScanner::
FILE "${LIGHTNING_SCANNER_CONFIG_INSTALL_DIR}/LightningScannerTargets.cmake"
)
write_basic_package_version_file(
"LightningScannerVersion.cmake"
COMPATIBILITY AnyNewerVersion
)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/LightningScannerVersion.cmake" "cmake/LightningScannerConfig.cmake"
DESTINATION "${LIGHTNING_SCANNER_CONFIG_INSTALL_DIR}"
)
install(
EXPORT LightningScannerTargets
NAMESPACE LightningScanner::
DESTINATION "${LIGHTNING_SCANNER_CONFIG_INSTALL_DIR}"
)

endif()
include(CMakePackageConfigHelpers)

install(
DIRECTORY "${PROJECT_SOURCE_DIR}/include/LightningScanner"
DESTINATION "${LIGHTNING_SCANNER_INCLUDE_INSTALL_DIR}"
)
install(
TARGETS LightningScanner
EXPORT LightningScannerTargets
INCLUDES DESTINATION "${LIGHTNING_SCANNER_INCLUDE_INSTALL_DIR}"
LIBRARY DESTINATION "${LIGHTNING_SCANNER_LIBRARY_INSTALL_DIR}"
ARCHIVE DESTINATION "${LIGHTNING_SCANNER_LIBRARY_INSTALL_DIR}"
RUNTIME DESTINATION "${LIGHTNING_SCANNER_BINARY_INSTALL_DIR}"
)
export(
TARGETS LightningScanner
NAMESPACE LightningScanner::
FILE "${LIGHTNING_SCANNER_CONFIG_INSTALL_DIR}/LightningScannerTargets.cmake"
)

write_basic_package_version_file(
"LightningScannerVersion.cmake"
COMPATIBILITY AnyNewerVersion
)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/LightningScannerVersion.cmake" "cmake/LightningScannerConfig.cmake"
DESTINATION "${LIGHTNING_SCANNER_CONFIG_INSTALL_DIR}"
)
install(
EXPORT LightningScannerTargets
NAMESPACE LightningScanner::
DESTINATION "${LIGHTNING_SCANNER_CONFIG_INSTALL_DIR}"
)

endif ()
7 changes: 7 additions & 0 deletions bench/LightningBench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ std::ostream& operator<<(std::ostream& os, const ScanMode& mode) {
case ScanMode::Sse42:
os << "SSE4.2";
break;
case ScanMode::StdFind:
os << "StdFind";
break;
case ScanMode::Scalar:
os << "Scalar";
break;
Expand Down Expand Up @@ -66,6 +69,10 @@ int main() {
largeBinary.data(), largeBinary.size(),
"48 89 5c 24 ?? 48 89 6c 24 ?? 48 89 74 24 ?? 48 89 7c 24 ?? 41 56 41 "
"57 4c 8b 79 38 aa bf cd");
Bench<ScanMode::StdFind>(
largeBinary.data(), largeBinary.size(),
"48 89 5c 24 ?? 48 89 6c 24 ?? 48 89 74 24 ?? 48 89 7c 24 ?? 41 56 41 "
"57 4c 8b 79 38 aa bf cd");
Bench<ScanMode::Scalar>(
largeBinary.data(), largeBinary.size(),
"48 89 5c 24 ?? 48 89 6c 24 ?? 48 89 74 24 ?? 48 89 7c 24 ?? 41 56 41 "
Expand Down
26 changes: 25 additions & 1 deletion include/LightningScanner/LightningScanner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
#include <LightningScanner/ScanMode.hpp>
#include <LightningScanner/ScanResult.hpp>

#include <LightningScanner/backends/Scalar.hpp>
#include <LightningScanner/backends/StdFind.hpp>

#if !defined(__aarch64__)
#include <LightningScanner/CpuInfo.hpp>
#include <LightningScanner/backends/Avx2.hpp>
#include <LightningScanner/backends/Scalar.hpp>
#include <LightningScanner/backends/Sse42.hpp>
#endif

namespace LightningScanner {

Expand Down Expand Up @@ -56,12 +60,24 @@ class Scanner {
* \endcode
*/
ScanResult Find(void* startAddr, size_t size) const {
#if !defined(__aarch64__)
return FindAMD64(startAddr, size);
#else
return FindAArch64(startAddr, size);
#endif
}

private:
#if !defined(__aarch64__)
ScanResult FindAMD64(void* startAddr, size_t size) const {
const CpuInfo& cpuInfo = CpuInfo::GetCpuInfo();

if (PreferredMode == ScanMode::Avx2 && cpuInfo.avx2Supported)
return FindAvx2(m_Pattern, startAddr, size);
else if (PreferredMode == ScanMode::Sse42 && cpuInfo.sse42Supported)
return FindSse42(m_Pattern, startAddr, size);
else if (PreferredMode == ScanMode::StdFind)
return FindStdFind(m_Pattern, startAddr, size);
else if (PreferredMode == ScanMode::Scalar)
return FindScalar(m_Pattern, startAddr, size);

Expand All @@ -72,6 +88,14 @@ class Scanner {

return FindScalar(m_Pattern, startAddr, size);
}
#else
ScanResult FindAArch64(void* startAddr, size_t size) const {
if (PreferredMode == ScanMode::StdFind)
return FindStdFind(m_Pattern, startAddr, size);

return FindScalar(m_Pattern, startAddr, size);
}
#endif

private:
Pattern m_Pattern;
Expand Down
9 changes: 6 additions & 3 deletions include/LightningScanner/Pattern.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,26 @@ struct Pattern {
*
* \tparam Len pattern string length.
*
* \param pattern pattern string.
* \param pattern pattern string. The first byte of the pattern string must
* not be a wildcard.
*/
template <size_t Len>
constexpr Pattern(const char (&pattern)[Len]) : Pattern(pattern, Len - 1) {}

/**
* Create a new Pattern instance from a `string_view`
*
* \param pattern pattern string.
* \param pattern pattern string. The first byte of the pattern string must
* not be a wildcard.
*/
Pattern(const std::string_view pattern)
: Pattern(pattern.data(), pattern.size()) {}

/**
* Create a new Pattern instance from a c-string and its length
*
* \param pattern pattern string.
* \param pattern pattern string. The first byte of the pattern string must
* not be a wildcard.
* \param len pattern string length.
*/
Pattern(const char* pattern, const size_t len) {
Expand Down
2 changes: 2 additions & 0 deletions include/LightningScanner/ScanMode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ enum class ScanMode {
Sse42,
/** Scan mode that uses AVX2 SIMD instructions */
Avx2,
/** Scan mode that uses std::find */
StdFind
};
18 changes: 18 additions & 0 deletions include/LightningScanner/backends/StdFind.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once
#include <LightningScanner/Pattern.hpp>
#include <LightningScanner/ScanResult.hpp>

namespace LightningScanner {

/**
* Scan the binary using std::find scanning.
*
* \headerfile StdFind.hpp <LightningScanner/backends/StdFind.hpp>
*
* \param{in} data pattern data.
* \param{in} startAddr addres to start the search from.
* \param{in} size binary size of the search area
*/
ScanResult FindStdFind(const Pattern& data, void* startAddr, size_t size);

} // namespace LightningScanner
4 changes: 4 additions & 0 deletions src/CpuInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ namespace LightningScanner {
#include <intrin.h>
#define cpuid(info, x) __cpuidex(info, x, 0)
#else
#if !defined(__aarch64__)
#include <cpuid.h>
void cpuid(int info[4], int infoType) {
__cpuid_count(infoType, 0, info[0], info[1], info[2], info[3]);
}
#endif
#endif

CpuInfo::CpuInfo() {
#if !defined(__aarch64__)
int32_t info[4];
cpuid(info, 0);
int32_t idsAmount = info[0];
Expand All @@ -35,6 +38,7 @@ CpuInfo::CpuInfo() {

avx2Supported = cpuInfo[1] & AVX2_MASK;
}
#endif
}

const CpuInfo& CpuInfo::GetCpuInfo() {
Expand Down
34 changes: 34 additions & 0 deletions src/backends/StdFind.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <LightningScanner/backends/StdFind.hpp>
#include <algorithm>

namespace LightningScanner {

ScanResult FindStdFind(const Pattern& data, void* startAddr, size_t size) {
uint8_t* start = static_cast<uint8_t*>(startAddr);
uint8_t* end =
static_cast<uint8_t*>(startAddr) + size - data.unpaddedSize + 1;

uint8_t element = data.data[0];
while ((start = std::find(start, end, element)) != end) {
bool found = true;

for (size_t i = 0; i < data.unpaddedSize; i++) {
uint8_t searchElement = data.data[i] & data.mask[i];
uint8_t foundElement = start[i] & data.mask[i];
if (searchElement != foundElement) {
found = false;
break;
}
}

if (found) {
return ScanResult(start);
}

start++;
}

return ScanResult(nullptr);
}

} // namespace LightningScanner
13 changes: 13 additions & 0 deletions tests/LargePattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ TEST(LargePattern, Sse42) {
ASSERT_EQ(offset, 0x40);
}

TEST(LargePattern, StdFind) {
const Scanner<ScanMode::StdFind> scanner(
"42 cd e7 f8 21 5b d6 b8 d1 be 12 0e 85 34 c4 ?? 03 7e bc 7b b9 29 b6 "
"07 31 7e ?? dd 3e 0a e7 71 f3 b7 76 3f 36 e1 f3 3b c6 e5 ?? f8 97 67 "
"86 60 ");

const uint8_t* pointer =
scanner.Find((void*)dataSet, dataSetSize).Get<uint8_t>();
const size_t offset = ((uint64_t)pointer - (uint64_t)dataSet);

ASSERT_EQ(offset, 0x40);
}

TEST(LargePattern, Scalar) {
const Scanner<ScanMode::Scalar> scanner(
"42 cd e7 f8 21 5b d6 b8 d1 be 12 0e 85 34 c4 ?? 03 7e bc 7b b9 29 b6 "
Expand Down
12 changes: 12 additions & 0 deletions tests/SimilarPattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ TEST(SimilarPattern, Sse42) {
ASSERT_EQ(offset, 0x24);
}

TEST(SimilarPattern, StdFind) {
const Scanner<ScanMode::StdFind> scanner(
"40 57 48 83 EC ? 48 C7 44 24 ? ? ? ? ? 48 89 5C 24 ? 48 89 6C 24 ? 48 "
"89 74 24 ? 49 8B E9 48 8B F2");

const uint8_t* pointer =
scanner.Find((void*)dataSet, dataSetSize).Get<uint8_t>();
const size_t offset = ((uint64_t)pointer - (uint64_t)dataSet);

ASSERT_EQ(offset, 0x24);
}

TEST(SimilarPattern, Scalar) {
const Scanner<ScanMode::Scalar> scanner(
"40 57 48 83 EC ? 48 C7 44 24 ? ? ? ? ? 48 89 5C 24 ? 48 89 6C 24 ? 48 "
Expand Down
Loading