查找和修补DLL中的指令



我有一个(C++(程序,在它的一个dll中,完成以下操作:

if (m_Map.GetMaxValue() >= MAX_CLASSES) {

我有这个程序的两个二进制文件(使用不同版本的Visual Studio编译(,一个是MAX_CLASSES被#定义为50,另一个是75。这些二进制文件是由不同的代码分支组成的,其他功能也不同。我需要的是二进制的一个版本,其中MAX_CLASSES被定义为50,除了更高的极限,即75。

因此,一个理智的人会更改我需要的分支的源代码中的常量,重建并回家。但是,构建这个软件很复杂,因为它很旧,依赖关系和工具也很旧,等等。;另外,我在构建安装程序和数据等方面遇到了问题。所以,我想,不如我只是修补这个二进制文件,让这个常量直接在DLL中更改。我模糊地记得在20世纪90年代做过类似的事情,嗯,可能是为了"教育"目的。

但时代变了,我几乎不记得做过什么,更不用说我当时是怎么做的了。我打开了Ghidra中的DLL(其中极限设置为75,这是我手头的二进制文件-一旦我有了50极限的实际二进制文件,我就必须重新做这件事,所以下面的参考文件75,即0x4b,用于说明原理(,经过一番翻查,我发现了以下内容:

18005160e 3c 4b           CMP        AL,0x4b
180051610 0f 82 19        JC         LAB_18005172f
01 00 00

在反编译器窗口中,我可以链接回

if (bVar3 < 0x4b)

以及之后的一些操作,我可以映射到我所拥有的函数的源代码。

现在我的问题是:

  • 如何将上面的值(Ghidra输出(wrt解释为dll的二进制布局?当我将鼠标悬停在Ghidra中的第一列值("18005160e"(上时,我会得到"imagebase offset"、"memory block offset","function offset"one_answers"byte source offset"的值。这个"字节源偏移量"是从这些指令开始的dll开始的物理地址吗?这个悬停气球中的实际值是50a0eh——这是Ghidra对0x50a0e的表示法吗?即,后面的"h"表示"hex"吗?

  • 然后,我尝试在常规的十六进制编辑器中打开dll(我喜欢使用"十六进制编辑器Neo"来查看/编辑二进制数据文件(,然后转到偏移量0x50a0e,并在那里查找我没有找到的值"3c 4b"。我在整个文件中搜索了这个字节序列,发现有7次出现,没有一次出现在0x50a0e附近,这让我觉得我误解了Ghidra的"字节源偏移量"。

  • 我该如何做一个"补丁"?我想我需要的是一个只做的程序

    FILE*fh=fopen('mydll.dll(;fseek(fh,0x[魔术常数](;fwrite(fh,0x4b(;fclose(fh(;

其中"0x[magic constants]"希望只是我从Ghidra获得的"字节源偏移量"中的值?或者我还有什么需要考虑的吗?有什么软件工具可以生成补丁程序吗?

谢谢。

18005160e是一个VA,一个虚拟地址

它是基地址(很可能是180000000(和RVA(相对虚拟地址(的总和。

使用任何PE检查工具(例如CFF Explorer(或Ghidra本身查找DLL的基址。

18005160e中的基地址减去RVA。假设结果是5160e

现在您需要找到此RVA所在的节。再次使用PE检查工具查找节的列表及其RVA/虚拟开始和RVA/虚拟大小
假设RVA位于.text部分,起始于RVA1000

从上面的结果中减去该起始RVA:5160e - 1000 = 4160e
这是.text部分中指令的偏移量。

要在文件中找到偏移量,只需添加截面的原始/偏移起点(同样,您可以使用PE检查工具找到(。假设.text部分从偏移400开始,则4160e + 400 = 41a0e是与VA18005160e相对应的偏移。

这都是PE 101。

最新更新