#include #include #include #include int main(int argc, char *argv[]) { CLI::App app("Patcher"); std::string inputFile; std::string outputFile; app.add_option("-i,--input", inputFile, "Input exe file to patch") ->required(); app.add_option("-o,--output", outputFile, "Output patched exe file") ->required(); CLI11_PARSE(app, argc, argv); // Load the object file containing the main function COFFI::coffi objReader; std::string objPath = SRC_OBJECT; SPDLOG_INFO("Loading object file: {}", objPath); if (!objReader.load(objPath)) { spdlog::error("Failed to load object file: {}", objPath); return 1; } // Load the source PE file COFFI::coffi peReader; SPDLOG_INFO("Loading PE file: {}", inputFile); if (!peReader.load(inputFile)) { spdlog::error("Failed to load PE file: {}", inputFile); return 1; } // Find the 'main' function in the object file auto &symbols = *objReader.get_symbols(); COFFI::symbol *mainSymbol = nullptr; for (auto &sym : symbols) { SPDLOG_INFO("Symbol: {}", sym.get_name()); if (sym.get_name() == "_ref") { mainSymbol = &sym; break; } } if (!mainSymbol) { spdlog::error("Could not find 'main' symbol in object file"); return 1; } // Get the section containing the main function auto §ions = objReader.get_sections(); auto mainSection = sections[mainSymbol->get_section_number() - 1]; // Calculate main function size using next symbol method uint32_t mainOffset = mainSymbol->get_value(); uint32_t mainSize = 0; // Find the next symbol in the same section to calculate size uint32_t nextSymbolOffset = UINT32_MAX; for (auto &sym : symbols) { if (sym.get_section_number() == mainSymbol->get_section_number() && sym.get_value() > mainOffset && sym.get_value() < nextSymbolOffset) { nextSymbolOffset = sym.get_value(); } } if (nextSymbolOffset != UINT32_MAX) { mainSize = nextSymbolOffset - mainOffset; spdlog::info( "Calculated main function size: {} bytes (next symbol at offset {})", mainSize, nextSymbolOffset); } else { // If no next symbol found, use remaining section size mainSize = mainSection->get_data_size() - mainOffset; spdlog::info("No next symbol found, using remaining section size: {} bytes", mainSize); } auto mainCodeData = mainSection->get_data(); spdlog::info("Found main function at offset {} with size {}", mainOffset, mainSize); // List relocations for the main function section auto& sectionRelocations = mainSection->get_relocations(); spdlog::info("Relocations for section {} (containing main function):", mainSymbol->get_section_number()); for (auto& reloc : sectionRelocations) { spdlog::info(" Relocation at offset 0x{:x}, type: {}, symbol index: {}", reloc.get_virtual_address(), reloc.get_type(), reloc.get_symbol_table_index()); // Get symbol name for this relocation spdlog::info(" -> Symbol: {}", reloc.get_symbol()); } spdlog::info("Main function code:"); std::string s; for (uint32_t i = 0; i < mainSize; i++) { if (i > 0 && i % 16 == 0) { spdlog::info("{}", s); s.clear(); } if (s.size() > 0) s += " "; s += fmt::format("{:02X}", mainCodeData[i]); } if (s.size() > 0) spdlog::info("{}", s); // Find .text section in PE file auto &peSections = peReader.get_sections(); COFFI::section *textSection = nullptr; for (auto §ion : peSections) { if (section->get_name() == ".text") { textSection = section; break; } } if (!textSection) { spdlog::error("Could not find .text section in PE file"); return 1; } // Get image base and calculate actual VA uint64_t imageBase = 0; auto winHeader = peReader.get_win_header(); if (winHeader) { imageBase = winHeader->get_image_base(); } uint32_t textSectionRVA = textSection->get_virtual_address(); uint32_t textSectionSize = textSection->get_virtual_size(); uint64_t textSectionVA = imageBase + textSectionRVA; uint64_t textSectionEndVA = textSectionVA + textSectionSize; spdlog::info("PE Image base: 0x{:x}", imageBase); spdlog::info(".text section RVA: 0x{:x}, size: 0x{:x}", textSectionRVA, textSectionSize); spdlog::info(".text section VA: 0x{:x} - 0x{:x}", textSectionVA, textSectionEndVA); return 0; }