WIP Patch
This commit is contained in:
parent
c854b78e02
commit
72c6656e01
|
@ -108,7 +108,7 @@ struct Patcher {
|
||||||
uint32_t availableSpace = 0;
|
uint32_t availableSpace = 0;
|
||||||
|
|
||||||
// Search backwards from the end to find contiguous null bytes
|
// Search backwards from the end to find contiguous null bytes
|
||||||
const char *ptr = sectionEnd-1;
|
const char *ptr = sectionEnd - 1;
|
||||||
while (ptr > sectionData) {
|
while (ptr > sectionData) {
|
||||||
if (*ptr != 0x00) {
|
if (*ptr != 0x00) {
|
||||||
break;
|
break;
|
||||||
|
@ -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 §ions = objReader.get_sections();
|
auto §ions = objReader.get_sections();
|
||||||
auto §ionRelocations = mainSection->get_relocations();
|
auto §ionRelocations = 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue