我已经反编译了一个 dll,我想用调用我创建的自定义函数(具有相同的签名)替换对 DLL 中函数的调用。
我设法找到了在程序集中调用该函数的位置。谁能解释我现在需要做什么?
我的自定义函数可以位于单独的 dll 中还是需要包含在同一个 dll 中?
如何调用用我的新函数调用替换函数调用?
谢谢
修补可执行模块可能更容易。将您的新代码添加到文本段的末尾,并在旧函数的开头放置一个跳转到您添加的代码。这样您就不必处理 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提出的建议,并按照本文所述创建代理 DLL 。