我已经反编译了一个dll,我希望用调用我创建的自定义函数(具有相同的签名)替换对DLL中函数的调用。
我已经设法找到在程序集中调用函数的位置。有人可以解释我现在需要做什么吗?
我的自定义函数可以位于单独的dll中,还是需要包含在同一个dll中?
如何调用我的新函数调用替换函数调用?
由于
答案 0 :(得分:3)
可能更容易修补可执行模块。将新代码添加到文本段的末尾,并在旧函数的开头跳转到添加的代码。这样您就不必处理DLL的反编译版本可能导致的问题。
例如,这里是您要替换的现有函数的开头:
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
要重定向呼叫,只需在D0880添加JMP指令。我们在跳转后添加NOP指令只是为了在调试会话期间使反汇编的输出更清晰。这不是必要的,但它确实派上用场。
000D0880 jmp NewFunction
000D0885 nop
000D0886 nop
000D0887 nop
000D0888 nop
000D0889 push ebx
000D088A push esi
000D088B push edi
现在,将新代码附加到文本段的末尾,并根据加载段的偏移量计算地址。这使得调试和管理变得更加容易,因为您事先知道函数实际驻留在文本段中的确切位置。
也可以从另一个进程内可执行模块调用任一函数。由于您已经知道原始函数和下一个函数的偏移量,因此您可以根据模块的加载地址计算它们的确切位置。
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);
函数CalculateAddress
检索DLL的基址并计算函数的实际地址并返回指向它的指针。结果与前面的示例相同 - 0xD0880。现在你有了地址,你可以通过函数指针调用它。您可以应用相同的技术来调用您正在添加的新函数,因为您也知道该函数的偏移量。
如果您想加倍努力,您甚至可以使用指向这些偏移的新条目更新导出表,并使用GetProcAddress
检索地址,而无需自行计算。这增加了修补过程的复杂性,因为您必须更新DLL中的其他部分。
调用存在于不同DLL中的函数有点复杂,因为您需要对原始函数执行运行时补丁以使其调用外部函数的地址。为此,我建议查看Rich提出的建议,并按照this文章中的说明创建代理DLL。