This is harder than a simple LD_PRELOAD, but still quite easy. Tested on VMWare with Windows XP Pro SP3.
Goal: start libcod.dll before WinMain() of libcod2_1_3.exe is called. We basically just gonna do three things:
- PUSH "libcod.dll"
- CALL LoadLibraryA
- Set the string "libcod.dll" in memory of the start-function
Pictures!
At first we open libcod2_1_3.exe (just a renamed CoD2MP.exe, so we don't overwrite original stuff) in OllyDBG.
It will jump directly to the program entry point, just what we need:
We double click on the "PUSH 60", to overwrite it with our opcode:
Same with the second opcode, just enter CALL LoadLibraryA. Now we need to write the string libcod.dll\0 into memory, use Rightclick -> Binary -> Edit:
Type "libcod.dll" in ASCII, then append 00 in HEX view (important C string terminator):
Now we see the address 0x0057DB5E, which is basically a (char *), lets point our PUSH 12345 to it.
Just like that:
Now patch the binary by saving our changes:
Which is quite cumbersome in OllyDBG, first close this window, then you need to press like 5 times yes:
Now we are done with the OllyDBG, now we need to copy the original opcodes of a normal CoD2MP.exe:
Just press CTRL+C, do some Notepad++ multi line edit magic, and come up with this (basically Code::Blocks DLL example with https://github.com/M-itch/libcod_win...c/cracking.cpp):
We basically just reset the overwritten parts of our program entry point and then jump to the entry-point with inline asm:
PHP Code:
#include "main.h"
#include <stdio.h>
#include "cracking.h"
// a sample exported function
void DLL_EXPORT SomeFunction(const LPCSTR sometext)
{
MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
}
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
MessageBoxA(NULL, "Hello KILLTUBE!", "Starting libcod.dll from libcod_1_3.exe!", MB_ICONINFORMATION);
cracking_write_hex(0x0057DB54, (char *)"6A60"); // PUSH 60
cracking_write_hex(0x0057DB56, (char *)"68D8925900"); // PUSH original.005992D8
cracking_write_hex(0x0057DB5B, (char *)"E8443F0000"); // CALL original.00581AA4
cracking_write_hex(0x0057DB60, (char *)"BF94000000"); // MOV EDI,94
cracking_write_hex(0x0057DB65, (char *)"8BC7"); // MOV EAX,EDI
cracking_write_hex(0x0057DB67, (char *)"E8C4880000"); // CALL original.00586430
asm("jmp *%0"::"r"(0x0057DB54):);
// attach to process
// return FALSE to fail DLL load
break;
case DLL_PROCESS_DETACH:
// detach from process
break;
case DLL_THREAD_ATTACH:
// attach to thread
break;
case DLL_THREAD_DETACH:
// detach from thread
break;
}
return TRUE; // successfull
}
Start libcod2_1_3.exe
Press OK:
Done.
I was always pissed of by the .dll injection process, making the reverse engineering so demotivating. Now this should feel pretty native.
Started with this, because I wanted to hook CreateWindow() to allow non-fullscreen and resizeable windows and maybe debug why DX9 starts up so slow.
I guess this works for .dll's as well, but not tested yet.
Basically it's now simple as fuck to extend any .exe with a custom .dll, kinda what I always wanted and missed for Windows. Looking forward what ya gonn do with this.