替换反编译DLL中的函数

Replacing a function in a decompiled DLL

本文关键字:函数 DLL 编译 替换      更新时间:2023-10-16

我已经反编译了一个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。