diff --git a/patcher/patcher.cpp b/patcher/patcher.cpp index c916ca42..5fda441a 100644 --- a/patcher/patcher.cpp +++ b/patcher/patcher.cpp @@ -108,7 +108,7 @@ struct Patcher { uint32_t availableSpace = 0; // Search backwards from the end to find contiguous null bytes - const char *ptr = sectionEnd-1; + const char *ptr = sectionEnd - 1; while (ptr > sectionData) { if (*ptr != 0x00) { break; @@ -116,14 +116,6 @@ struct Patcher { availableSpace++; ptr--; } - // } - // for (int32_t i = sectionSize - 1; i >= 0; i--) { - // if (reinterpret_cast(sectionData)[i] == 0x00) { - // availableSpace++; - // } else { - // break; // Found non-null byte, stop counting - // } - // } return availableSpace; } @@ -189,15 +181,34 @@ struct Patcher { return true; } - bool processRelocations(std::vector &newTextData, - std::vector &newRdataData, - uint32_t injectionOffset, - uint32_t &rdataCurrentOffset) { + // Tries to find an import in the input PE file + void findImportInPE(std::string_view name) { + auto &imports = peReader.get_imports(); + for (auto &import : imports) { + if (import.get_name() == name) { + spdlog::info("Found import: {}", name); + return; + } + } + spdlog::error("Could not find import: {}", name); + } + + bool processRelocations(char *textStart, char *textEnd, char *&rdataPtr) { auto &symbols = *objReader.get_symbols(); auto §ions = objReader.get_sections(); auto §ionRelocations = mainSection->get_relocations(); uint32_t rdataSize = rdataSection->get_data_size(); - uint32_t rdataRVA = rdataSection->get_virtual_address(); + char *textSectionStart = const_cast(textSection->get_data()); + const char *textSectionEnd = + textSectionStart + textSection->get_data_size(); + const char *rdataEndPtr = rdataSection->get_data() + rdataSize; + char *rdataStart = const_cast(rdataSection->get_data()); + // char* rdataEndPtr = rdataPtr + rdataSize; + + size_t textStartRVA = + (textStart - textSectionStart) + textSection->get_virtual_address(); + size_t textEndRVA = + (textEnd - textSectionStart) + textSection->get_virtual_address(); spdlog::info("Processing relocations..."); @@ -205,12 +216,12 @@ struct Patcher { if (reloc.get_type() != 6) continue; // Only handle type 6 (IMAGE_REL_I386_DIR32) - uint32_t relocOffset = reloc.get_virtual_address(); + uint32_t relocRVA = reloc.get_virtual_address() + textStartRVA; std::string symbolName = reloc.get_symbol(); uint32_t resolvedAddress = 0; - spdlog::info("Processing relocation at offset 0x{:x} for symbol: {}", - relocOffset, symbolName); + spdlog::info("Processing relocation at VA 0x{:x} for symbol: {}", + relocRVA + imageBase, symbolName); if (symbolName.starts_with("__imp_")) { // Import symbol handling @@ -247,31 +258,33 @@ struct Patcher { } stringLen++; // Include null terminator - if (rdataCurrentOffset + stringLen > rdataSize) { + if (rdataPtr + stringLen > rdataEndPtr) { spdlog::error("Not enough space in .rdata for string constant"); return false; } // Copy string to .rdata - std::memcpy(newRdataData.data() + rdataCurrentOffset, - constData + constOffset, stringLen); + std::memcpy(rdataPtr, constData + constOffset, stringLen); - resolvedAddress = imageBase + rdataRVA + rdataCurrentOffset; + size_t rdataRVA = + (rdataPtr - rdataStart) + rdataSection->get_virtual_address(); + resolvedAddress = imageBase + rdataRVA; spdlog::info("Copied string constant '{}' to .rdata at RVA 0x{:x} " "(VA: 0x{:x})", - std::string(constData + constOffset), - rdataRVA + rdataCurrentOffset, resolvedAddress); + std::string(constData + constOffset), rdataRVA, + resolvedAddress); - rdataCurrentOffset += stringLen; + rdataPtr += stringLen; } } // Apply the relocation if (resolvedAddress != 0) { - uint32_t patchOffset = injectionOffset + relocOffset; - *reinterpret_cast(newTextData.data() + patchOffset) = - resolvedAddress; + uint32_t patchOffset = relocRVA - textSection->get_virtual_address(); + uint32_t *ptr = + reinterpret_cast(textSectionStart + patchOffset); + ptr[0] = resolvedAddress; spdlog::info( "Applied relocation: patched offset 0x{:x} with address 0x{:x}", patchOffset, resolvedAddress); @@ -302,45 +315,36 @@ struct Patcher { // Calculate injection points uint32_t textSize = textSection->get_data_size(); uint32_t rdataSize = rdataSection->get_data_size(); - uint32_t injectionOffset = textSize - textAvailableSpace; + uint32_t textInjectionOffset = textSize - textAvailableSpace; uint32_t rdataInjectionOffset = rdataSize - rdataAvailableSpace; - uint32_t rdataCurrentOffset = rdataInjectionOffset; - uint64_t textSectionVA = imageBase + textSection->get_virtual_address(); - uint64_t injectionVA = textSectionVA + injectionOffset; + uint64_t textInjectionRVA = + textSection->get_virtual_address() + textInjectionOffset; + uint64_t rdataInjectionRVA = + rdataSection->get_virtual_address() + rdataInjectionOffset; spdlog::info( "Injecting {} bytes at .text section offset 0x{:x} (VA: 0x{:x})", - mainSize, injectionOffset, injectionVA); + mainSize, textInjectionOffset, textInjectionRVA + imageBase); // Create copies of section data auto textSectionData = textSection->get_data(); auto rdataData = rdataSection->get_data(); - std::vector newTextData( - reinterpret_cast(textSectionData), - reinterpret_cast(textSectionData) + textSize); - std::vector newRdataData( - reinterpret_cast(rdataData), - reinterpret_cast(rdataData) + rdataSize); + char *dstText = const_cast(textSectionData) + textInjectionOffset; + char *dstRdata = const_cast(rdataData) + rdataInjectionOffset; // Copy main function code const uint8_t *mainCode = reinterpret_cast(mainSection->get_data()) + mainOffset; - std::memcpy(newTextData.data() + injectionOffset, mainCode, mainSize); + std::memcpy(dstText, mainCode, mainSize); // Process relocations - if (!processRelocations(newTextData, newRdataData, injectionOffset, - rdataCurrentOffset)) { + char *rdataPtr = dstRdata; + if (!processRelocations(dstText, dstText + mainSize, rdataPtr)) { return false; } - // Update sections - rdataSection->set_data(reinterpret_cast(newRdataData.data()), - newRdataData.size()); - textSection->set_data(reinterpret_cast(newTextData.data()), - newTextData.size()); - spdlog::info("Injected code into existing .text section space (size " "unchanged: 0x{:x})", textSize); @@ -354,7 +358,7 @@ struct Patcher { spdlog::info( "Successfully patched PE file! Main function injected at VA: 0x{:x}", - injectionVA); + textInjectionRVA + imageBase); return true; }