WIP Patch
This commit is contained in:
parent
892aa30091
commit
6104238552
|
@ -4,4 +4,5 @@ add_executable(patcher patcher.cpp)
|
|||
target_link_libraries(patcher PRIVATE coffi CLI11 spdlog)
|
||||
target_compile_options(patcher PRIVATE -DSRC_OBJECT="$<TARGET_OBJECTS:ref>")
|
||||
add_dependencies(patcher ref)
|
||||
target_compile_features(patcher PRIVATE cxx_std_20)
|
||||
|
||||
|
|
|
@ -178,6 +178,134 @@ int main(int argc, char *argv[]) {
|
|||
// Copy our code into the null space
|
||||
std::memcpy(newTextData.data() + injectionOffset, mainCode, mainSize);
|
||||
|
||||
// Now handle relocations - resolve imports and copy constants to .rdata
|
||||
spdlog::info("Processing relocations...");
|
||||
|
||||
// Find .rdata section for constants
|
||||
COFFI::section* rdataSection = nullptr;
|
||||
for (auto& section : peSections) {
|
||||
if (section->get_name() == ".rdata") {
|
||||
rdataSection = section;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rdataSection) {
|
||||
spdlog::error("Could not find .rdata section in PE file");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Find available space in .rdata section (similar to .text)
|
||||
auto rdataData = rdataSection->get_data();
|
||||
uint32_t rdataSize = rdataSection->get_data_size();
|
||||
uint32_t rdataAvailableSpace = 0;
|
||||
|
||||
for (int32_t i = rdataSize - 1; i >= 0; i--) {
|
||||
if (reinterpret_cast<const uint8_t*>(rdataData)[i] == 0x00) {
|
||||
rdataAvailableSpace++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spdlog::info("Found {} bytes of available space in .rdata section", rdataAvailableSpace);
|
||||
|
||||
// Create rdata copy for modifications
|
||||
std::vector<uint8_t> newRdataData(reinterpret_cast<const uint8_t*>(rdataData),
|
||||
reinterpret_cast<const uint8_t*>(rdataData) + rdataSize);
|
||||
uint32_t rdataInjectionOffset = rdataSize - rdataAvailableSpace;
|
||||
uint32_t rdataCurrentOffset = rdataInjectionOffset;
|
||||
|
||||
// Get import table information for resolving __imp_ symbols
|
||||
auto& directories = peReader.get_directories();
|
||||
uint32_t importRVA = 0;
|
||||
if (directories.size() > 1) {
|
||||
importRVA = directories[1]->get_virtual_address(); // Import table is directory entry 1
|
||||
}
|
||||
|
||||
// Process each relocation
|
||||
for (auto& reloc : sectionRelocations) {
|
||||
if (reloc.get_type() != 6) continue; // Only handle type 6 (IMAGE_REL_I386_DIR32)
|
||||
|
||||
uint32_t relocOffset = reloc.get_virtual_address();
|
||||
std::string symbolName = reloc.get_symbol();
|
||||
uint32_t resolvedAddress = 0;
|
||||
|
||||
spdlog::info("Processing relocation at offset 0x{:x} for symbol: {}", relocOffset, symbolName);
|
||||
|
||||
if (symbolName.starts_with("__imp_")) {
|
||||
// This is an import symbol - find it in the PE's import table
|
||||
std::string functionName = symbolName.substr(6); // Remove "__imp_" prefix
|
||||
|
||||
// Remove @N suffix for stdcall functions
|
||||
size_t atPos = functionName.find('@');
|
||||
if (atPos != std::string::npos) {
|
||||
functionName = functionName.substr(0, atPos);
|
||||
}
|
||||
|
||||
spdlog::info("Looking for import function: {}", functionName);
|
||||
|
||||
// For now, we'll need to implement import table parsing
|
||||
// This is a placeholder - you'd need to parse the import table to find the actual IAT address
|
||||
spdlog::warn("Import resolution not fully implemented yet for: {}", functionName);
|
||||
resolvedAddress = 0x12345678; // Placeholder
|
||||
|
||||
} else if (symbolName.starts_with("??_C@")) {
|
||||
// This is a string constant - find it in the object file and copy to .rdata
|
||||
COFFI::symbol* constSymbol = nullptr;
|
||||
for (auto& sym : symbols) {
|
||||
if (sym.get_name() == symbolName) {
|
||||
constSymbol = &sym;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (constSymbol) {
|
||||
// Get the string data from the object file
|
||||
auto constSection = sections[constSymbol->get_section_number() - 1];
|
||||
auto constData = constSection->get_data();
|
||||
uint32_t constOffset = constSymbol->get_value();
|
||||
|
||||
// Find the string length (null-terminated)
|
||||
uint32_t stringLen = 0;
|
||||
while (constData[constOffset + stringLen] != 0) {
|
||||
stringLen++;
|
||||
}
|
||||
stringLen++; // Include null terminator
|
||||
|
||||
if (rdataCurrentOffset + stringLen > rdataSize) {
|
||||
spdlog::error("Not enough space in .rdata for string constant");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Copy string to .rdata
|
||||
std::memcpy(newRdataData.data() + rdataCurrentOffset,
|
||||
constData + constOffset, stringLen);
|
||||
|
||||
// Calculate the new address
|
||||
uint32_t rdataRVA = rdataSection->get_virtual_address();
|
||||
resolvedAddress = imageBase + rdataRVA + rdataCurrentOffset;
|
||||
|
||||
spdlog::info("Copied string constant '{}' to .rdata at RVA 0x{:x} (VA: 0x{:x})",
|
||||
std::string(constData + constOffset),
|
||||
rdataRVA + rdataCurrentOffset, resolvedAddress);
|
||||
|
||||
rdataCurrentOffset += stringLen;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the relocation to the injected code
|
||||
if (resolvedAddress != 0) {
|
||||
uint32_t patchOffset = injectionOffset + relocOffset;
|
||||
*reinterpret_cast<uint32_t*>(newTextData.data() + patchOffset) = resolvedAddress;
|
||||
spdlog::info("Applied relocation: patched offset 0x{:x} with address 0x{:x}",
|
||||
patchOffset, resolvedAddress);
|
||||
}
|
||||
}
|
||||
|
||||
// Update both sections
|
||||
rdataSection->set_data(reinterpret_cast<const char*>(newRdataData.data()), newRdataData.size());
|
||||
|
||||
// Update the .text section with modified data (same size)
|
||||
textSection->set_data(reinterpret_cast<const char*>(newTextData.data()), newTextData.size());
|
||||
|
||||
|
|
Loading…
Reference in New Issue