### CMake Project Setup and Interface Library Configuration Source: https://github.com/can1357/linux-pe/blob/master/CMakeLists.txt This CMake script initializes the project, defines it as a header-only interface library, and sets the required include directories. It also enforces C++20 compilation standards. ```cmake cmake_minimum_required(VERSION 3.17) project(linux-pe) # Header only interface. add_library(${PROJECT_NAME} INTERFACE) target_include_directories(${PROJECT_NAME} INTERFACE includes) # C++20 requirement. target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED true) ``` -------------------------------- ### Convert RVA to File Offset and Pointer (C++) Source: https://context7.com/can1357/linux-pe/llms.txt Demonstrates how to convert between Relative Virtual Addresses (RVA) and raw file offsets using the `rva_to_ptr`, `rva_to_fo`, and `fo_to_rva` functions. Includes boundary checking for RVA to pointer conversions and accessing the DOS header. Requires a loaded PE image object. ```cpp #include #include // Assuming img is loaded as win::image_x64_t* // Convert RVA to pointer (for raw file view) uint32_t rva = 0x2000; auto* ptr = img->rva_to_ptr(rva, 4); // length=4 for boundary check if (ptr) { std::cout << "Data at RVA 0x" << std::hex << rva << ": "; for (int i = 0; i < 4; i++) { std::cout << std::hex << (int)ptr[i] << " "; } std::cout << std::endl; } else { std::cout << "RVA 0x" << std::hex << rva << " is invalid or out of bounds" << std::endl; } // Convert RVA to file offset uint32_t file_offset = img->rva_to_fo(rva); if (file_offset != win::img_npos) { std::cout << "RVA 0x" << std::hex << rva << " -> File offset 0x" << file_offset << std::endl; } // Convert file offset to RVA (for mapped view) uint32_t offset = 0x400; uint32_t result_rva = img->fo_to_rva(offset); if (result_rva != win::img_npos) { std::cout << "File offset 0x" << std::hex << offset << " -> RVA 0x" << result_rva << std::endl; } // Raw offset to pointer (no boundary checks by default) auto* raw_ptr = img->raw_to_ptr(0); std::cout << "DOS magic: 0x" << std::hex << raw_ptr->e_magic << std::endl; ``` -------------------------------- ### Process PE Base Relocations Source: https://context7.com/can1357/linux-pe/llms.txt This C++ snippet enumerates and applies base relocations to adjust addresses within a PE image. It iterates through relocation blocks and entries, identifying relocation types and applying necessary adjustments, particularly for IMAGE_REL_BASED_DIR64. Dependencies include the linuxpe library and iostream for output. It takes a loaded PE image as input and outputs information about the relocation process. ```cpp #include #include // Assuming img is loaded as win::image_x64_t* // Get relocation directory auto* reloc_dir_entry = img->get_directory(win::directory_entry_basereloc); if (!reloc_dir_entry || !reloc_dir_entry->present()) { std::cout << "No relocations found" << std::endl; return; } auto* reloc_dir = img->rva_to_ptr(reloc_dir_entry->rva); if (!reloc_dir) { std::cout << "Invalid relocation directory" << std::endl; return; } // Iterate through relocation blocks auto* block = &reloc_dir->first_block; size_t total_limit = reloc_dir_entry->size; size_t processed = 0; while (processed < total_limit && block->size_block > 0) { std::cout << "Relocation block at RVA 0x" << std::hex << block->base_rva << std::endl; std::cout << " Block size: " << std::dec << block->size_block << " bytes" << std::endl; std::cout << " Number of entries: " << block->num_entries() << std::endl; // Process each relocation entry for (const auto& entry : *block) { if (entry.type != win::rel_based_absolute) { uint32_t rva = block->base_rva + entry.offset; std::cout << " Type " << entry.type << " at RVA 0x" << std::hex << rva << std::endl; // Apply relocation (example for 64-bit) if (entry.type == win::rel_based_dir64) { auto* target = img->rva_to_ptr(rva); if (target) { // *target += (new_base - old_base); // Actual relocation logic } } } } processed += block->size_block; block = block->next(); } ``` -------------------------------- ### Calculate and Verify PE Checksum Source: https://context7.com/can1357/linux-pe/llms.txt This C++ code snippet demonstrates how to compute, verify, and update the PE optional header checksum for a given PE image. It reads a PE file into a buffer, calculates the checksum using the image size, compares it with the stored checksum, and optionally updates it. Dependencies include linuxpe, iostream, fstream, and vector. Inputs are a file path and the PE image data. Outputs include checksum values and validation status. ```cpp #include #include #include #include // Load PE file std::ifstream file("example.exe", std::ios::binary); std::vector buffer((std::istreambuf_iterator(file)), {}); file.close(); size_t file_size = buffer.size(); auto* img = reinterpret_cast(buffer.data()); // Get stored checksum uint32_t stored_checksum = img->get_nt_headers()->optional_header.checksum; std::cout << "Stored checksum: 0x" << std::hex << stored_checksum << std::endl; // Compute actual checksum uint32_t computed_checksum = img->compute_checksum(file_size); std::cout << "Computed checksum: 0x" << std::hex << computed_checksum << std::endl; // Verify checksum if (stored_checksum == computed_checksum) { std::cout << "Checksum is valid" << std::endl; } else { std::cout << "Checksum mismatch!" << std::endl; } // Update checksum in memory img->update_checksum(file_size); std::cout << "Updated checksum: 0x" << std::hex << img->get_nt_headers()->optional_header.checksum << std::endl; // Write back to file if needed std::ofstream out("example_fixed.exe", std::ios::binary); out.write(reinterpret_cast(buffer.data()), buffer.size()); out.close(); ``` -------------------------------- ### Parse COFF Object File Header, Sections, and Symbols in C++ Source: https://context7.com/can1357/linux-pe/llms.txt This C++ code snippet demonstrates how to load and parse a COFF object file (.obj) using the linux-pe library. It accesses the file header, enumerates sections by name and size, and iterates through symbols, retrieving their names from either short names or the string table. Dependencies include ``, ``, ``, and ``. The input is a binary file 'example.obj', and the output is printed to standard output. ```cpp #include #include #include #include // Load COFF object file std::ifstream file("example.obj", std::ios::binary); std::vector buffer((std::istreambuf_iterator(file)), {}); file.close(); auto* coff = reinterpret_cast(buffer.data()); // Access file header std::cout << "Machine: 0x" << std::hex << (int)coff->file_header.machine << std::endl; std::cout << "Number of sections: " << coff->file_header.num_sections << std::endl; std::cout << "Number of symbols: " << coff->file_header.num_symbols << std::endl; // Enumerate sections for (size_t i = 0; i < coff->file_header.num_sections; i++) { auto* section = coff->get_section(i); char name[9] = {0}; memcpy(name, section->name.short_name, 8); std::cout << "Section: " << name << std::endl; std::cout << " Size: " << section->size_raw_data << " bytes" << std::endl; std::cout << " Relocations: " << section->num_relocs << std::endl; } // Enumerate symbols auto* string_table = coff->get_strings(); for (size_t i = 0; i < coff->file_header.num_symbols; i++) { auto* symbol = coff->get_symbol(i); // Get symbol name (either short name or from string table) const char* sym_name; if (symbol->name.short_name[0] == 0 && *(uint32_t*)symbol->name.short_name == 0) { uint32_t offset = *(uint32_t*)&symbol->name.short_name[4]; sym_name = string_table->get_string(offset); } else { static char short_name[9]; memcpy(short_name, symbol->name.short_name, 8); short_name[8] = 0; sym_name = short_name; } std::cout << "Symbol: " << sym_name << " (section: " << symbol->section_index << ", value: 0x" << std::hex << symbol->value << ")" << std::endl; // Skip auxiliary symbols i += symbol->num_auxiliary; } ``` -------------------------------- ### Enumerate and Analyze PE Sections in C++ Source: https://context7.com/can1357/linux-pe/llms.txt Iterates through all sections of a loaded PE file, printing their names, virtual addresses, sizes, and characteristics like executability, readability, and writability. It also demonstrates how to find a specific section by its Relative Virtual Address (RVA). This snippet is useful for understanding the memory layout and properties of PE sections. ```cpp #include #include #include // Assuming img is already loaded as win::image_x64_t* auto* nt_headers = img->get_nt_headers(); // Iterate sections using range-based for loop for (const auto& section : nt_headers->sections()) { // Extract section name (8-byte fixed string) char name[9] = {0}; memcpy(name, section.name.short_name, 8); std::cout << "Section: " << name << std::endl; std::cout << " Virtual Address: 0x" << std::hex << section.virtual_address << std::endl; std::cout << " Virtual Size: 0x" << section.virtual_size << std::endl; std::cout << " Raw Data Offset: 0x" << section.ptr_raw_data << std::endl; std::cout << " Raw Data Size: 0x" << section.size_raw_data << std::endl; // Check section characteristics auto& chars = section.characteristics; std::cout << " Executable: " << chars.mem_execute << std::endl; std::cout << " Readable: " << chars.mem_read << std::endl; std::cout << " Writable: " << chars.mem_write << std::endl; std::cout << " Contains Code: " << chars.cnt_code << std::endl; std::cout << " Alignment: " << chars.get_alignment() << " bytes" << std::endl; } // Find specific section by RVA uint32_t target_rva = 0x1000; auto* section = img->rva_to_section(target_rva); if (section) { char name[9] = {0}; memcpy(name, section->name.short_name, 8); std::cout << "RVA 0x" << std::hex << target_rva << " is in section: " << name << std::endl; } ``` -------------------------------- ### Access Import Directory and Functions (C++) Source: https://context7.com/can1357/linux-pe/llms.txt Parses the import directory of a PE file to list imported DLLs and their functions. Handles both name-based and ordinal imports. Requires a loaded PE image object and checks for the presence of the import directory. ```cpp #include #include // Assuming img is loaded as win::image_x64_t* // Get import directory auto* import_dir = img->get_directory(win::directory_entry_import); if (!import_dir || !import_dir->present()) { std::cout << "No import directory found" << std::endl; return; } // Parse import descriptors auto* import_desc = img->rva_to_ptr(import_dir->rva); while (import_desc && import_desc->rva_name != 0) { // Get DLL name auto* dll_name = img->rva_to_ptr(import_desc->rva_name); if (dll_name) { std::cout << "Imports from: " << dll_name << std::endl; // Parse import names/ordinals uint32_t thunk_rva = import_desc->rva_original_first_thunk ? import_desc->rva_original_first_thunk : import_desc->rva_first_thunk; auto* thunk = img->rva_to_ptr(thunk_rva); // Use uint64_t for x64 while (thunk && *thunk != 0) { if (*thunk & 0x8000000000000000ULL) { // Import by ordinal uint16_t ordinal = *thunk & 0xFFFF; std::cout << " Ordinal: " << ordinal << std::endl; } else { // Import by name auto* import_name = img->rva_to_ptr(*thunk); // Hint is uint16_t if (import_name) { char* func_name = (char*)(import_name + 1); std::cout << " Function: " << func_name << std::endl; } } thunk++; } } import_desc++; } ``` -------------------------------- ### Parse PE Image and Access Headers in C++ Source: https://context7.com/can1357/linux-pe/llms.txt Loads a PE file into memory and accesses its DOS header, file header, NT headers, and optional header. It verifies the magic numbers for DOS and NT headers and prints key properties like machine type, number of sections, entry point, and image base. This snippet demonstrates fundamental PE file structure access. ```cpp #include #include #include #include // Load PE file into memory std::ifstream file("example.exe", std::ios::binary); std::vector buffer((std::istreambuf_iterator(file)), {}); file.close(); // Cast to PE image structure auto* img = reinterpret_cast(buffer.data()); // Verify DOS and NT headers if (img->dos_header.e_magic != win::DOS_HDR_MAGIC) { std::cerr << "Invalid DOS signature" << std::endl; return 1; } auto* nt_headers = img->get_nt_headers(); if (nt_headers->signature != win::NT_HDR_MAGIC) { std::cerr << "Invalid NT signature" << std::endl; return 1; } // Access file header properties auto* file_header = img->get_file_header(); std::cout << "Machine: 0x" << std::hex << (int)file_header->machine << std::endl; std::cout << "Number of sections: " << file_header->num_sections << std::endl; std::cout << "Timestamp: " << file_header->timedate_stamp << std::endl; // Access optional header auto& opt_header = nt_headers->optional_header; std::cout << "Entry point RVA: 0x" << std::hex << opt_header.entry_point << std::endl; std::cout << "Image base: 0x" << opt_header.image_base << std::endl; std::cout << "Subsystem: " << (int)opt_header.subsystem << std::endl; ``` -------------------------------- ### Access Export Directory and Functions (C++) Source: https://context7.com/can1357/linux-pe/llms.txt Extracts information from the export directory of a PE file, including module name, base ordinal, and details of exported functions, variables, and forwarded exports. Requires a loaded PE image object and checks for the export directory's presence and validity. ```cpp #include #include #include // Assuming img is loaded as win::image_x64_t* // Get export directory auto* export_dir_entry = img->get_directory(win::directory_entry_export); if (!export_dir_entry || !export_dir_entry->present()) { std::cout << "No export directory found" << std::endl; return; } auto* export_dir = img->rva_to_ptr(export_dir_entry->rva); if (!export_dir) { std::cout << "Invalid export directory" << std::endl; return; } // Get module name auto* module_name = img->rva_to_ptr(export_dir->name); std::cout << "Module: " << (module_name ? module_name : "unknown") << std::endl; std::cout << "Number of functions: " << export_dir->num_functions << std::endl; std::cout << "Number of names: " << export_dir->num_names << std::endl; std::cout << "Base ordinal: " << export_dir->base << std::endl; // Parse exported functions auto* functions = img->rva_to_ptr(export_dir->rva_functions); auto* names = img->rva_to_ptr(export_dir->rva_names); auto* ordinals = img->rva_to_ptr(export_dir->rva_name_ordinals); for (uint32_t i = 0; i < export_dir->num_names; i++) { auto* func_name = img->rva_to_ptr(names[i]); uint16_t ordinal = ordinals[i]; uint32_t func_rva = functions[ordinal]; std::cout << "Export #" << (ordinal + export_dir->base) << ": " << (func_name ? func_name : "") << " @ RVA 0x" << std::hex << func_rva << std::endl; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.