mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
Feature/elf pattern scan (#133)
* added some code * improvement * visit * added scanner code * update * fixed naming * added const * added type casting * added file * patch * added unlikely * added in module scanner * fixing test * fix * remove * improvement * fix * Update source/utility/elf_pattern_scan.cpp Co-authored-by: Saikari <lin@sz.cn.eu.org> * rev * fix * patch * decomposed method * fix * fix * improvement * fix * fix * commented stuff --------- Co-authored-by: Saikari <lin@sz.cn.eu.org>
This commit is contained in:
@@ -239,8 +239,8 @@ namespace
|
||||
|
||||
struct ExtractedSection
|
||||
{
|
||||
std::uint64_t virtual_base_addr;
|
||||
std::uint64_t raw_base_addr;
|
||||
std::uintptr_t virtual_base_addr;
|
||||
std::uintptr_t raw_base_addr;
|
||||
std::vector<std::byte> data;
|
||||
};
|
||||
|
||||
@@ -261,7 +261,7 @@ namespace
|
||||
|
||||
const auto nt_headers = get_nt_header_from_file(file, dos_header);
|
||||
|
||||
if (!nt_headers)
|
||||
if (!nt_headers) [[unlikely]]
|
||||
return std::nullopt;
|
||||
|
||||
if (invalid_nt_header_file(nt_headers.value())) [[unlikely]]
|
||||
@@ -290,10 +290,11 @@ namespace
|
||||
file.seekg(current_section.ptr_raw_data, std::ios::beg);
|
||||
file.read(reinterpret_cast<char*>(section_data.data()),
|
||||
static_cast<std::streamsize>(section_data.size()));
|
||||
return ExtractedSection{.virtual_base_addr = current_section.virtual_address
|
||||
+ concrete_headers.optional_header.image_base,
|
||||
.raw_base_addr = current_section.ptr_raw_data,
|
||||
.data = std::move(section_data)};
|
||||
return ExtractedSection{
|
||||
.virtual_base_addr = static_cast<std::uintptr_t>(
|
||||
current_section.virtual_address + concrete_headers.optional_header.image_base),
|
||||
.raw_base_addr = static_cast<std::uintptr_t>(current_section.ptr_raw_data),
|
||||
.data = std::move(section_data)};
|
||||
}
|
||||
return std::nullopt;
|
||||
},
|
||||
@@ -304,46 +305,71 @@ namespace
|
||||
namespace omath
|
||||
{
|
||||
|
||||
std::optional<std::uintptr_t> PePatternScanner::scan_for_pattern_in_loaded_module(const void* module_base_address,
|
||||
const std::string_view& pattern)
|
||||
std::optional<std::uintptr_t>
|
||||
PePatternScanner::scan_for_pattern_in_loaded_module(const void* module_base_address,
|
||||
const std::string_view& pattern,
|
||||
const std::string_view& target_section_name)
|
||||
{
|
||||
const auto base_address = reinterpret_cast<std::uintptr_t>(module_base_address);
|
||||
const auto* base_bytes = static_cast<const std::byte*>(module_base_address);
|
||||
|
||||
if (!base_address)
|
||||
return std::nullopt;
|
||||
|
||||
auto nt_header_variant = get_nt_header_from_loaded_module(module_base_address);
|
||||
const auto* dos_header = static_cast<const DosHeader*>(module_base_address);
|
||||
|
||||
if (!nt_header_variant)
|
||||
if (invalid_dos_header_file(*dos_header)) [[unlikely]]
|
||||
return std::nullopt;
|
||||
|
||||
const auto nt_header_variant = get_nt_header_from_loaded_module(module_base_address);
|
||||
|
||||
if (!nt_header_variant) [[unlikely]]
|
||||
return std::nullopt;
|
||||
|
||||
return std::visit(
|
||||
[base_address, &pattern](const auto& nt_header) -> std::optional<std::uintptr_t>
|
||||
[base_bytes, base_address, lfanew = dos_header->e_lfanew, &target_section_name,
|
||||
&pattern](const auto& nt_header) -> std::optional<std::uintptr_t>
|
||||
{
|
||||
// Define .text segment as scan area
|
||||
const auto start = nt_header.optional_header.base_of_code;
|
||||
const auto scan_size = nt_header.optional_header.size_code;
|
||||
constexpr std::size_t signature_size = sizeof(nt_header.signature);
|
||||
const auto section_table_off = static_cast<std::size_t>(lfanew) + signature_size
|
||||
+ sizeof(FileHeader) + nt_header.file_header.size_optional_header;
|
||||
|
||||
const auto scan_range = std::span{reinterpret_cast<std::byte*>(base_address) + start, scan_size};
|
||||
const auto* section_table = reinterpret_cast<const SectionHeader*>(base_bytes + section_table_off);
|
||||
|
||||
// ReSharper disable once CppTooWideScopeInitStatement
|
||||
const auto result = PatternScanner::scan_for_pattern(scan_range, pattern);
|
||||
for (std::size_t i = 0; i < nt_header.file_header.num_sections; ++i)
|
||||
{
|
||||
const auto* section = section_table + i;
|
||||
|
||||
if (result != scan_range.end())
|
||||
return reinterpret_cast<std::uintptr_t>(&*result);
|
||||
if (std::string_view{section->name} != target_section_name || section->size_raw_data == 0)
|
||||
continue;
|
||||
|
||||
const auto section_size = section->virtual_size != 0
|
||||
? static_cast<std::size_t>(section->virtual_size)
|
||||
: static_cast<std::size_t>(section->size_raw_data);
|
||||
|
||||
const auto* section_begin =
|
||||
reinterpret_cast<std::byte*>(base_address + section->virtual_address);
|
||||
const auto scan_range = std::span{section_begin, section_size};
|
||||
|
||||
const auto result =
|
||||
PatternScanner::scan_for_pattern(scan_range.begin(), scan_range.end(), pattern);
|
||||
|
||||
if (result != scan_range.end())
|
||||
return reinterpret_cast<std::uintptr_t>(&*result);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
},
|
||||
nt_header_variant.value());
|
||||
}
|
||||
std::optional<PeSectionScanResult>
|
||||
std::optional<SectionScanResult>
|
||||
PePatternScanner::scan_for_pattern_in_file(const std::filesystem::path& path_to_file,
|
||||
const std::string_view& pattern,
|
||||
const std::string_view& target_section_name)
|
||||
{
|
||||
const auto pe_section = extract_section_from_pe_file(path_to_file, target_section_name);
|
||||
|
||||
if (!pe_section.has_value())
|
||||
if (!pe_section.has_value()) [[unlikely]]
|
||||
return std::nullopt;
|
||||
|
||||
const auto scan_result =
|
||||
@@ -353,8 +379,8 @@ namespace omath
|
||||
return std::nullopt;
|
||||
const auto offset = std::distance(pe_section->data.begin(), scan_result);
|
||||
|
||||
return PeSectionScanResult{.virtual_base_addr = pe_section->virtual_base_addr,
|
||||
.raw_base_addr = pe_section->raw_base_addr,
|
||||
.target_offset = offset};
|
||||
return SectionScanResult{.virtual_base_addr = pe_section->virtual_base_addr,
|
||||
.raw_base_addr = pe_section->raw_base_addr,
|
||||
.target_offset = offset};
|
||||
}
|
||||
} // namespace omath
|
||||
Reference in New Issue
Block a user