Reputation: 170
I have decompiled a dll and I want to replace a call to a function in the DLL with call a custom function created by me (with the same signature) instead.
I have managed to find where the function is called in assembly. Could anybody explain what I need to do now?
Can my custom function be located in a separate dll or does it need to be included in the same dll?
How can I call replace the function call with my new one?
Thanks
Upvotes: 1
Views: 2255
Reputation: 20063
Might be easier to just patch the executable module. Add your new code to the end of the text segment and place a jump to your added code at the beginning to the old function. This way you don't have to deal with problems the decompiled version of the DLL may cause.
For example here is the beginning of the existing function you want to replace:
000D0880 push ebp
000D0881 mov ebp,esp
000D0883 sub esp,0E0h
000D0889 push ebx
000D088A push esi
000D088B push edi
000D088C lea edi,[ebp-0E0h]
000D0892 mov ecx,38h
000D0897 mov eax,0CCCCCCCCh
To redirect the call just add a JMP instruction at D0880. We add NOP instructions after the jump just to make the disassembled output cleaner during debug sessions. It's not necessary but it does come in handy.
000D0880 jmp NewFunction
000D0885 nop
000D0886 nop
000D0887 nop
000D0888 nop
000D0889 push ebx
000D088A push esi
000D088B push edi
Now you append your new code to the end of the text segment and calculate the address based on the offset where the segment is loaded. This makes it much easier to debug and manage since you know beforehand exactly where in the text segment your function actually resides.
To call either function from another in-process executable module can also be done. Since you already know the offsets of both the original function and the next function you can calculate their exact location based on the load address of the module.
typedef void (*EXTPROC)(int a, int b);
// Windows loads the dll at 0xC0000
HMODULE hMod = LoadLibrary("some.dll");
// The function is at offset 0x10880 (from start of text segment)
EXTPROC proc = CalculateAddress(hMod, 0x00010880);
// Call proc at 0xd0880
proc(0, 1);
The function CalculateAddress
retrieves the base address of the DLL and calculates the actual address of the function and returns pointer to it. The result is the same as in the earlier example - 0xD0880. Now that you have the address you can call it through the function pointer. You can apply the same technique to call the new function you are adding as you know the offset of that function as well.
If you wanted to go the extra mile you could even update the export table with new entries pointing to those offsets and use GetProcAddress
to retrieve the address without having to calculate it yourself. This adds a bit more complexity to the patching process since you have to update an additional section in the DLL.
To call a function that exists in a different DLL is a bit more complex as you would need to do a runtime patch of the original function to make it call the address of the external one. For this I recommend looking into the suggestion made by Rich and create a proxy DLL as described in this article.
Upvotes: 5