Compare commits

..

No commits in common. "891277f15d0e58fa665c1eac96bf5e43a05832de" and "1e91d934700082059b12052b3fbb917f55b86e59" have entirely different histories.

3 changed files with 28 additions and 45 deletions

View File

@ -82,6 +82,7 @@ function(setup_target TARGET DBG_MODE)
target_link_options(${TARGET} PRIVATE target_link_options(${TARGET} PRIVATE
-Wl,/BASE:0x20000000 -Wl,/BASE:0x20000000
-Wl,/DYNAMICBASE:NO -Wl,/DYNAMICBASE:NO
-Wl,/SECTION:.reserved,RW,0x400000
) )
target_link_libraries(${TARGET} PRIVATE target_link_libraries(${TARGET} PRIVATE
DbgHelp DbgHelp

View File

@ -7,44 +7,31 @@
static uintptr_t g_gh_translationOffset{}; static uintptr_t g_gh_translationOffset{};
extern "C" {
cdecl void CDAPFN0506_CDAPFN0506_X_IPT_fn_vResetInputEntry();
}
struct R3Bin { struct R3Bin {
R3Bin() { loadOriginal(); } R3Bin() { loadOriginal(); }
void loadOriginal() { void loadOriginal() {
void* ptr = (void*)&CDAPFN0506_CDAPFN0506_X_IPT_fn_vResetInputEntry;
SPDLOG_DEBUG("Loading original binary"); SPDLOG_DEBUG("Loading original binary");
auto &config = getDefaultConfig(); auto &config = getDefaultConfig();
std::string path = config.gameRootDir + "/Rayman3.exe"; std::string path = config.gameRootDir + "/Rayman3.exe";
module = LoadLibraryA(path.c_str()); // Reserve 4MB at the original base address
if (!module) module = (HINSTANCE)VirtualAlloc((LPVOID)GH_BASE_ADDR, 4 * 1024 * 1024, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
throw std::runtime_error("Failed to load original binary"); 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");
fixupImports(module); fixupImports(module);
g_gh_translationOffset = translationOffset = g_gh_translationOffset = translationOffset =
uintptr_t(module) - GH_BASE_ADDR; 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 // Translate address relative from the original image base address

View File

@ -27,7 +27,7 @@ public class FindRelocations extends GhidraScript {
addrMax = RemanConfig.INSTANCE.staticMemoryBlockEnd.getOffset(); addrMax = RemanConfig.INSTANCE.staticMemoryBlockEnd.getOffset();
// Create output file for relocations // Create output file for relocations
File relocFile = new File(RemanConfig.INSTANCE.outputDir, "relocations.def"); File relocFile = new File(RemanConfig.INSTANCE.outputDir, "relocations.txt");
outputFile = new PrintWriter(new FileWriter(relocFile)); outputFile = new PrintWriter(new FileWriter(relocFile));
try { try {
@ -96,17 +96,15 @@ public class FindRelocations extends GhidraScript {
Address toAddr = ref.getToAddress(); Address toAddr = ref.getToAddress();
if (isInMainMemorySpace(toAddr)) { if (isInMainMemorySpace(toAddr)) {
// Check if the target address appears in the instruction bytes (absolute addressing) // Check if the target address appears in the instruction bytes (absolute addressing)
int operandOffset = findAbsoluteAddressOffset(instruction, toAddr); if (containsAbsoluteAddress(instruction, toAddr)) {
if (operandOffset >= 0) { recordRelocation(instruction.getAddress(), toAddr, mnemonic, "absolute_" + ref.getReferenceType().getName());
recordRelocation(instruction.getAddress(), toAddr, mnemonic,
"absolute_" + ref.getReferenceType().getName(), operandOffset);
} }
} }
} }
} }
} }
private int findAbsoluteAddressOffset(Instruction instruction, Address targetAddr) { private boolean containsAbsoluteAddress(Instruction instruction, Address targetAddr) {
try { try {
byte[] instructionBytes = instruction.getBytes(); byte[] instructionBytes = instruction.getBytes();
long targetValue = targetAddr.getOffset(); long targetValue = targetAddr.getOffset();
@ -118,17 +116,17 @@ public class FindRelocations extends GhidraScript {
targetBytes[2] = (byte) ((targetValue >> 16) & 0xFF); targetBytes[2] = (byte) ((targetValue >> 16) & 0xFF);
targetBytes[3] = (byte) ((targetValue >> 24) & 0xFF); targetBytes[3] = (byte) ((targetValue >> 24) & 0xFF);
// Search for the target address bytes in the instruction and return offset // Search for the target address bytes in the instruction
return findSequenceOffset(instructionBytes, targetBytes); return containsSequence(instructionBytes, targetBytes);
} catch (Exception e) { } catch (Exception e) {
return -1; return false;
} }
} }
private int findSequenceOffset(byte[] haystack, byte[] needle) { private boolean containsSequence(byte[] haystack, byte[] needle) {
if (needle.length > haystack.length) { if (needle.length > haystack.length) {
return -1; return false;
} }
for (int i = 0; i <= haystack.length - needle.length; i++) { for (int i = 0; i <= haystack.length - needle.length; i++) {
@ -140,10 +138,10 @@ public class FindRelocations extends GhidraScript {
} }
} }
if (found) { if (found) {
return i; // Return the offset where the sequence starts return true;
} }
} }
return -1; return false;
} }
private boolean isRelocatableInstruction(String mnemonic) { private boolean isRelocatableInstruction(String mnemonic) {
@ -179,7 +177,7 @@ public class FindRelocations extends GhidraScript {
return; return;
} }
if (block.getName().equals(".rsrc")) { if (block.getName() == ".rsrc") {
continue; continue;
} }
@ -201,7 +199,7 @@ public class FindRelocations extends GhidraScript {
try { try {
Address targetAddr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(value); Address targetAddr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(value);
if (isInMainMemorySpace(targetAddr)) { if (isInMainMemorySpace(targetAddr)) {
recordRelocation(addr, targetAddr, "data", "pointer", 0); recordRelocation(addr, targetAddr, "data", "pointer");
} }
} catch (Exception e) { } catch (Exception e) {
// Invalid address, ignore // Invalid address, ignore
@ -235,14 +233,11 @@ public class FindRelocations extends GhidraScript {
&& value <= addrMax; // Typical executable range && value <= addrMax; // Typical executable range
} }
private void recordRelocation(Address fromAddr, Address toAddr, String instruction, String type, int operandOffset) { private void recordRelocation(Address fromAddr, Address toAddr, String instruction, String type) {
if (foundRelocations.add(toAddr)) { if (foundRelocations.add(toAddr)) {
String instructionBytes = getInstructionBytesString(fromAddr); String instructionBytes = getInstructionBytesString(fromAddr);
Address operandPtr = fromAddr.add(operandOffset); String line = String.format("0x%s -> 0x%s (%s) [%s] | %s",
String line = String.format("REL(0x%s, 0x%s, 0x%s) // %s [%s] | %s",
fromAddr.toString(), fromAddr.toString(),
operandPtr.toString(),
toAddr.toString(), toAddr.toString(),
instruction, instruction,
type, type,