added stuff

This commit is contained in:
2026-03-15 16:54:47 +03:00
parent 3fb98397e4
commit ccea4a0f0d
9 changed files with 810 additions and 8 deletions

View File

@@ -5,6 +5,7 @@
#include <array>
#include <fstream>
#include <omath/utility/elf_pattern_scan.hpp>
#include <span>
#include <utility>
#include <variant>
#include <vector>
@@ -140,6 +141,87 @@ namespace
std::uintptr_t raw_base_addr{};
std::vector<std::byte> data;
};
template<FileArch arch>
std::optional<ExtractedSection> get_elf_section_from_memory_impl(const std::span<const std::byte> data,
const std::string_view& section_name)
{
using FH = typename ElfHeaders<arch>::FileHeader;
using SH = typename ElfHeaders<arch>::SectionHeader;
if (data.size() < sizeof(FH))
return std::nullopt;
const auto* file_header = reinterpret_cast<const FH*>(data.data());
const auto shoff = static_cast<std::size_t>(file_header->e_shoff);
const auto shnum = static_cast<std::size_t>(file_header->e_shnum);
const auto shstrndx = static_cast<std::size_t>(file_header->e_shstrndx);
const auto shstrtab_hdr_off = shoff + shstrndx * sizeof(SH);
if (shstrtab_hdr_off + sizeof(SH) > data.size())
return std::nullopt;
const auto* shstrtab_hdr = reinterpret_cast<const SH*>(data.data() + shstrtab_hdr_off);
const auto shstrtab_off = static_cast<std::size_t>(shstrtab_hdr->sh_offset);
const auto shstrtab_size = static_cast<std::size_t>(shstrtab_hdr->sh_size);
if (shstrtab_off + shstrtab_size > data.size())
return std::nullopt;
const auto* shstrtab = reinterpret_cast<const char*>(data.data() + shstrtab_off);
for (std::size_t i = 0; i < shnum; ++i)
{
const auto sect_hdr_off = shoff + i * sizeof(SH);
if (sect_hdr_off + sizeof(SH) > data.size())
continue;
const auto* section = reinterpret_cast<const SH*>(data.data() + sect_hdr_off);
if (std::cmp_greater_equal(section->sh_name, shstrtab_size))
continue;
if (std::string_view{shstrtab + section->sh_name} != section_name)
continue;
const auto raw_off = static_cast<std::size_t>(section->sh_offset);
const auto sec_size = static_cast<std::size_t>(section->sh_size);
if (raw_off + sec_size > data.size())
return std::nullopt;
ExtractedSection out;
out.virtual_base_addr = static_cast<std::uintptr_t>(section->sh_addr);
out.raw_base_addr = raw_off;
out.data.assign(data.data() + raw_off, data.data() + raw_off + sec_size);
return out;
}
return std::nullopt;
}
std::optional<ExtractedSection> get_elf_section_by_name_from_memory(const std::span<const std::byte> data,
const std::string_view& section_name)
{
constexpr std::string_view valid_elf_signature = "\x7F"
"ELF";
if (data.size() < ei_nident)
return std::nullopt;
if (std::string_view{reinterpret_cast<const char*>(data.data()), valid_elf_signature.size()}
!= valid_elf_signature)
return std::nullopt;
const auto class_byte = static_cast<uint8_t>(data[ei_class]);
if (class_byte == elfclass64)
return get_elf_section_from_memory_impl<FileArch::x64>(data, section_name);
if (class_byte == elfclass32)
return get_elf_section_from_memory_impl<FileArch::x32>(data, section_name);
return std::nullopt;
}
[[maybe_unused]]
std::optional<ExtractedSection> get_elf_section_by_name(const std::filesystem::path& path,
const std::string_view& section_name)
@@ -322,4 +404,27 @@ namespace omath
.raw_base_addr = pe_section->raw_base_addr,
.target_offset = offset};
}
std::optional<SectionScanResult>
ElfPatternScanner::scan_for_pattern_in_memory_file(const std::span<const std::byte> file_data,
const std::string_view& pattern,
const std::string_view& target_section_name)
{
const auto section = get_elf_section_by_name_from_memory(file_data, target_section_name);
if (!section.has_value()) [[unlikely]]
return std::nullopt;
const auto scan_result =
PatternScanner::scan_for_pattern(section->data.cbegin(), section->data.cend(), pattern);
if (scan_result == section->data.cend())
return std::nullopt;
const auto offset = std::distance(section->data.begin(), scan_result);
return SectionScanResult{.virtual_base_addr = section->virtual_base_addr,
.raw_base_addr = section->raw_base_addr,
.target_offset = offset};
}
} // namespace omath

View File

@@ -5,6 +5,7 @@
#include "omath/utility/pattern_scan.hpp"
#include <cstring>
#include <fstream>
#include <span>
#include <variant>
#include <vector>
@@ -231,6 +232,96 @@ namespace
return std::nullopt;
}
template<typename HeaderType, typename SegmentType, typename SectionType, std::uint32_t segment_cmd>
std::optional<ExtractedSection> extract_section_from_memory_impl(const std::span<const std::byte> data,
const std::string_view& section_name)
{
if (data.size() < sizeof(HeaderType))
return std::nullopt;
const auto* header = reinterpret_cast<const HeaderType*>(data.data());
std::size_t cmd_offset = sizeof(HeaderType);
for (std::uint32_t i = 0; i < header->ncmds; ++i)
{
if (cmd_offset + sizeof(LoadCommand) > data.size())
return std::nullopt;
const auto* lc = reinterpret_cast<const LoadCommand*>(data.data() + cmd_offset);
if (lc->cmd != segment_cmd)
{
cmd_offset += lc->cmdsize;
continue;
}
if (cmd_offset + sizeof(SegmentType) > data.size())
return std::nullopt;
const auto* segment = reinterpret_cast<const SegmentType*>(data.data() + cmd_offset);
if (!segment->nsects)
{
cmd_offset += lc->cmdsize;
continue;
}
std::size_t sect_offset = cmd_offset + sizeof(SegmentType);
for (std::uint32_t j = 0; j < segment->nsects; ++j)
{
if (sect_offset + sizeof(SectionType) > data.size())
return std::nullopt;
const auto* section = reinterpret_cast<const SectionType*>(data.data() + sect_offset);
if (get_section_name(section->sectname) != section_name)
{
sect_offset += sizeof(SectionType);
continue;
}
const auto raw_off = static_cast<std::size_t>(section->offset);
const auto sec_size = static_cast<std::size_t>(section->size);
if (raw_off + sec_size > data.size())
return std::nullopt;
ExtractedSection out;
out.virtual_base_addr = static_cast<std::uintptr_t>(section->addr);
out.raw_base_addr = raw_off;
out.data.assign(data.data() + raw_off, data.data() + raw_off + sec_size);
return out;
}
cmd_offset += lc->cmdsize;
}
return std::nullopt;
}
[[nodiscard]]
std::optional<ExtractedSection> get_macho_section_by_name_from_memory(const std::span<const std::byte> data,
const std::string_view& section_name)
{
if (data.size() < sizeof(std::uint32_t))
return std::nullopt;
std::uint32_t magic{};
std::memcpy(&magic, data.data(), sizeof(magic));
if (magic == mh_magic_64 || magic == mh_cigam_64)
return extract_section_from_memory_impl<MachHeader64, SegmentCommand64, Section64, lc_segment_64>(
data, section_name);
if (magic == mh_magic_32 || magic == mh_cigam_32)
return extract_section_from_memory_impl<MachHeader32, SegmentCommand32, Section32, lc_segment>(data,
section_name);
return std::nullopt;
}
[[nodiscard]]
std::optional<ExtractedSection> get_macho_section_by_name(const std::filesystem::path& path,
const std::string_view& section_name)
@@ -346,4 +437,27 @@ namespace omath
.raw_base_addr = macho_section->raw_base_addr,
.target_offset = offset};
}
std::optional<SectionScanResult>
MachOPatternScanner::scan_for_pattern_in_memory_file(const std::span<const std::byte> file_data,
const std::string_view& pattern,
const std::string_view& target_section_name)
{
const auto section = get_macho_section_by_name_from_memory(file_data, target_section_name);
if (!section.has_value()) [[unlikely]]
return std::nullopt;
const auto scan_result =
PatternScanner::scan_for_pattern(section->data.cbegin(), section->data.cend(), pattern);
if (scan_result == section->data.cend())
return std::nullopt;
const auto offset = std::distance(section->data.begin(), scan_result);
return SectionScanResult{.virtual_base_addr = section->virtual_base_addr,
.raw_base_addr = section->raw_base_addr,
.target_offset = offset};
}
} // namespace omath

View File

@@ -7,6 +7,7 @@
#include <span>
#include <stdexcept>
#include <variant>
#include <vector>
// Internal PE shit defines
// Big thx for linuxpe sources as ref
@@ -244,6 +245,78 @@ namespace
std::vector<std::byte> data;
};
[[nodiscard]]
std::optional<ExtractedSection> extract_section_from_pe_memory(const std::span<const std::byte> data,
const std::string_view& section_name)
{
if (data.size() < sizeof(DosHeader))
return std::nullopt;
const auto* dos_header = reinterpret_cast<const DosHeader*>(data.data());
if (invalid_dos_header_file(*dos_header))
return std::nullopt;
const auto nt_off = static_cast<std::size_t>(dos_header->e_lfanew);
if (nt_off + sizeof(ImageNtHeaders<NtArchitecture::x32_bit>) > data.size())
return std::nullopt;
const auto* x86_hdrs =
reinterpret_cast<const ImageNtHeaders<NtArchitecture::x32_bit>*>(data.data() + nt_off);
NtHeaderVariant nt_headers;
if (x86_hdrs->optional_header.magic == opt_hdr32_magic)
nt_headers = *x86_hdrs;
else if (x86_hdrs->optional_header.magic == opt_hdr64_magic)
{
if (nt_off + sizeof(ImageNtHeaders<NtArchitecture::x64_bit>) > data.size())
return std::nullopt;
nt_headers = *reinterpret_cast<const ImageNtHeaders<NtArchitecture::x64_bit>*>(data.data() + nt_off);
}
else
return std::nullopt;
if (invalid_nt_header_file(nt_headers))
return std::nullopt;
return std::visit(
[&data, &section_name, nt_off](const auto& concrete_headers) -> std::optional<ExtractedSection>
{
constexpr std::size_t sig_size = sizeof(concrete_headers.signature);
const auto section_table_off = nt_off + sig_size + sizeof(FileHeader)
+ concrete_headers.file_header.size_optional_header;
for (std::size_t i = 0; i < concrete_headers.file_header.num_sections; ++i)
{
const auto sh_off = section_table_off + i * sizeof(SectionHeader);
if (sh_off + sizeof(SectionHeader) > data.size())
return std::nullopt;
const auto* section = reinterpret_cast<const SectionHeader*>(data.data() + sh_off);
if (std::string_view(section->name) != section_name)
continue;
const auto raw_off = static_cast<std::size_t>(section->ptr_raw_data);
const auto raw_size = static_cast<std::size_t>(section->size_raw_data);
if (raw_off + raw_size > data.size())
return std::nullopt;
std::vector<std::byte> section_data(data.data() + raw_off, data.data() + raw_off + raw_size);
return ExtractedSection{
.virtual_base_addr = static_cast<std::uintptr_t>(
section->virtual_address + concrete_headers.optional_header.image_base),
.raw_base_addr = raw_off,
.data = std::move(section_data)};
}
return std::nullopt;
},
nt_headers);
}
[[nodiscard]]
std::optional<ExtractedSection> extract_section_from_pe_file(const std::filesystem::path& path_to_file,
const std::string_view& section_name)
@@ -383,4 +456,27 @@ namespace omath
.raw_base_addr = pe_section->raw_base_addr,
.target_offset = offset};
}
std::optional<SectionScanResult>
PePatternScanner::scan_for_pattern_in_memory_file(const std::span<const std::byte> file_data,
const std::string_view& pattern,
const std::string_view& target_section_name)
{
const auto pe_section = extract_section_from_pe_memory(file_data, target_section_name);
if (!pe_section.has_value()) [[unlikely]]
return std::nullopt;
const auto scan_result =
PatternScanner::scan_for_pattern(pe_section->data.cbegin(), pe_section->data.cend(), pattern);
if (scan_result == pe_section->data.cend())
return std::nullopt;
const auto offset = std::distance(pe_section->data.begin(), scan_result);
return SectionScanResult{.virtual_base_addr = pe_section->virtual_base_addr,
.raw_base_addr = pe_section->raw_base_addr,
.target_offset = offset};
}
} // namespace omath