DLLHack wip
This commit is contained in:
parent
1e91d93470
commit
532c1653c0
|
@ -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()
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
LIBRARY Rayman3
|
||||
EXPORTS
|
||||
CDAPFN0506_CDAPFN0506_X_IPT_fn_vResetInputEntry @1
|
Binary file not shown.
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue