diff --git a/game_re/CMakeLists.txt b/game_re/CMakeLists.txt index caf8f3a2..cc4746c2 100644 --- a/game_re/CMakeLists.txt +++ b/game_re/CMakeLists.txt @@ -82,10 +82,11 @@ function(setup_target TARGET DBG_MODE) target_link_options(${TARGET} PRIVATE -Wl,/BASE:0x20000000 -Wl,/DYNAMICBASE:NO - -Wl,/SECTION:.reserved,RW,0x400000 ) + target_link_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/dllhack) target_link_libraries(${TARGET} PRIVATE DbgHelp + Rayman3 ) else() diff --git a/game_re/dllhack/Rayman3.def b/game_re/dllhack/Rayman3.def new file mode 100644 index 00000000..ec1dc68a --- /dev/null +++ b/game_re/dllhack/Rayman3.def @@ -0,0 +1,3 @@ +LIBRARY Rayman3 +EXPORTS + CDAPFN0506_CDAPFN0506_X_IPT_fn_vResetInputEntry @1 diff --git a/game_re/dllhack/Rayman3.lib b/game_re/dllhack/Rayman3.lib new file mode 100644 index 00000000..df9e882f Binary files /dev/null and b/game_re/dllhack/Rayman3.lib differ diff --git a/game_re/r3/binders/dbg_mem.cxx b/game_re/r3/binders/dbg_mem.cxx index 008b3138..6a25a81d 100644 --- a/game_re/r3/binders/dbg_mem.cxx +++ b/game_re/r3/binders/dbg_mem.cxx @@ -7,31 +7,44 @@ static uintptr_t g_gh_translationOffset{}; +extern "C" { +cdecl void CDAPFN0506_CDAPFN0506_X_IPT_fn_vResetInputEntry(); +} + struct R3Bin { R3Bin() { loadOriginal(); } - + void loadOriginal() { + void* ptr = (void*)&CDAPFN0506_CDAPFN0506_X_IPT_fn_vResetInputEntry; SPDLOG_DEBUG("Loading original binary"); auto &config = getDefaultConfig(); std::string path = config.gameRootDir + "/Rayman3.exe"; - // Reserve 4MB at the original base address - module = (HINSTANCE)VirtualAlloc((LPVOID)GH_BASE_ADDR, 4 * 1024 * 1024, MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (!module) { - // Get the error code - DWORD error = GetLastError(); - throw std::runtime_error("Failed to allocate memory at original base address: " + std::to_string(error)); - } - - // module = LoadLibraryA(path.c_str()); - // if (!module) - // throw std::runtime_error("Failed to load original binary"); + module = LoadLibraryA(path.c_str()); + if (!module) + throw std::runtime_error("Failed to load original binary"); fixupImports(module); g_gh_translationOffset = translationOffset = uintptr_t(module) - GH_BASE_ADDR; + + // Now we have to relocate the module to the new base address + } + + inline void relocate(HMODULE module, void* from, void* to, void* check) { + auto relocated_addr = uintptr_t(from) + translationOffset; + auto relocated_to = uintptr_t(to) + translationOffset; + void *checkRead{}; + size_t numRead{}; + ReadProcessMemory(GetCurrentProcess(), relocated_addr, &checkRead, sizeof(checkRead), &numRead); + WriteProcessMemory(GetCurrentProcess(), relocated_addr, relocated_to, sizeof(relocated_to), NULL); + } + + void relocateModule(HMODULE module) { + #define REL(from, to, original) relocate(module, (void*)(from), (void*)(to), (void*)(original)) + #include "relocations.def" } // Translate address relative from the original image base address diff --git a/java/ghidra/FindRelocations.java b/java/ghidra/FindRelocations.java index 630123ca..fc224857 100644 --- a/java/ghidra/FindRelocations.java +++ b/java/ghidra/FindRelocations.java @@ -27,7 +27,7 @@ public class FindRelocations extends GhidraScript { addrMax = RemanConfig.INSTANCE.staticMemoryBlockEnd.getOffset(); // Create output file for relocations - File relocFile = new File(RemanConfig.INSTANCE.outputDir, "relocations.txt"); + File relocFile = new File(RemanConfig.INSTANCE.outputDir, "relocations.def"); outputFile = new PrintWriter(new FileWriter(relocFile)); try { @@ -96,15 +96,17 @@ public class FindRelocations extends GhidraScript { Address toAddr = ref.getToAddress(); if (isInMainMemorySpace(toAddr)) { // Check if the target address appears in the instruction bytes (absolute addressing) - if (containsAbsoluteAddress(instruction, toAddr)) { - recordRelocation(instruction.getAddress(), toAddr, mnemonic, "absolute_" + ref.getReferenceType().getName()); + int operandOffset = findAbsoluteAddressOffset(instruction, toAddr); + if (operandOffset >= 0) { + recordRelocation(instruction.getAddress(), toAddr, mnemonic, + "absolute_" + ref.getReferenceType().getName(), operandOffset); } } } } } - private boolean containsAbsoluteAddress(Instruction instruction, Address targetAddr) { + private int findAbsoluteAddressOffset(Instruction instruction, Address targetAddr) { try { byte[] instructionBytes = instruction.getBytes(); long targetValue = targetAddr.getOffset(); @@ -116,17 +118,17 @@ public class FindRelocations extends GhidraScript { targetBytes[2] = (byte) ((targetValue >> 16) & 0xFF); targetBytes[3] = (byte) ((targetValue >> 24) & 0xFF); - // Search for the target address bytes in the instruction - return containsSequence(instructionBytes, targetBytes); + // Search for the target address bytes in the instruction and return offset + return findSequenceOffset(instructionBytes, targetBytes); } catch (Exception e) { - return false; + return -1; } } - private boolean containsSequence(byte[] haystack, byte[] needle) { + private int findSequenceOffset(byte[] haystack, byte[] needle) { if (needle.length > haystack.length) { - return false; + return -1; } for (int i = 0; i <= haystack.length - needle.length; i++) { @@ -138,10 +140,10 @@ public class FindRelocations extends GhidraScript { } } if (found) { - return true; + return i; // Return the offset where the sequence starts } } - return false; + return -1; } private boolean isRelocatableInstruction(String mnemonic) { @@ -177,7 +179,7 @@ public class FindRelocations extends GhidraScript { return; } - if (block.getName() == ".rsrc") { + if (block.getName().equals(".rsrc")) { continue; } @@ -199,7 +201,7 @@ public class FindRelocations extends GhidraScript { try { Address targetAddr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(value); if (isInMainMemorySpace(targetAddr)) { - recordRelocation(addr, targetAddr, "data", "pointer"); + recordRelocation(addr, targetAddr, "data", "pointer", 0); } } catch (Exception e) { // Invalid address, ignore @@ -233,11 +235,14 @@ public class FindRelocations extends GhidraScript { && value <= addrMax; // Typical executable range } - private void recordRelocation(Address fromAddr, Address toAddr, String instruction, String type) { + private void recordRelocation(Address fromAddr, Address toAddr, String instruction, String type, int operandOffset) { if (foundRelocations.add(toAddr)) { String instructionBytes = getInstructionBytesString(fromAddr); - String line = String.format("0x%s -> 0x%s (%s) [%s] | %s", + Address operandPtr = fromAddr.add(operandOffset); + + String line = String.format("REL(0x%s, 0x%s, 0x%s) // %s [%s] | %s", fromAddr.toString(), + operandPtr.toString(), toAddr.toString(), instruction, type,