Adds PE file header definitions

Defines `DosHeader` and `FileHeader` structures to represent PE file header information.
Includes definitions for `MachineId` enum and `FileCharacteristics` union.
These definitions are prerequisite for PE file parsing and analysis.
This commit is contained in:
2025-10-07 11:19:43 +03:00
parent d64c7ad756
commit d84259fdcc
4 changed files with 115 additions and 3 deletions

View File

@@ -0,0 +1,32 @@
//
// Created by Vlad on 10/7/2025.
//
#pragma once
#include <cstdint>
namespace omath::system::pe
{
struct DosHeader
{
std::uint16_t e_magic;
std::uint16_t e_cblp;
std::uint16_t e_cp;
std::uint16_t e_crlc;
std::uint16_t e_cparhdr;
std::uint16_t e_minalloc;
std::uint16_t e_maxalloc;
std::uint16_t e_ss;
std::uint16_t e_sp;
std::uint16_t e_csum;
std::uint16_t e_ip;
std::uint16_t e_cs;
std::uint16_t e_lfarlc;
std::uint16_t e_ovno;
std::uint16_t e_res[4];
std::uint16_t e_oemid;
std::uint16_t e_oeminfo;
std::uint16_t e_res2[10];
std::uint32_t e_lfanew;
};
}

View File

@@ -0,0 +1,77 @@
//
// Created by Vlad on 10/7/2025.
//
#pragma once
#include <cstdint>
enum class MachineId : std::uint16_t
{
UNKNOWN = 0x0000,
TARGET_HOST = 0x0001, // Useful for indicating we want to interact with the host and not a WoW guest.
I386 = 0x014C, // Intel 386.
R3000 = 0x0162, // MIPS little-endian, 0x160 big-endian
R4000 = 0x0166, // MIPS little-endian
R10000 = 0x0168, // MIPS little-endian
WCEMIPSV2 = 0x0169, // MIPS little-endian WCE v2
ALPHA = 0x0184, // Alpha_AXP
SH3 = 0x01A2, // SH3 little-endian
SH3DSP = 0x01A3,
SH3E = 0x01A4, // SH3E little-endian
SH4 = 0x01A6, // SH4 little-endian
SH5 = 0x01A8, // SH5
ARM = 0x01C0, // ARM Little-Endian
THUMB = 0x01C2, // ARM Thumb/Thumb-2 Little-Endian
ARMNT = 0x01C4, // ARM Thumb-2 Little-Endian
AM33 = 0x01D3,
POWERPC = 0x01F0, // IBM PowerPC Little-Endian
POWERPCP = 0x01F1,
IA64 = 0x0200, // Intel 64
MIPS16 = 0x0266, // MIPS
ALPHA64 = 0x0284, // ALPHA64
MIPSFPU = 0x0366, // MIPS
MIPSFPU16 = 0x0466, // MIPS
AXP64 = 0x0284,
TRICORE = 0x0520, // Infineon
CEF = 0x0CEF,
EBC = 0x0EBC, // EFI Byte Code
AMD64 = 0x8664, // AMD64 (K8)
M32R = 0x9041, // M32R little-endian
ARM64 = 0xAA64, // ARM64 Little-Endian
CEE = 0xC0EE,
};
union FileCharacteristics
{
std::uint16_t flags;
struct
{
std::uint16_t relocs_stripped : 1; // Relocation info stripped from file.
std::uint16_t executable : 1; // File is executable (i.e. no unresolved external references).
std::uint16_t lines_stripped : 1; // Line nunbers stripped from file.
std::uint16_t local_symbols_stripped : 1; // Local symbols stripped from file.
std::uint16_t aggressive_ws_trim : 1; // Aggressively trim working set
std::uint16_t large_address_aware : 1; // App can handle >2gb addresses
std::uint16_t _pad0 : 1;
std::uint16_t bytes_reversed_lo : 1; // Bytes of machine word are reversed.
std::uint16_t machine_32 : 1; // 32 bit word machine.
std::uint16_t debug_stripped : 1; // Debugging info stripped from file in .DBG file
std::uint16_t runnable_from_swap : 1; // If Image is on removable media, copy and run from the swap file.
std::uint16_t net_run_from_swap : 1; // If Image is on Net, copy and run from the swap file.
std::uint16_t system_file : 1; // System File.
std::uint16_t dll_file : 1; // File is a DLL.
std::uint16_t up_system_only : 1; // File should only be run on a UP machine
std::uint16_t bytes_reversed_hi : 1; // Bytes of machine word are reversed.
};
};
struct FileHeader
{
MachineId machine;
uint16_t num_sections;
uint32_t timedate_stamp;
uint32_t ptr_symbols;
uint32_t num_symbols;
uint16_t size_optional_header;
FileCharacteristics characteristics;
};

View File

@@ -62,7 +62,7 @@ namespace omath
PePatternScanner::extract_section_from_pe_file(const std::filesystem::path& path_to_file, PePatternScanner::extract_section_from_pe_file(const std::filesystem::path& path_to_file,
const std::string_view& section_name) const std::string_view& section_name)
{ {
std::ifstream file(path_to_file, std::ios::binary); std::fstream file(path_to_file, std::ios::binary | std::ios::in);
if (!file.is_open()) [[unlikely]] if (!file.is_open()) [[unlikely]]
return std::nullopt; return std::nullopt;

View File

@@ -1,11 +1,11 @@
// //
// Created by Vlad on 10/4/2025. // Created by Vlad on 10/4/2025.
// //
#include "omath/utility/pe_pattern_scan.hpp"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include <omath/utility/pattern_scan.hpp> #include <omath/utility/pattern_scan.hpp>
#include <source_location> #include <source_location>
TEST(unit_test_pattern_scan, read_test) TEST(unit_test_pattern_scan, read_test)
{ {
const auto result = omath::PatternScanner::parse_pattern("FF ? ?? E9"); const auto result = omath::PatternScanner::parse_pattern("FF ? ?? E9");
@@ -49,6 +49,9 @@ TEST(unit_test_pattern_scan, corner_case_3)
TEST(unit_test_pattern_scan, corner_case_4) TEST(unit_test_pattern_scan, corner_case_4)
{ {
const auto result = omath::PatternScanner::parse_pattern("X ? ?? E9 "); const auto result = omath::PatternScanner::parse_pattern("X ? ?? E9 ");
const auto result2 = omath::PePatternScanner::scan_for_pattern_in_file(
std::filesystem::path{
"C:\\Users\\Vlad\\CLionProjects\\l4bhop\\cmake-build\\build\\windows-release\\l4bhop.dll"},
"4C 8B D1 B8 ? ? ? ? F6 04 25 ? ? ? ? ? 75 ? 0F 05 C3");
EXPECT_FALSE(result.has_value()); EXPECT_FALSE(result.has_value());
} }