WIP Patch

This commit is contained in:
Guus Waals 2025-06-06 19:46:03 +08:00
parent c854b78e02
commit 72c6656e01
1 changed files with 52 additions and 48 deletions

View File

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