WIP Patch
This commit is contained in:
parent
c854b78e02
commit
72c6656e01
|
@ -116,14 +116,6 @@ struct Patcher {
|
|||
availableSpace++;
|
||||
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;
|
||||
}
|
||||
|
@ -189,15 +181,34 @@ struct Patcher {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool processRelocations(std::vector<uint8_t> &newTextData,
|
||||
std::vector<uint8_t> &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<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...");
|
||||
|
||||
|
@ -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<uint32_t *>(newTextData.data() + patchOffset) =
|
||||
resolvedAddress;
|
||||
uint32_t patchOffset = relocRVA - textSection->get_virtual_address();
|
||||
uint32_t *ptr =
|
||||
reinterpret_cast<uint32_t *>(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<uint8_t> newTextData(
|
||||
reinterpret_cast<const uint8_t *>(textSectionData),
|
||||
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);
|
||||
char *dstText = const_cast<char *>(textSectionData) + textInjectionOffset;
|
||||
char *dstRdata = const_cast<char *>(rdataData) + rdataInjectionOffset;
|
||||
|
||||
// Copy main function code
|
||||
const uint8_t *mainCode =
|
||||
reinterpret_cast<const uint8_t *>(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<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 "
|
||||
"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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue