替换反编译DLL中的函数

时间:2013-04-26 22:49:01

标签: c++ assembly dll

我已经反编译了一个dll,我希望用调用我创建的自定义函数(具有相同的签名)替换对DLL中函数的调用。

我已经设法找到在程序集中调用函数的位置。有人可以解释我现在需要做什么吗?

我的自定义函数可以位于单独的dll中,还是需要包含在同一个dll中?

如何调用我的新函数调用替换函数调用?

由于

1 个答案:

答案 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。