2

这是我的第一篇文章,我是组装和调试的新手,所以请多多包涵。

我试图将一些代码(对 MessageBoxA 的一点调用)注入到 Windows 7 记事本可执行文件中。但是,我遇到了地址的问题。首先,我在 OllyDbg 中打开 exe,然后转到包含“notepad.pdb”的 ASCII 文本的行。然后我在其下方放置一个 ASCII 字符串(例如,“INJECTED NOTEPAD”)。接下来,在此之下,我输入了这个 asm 代码:

PUSH 0
PUSH address_of_ASCII_string ; In this case, 00A6B668C
PUSH address_of_ASCII_string ; In this case, 00A6B668C
PUSH 0
CALL MessageBoxA

接下来,我转到程序中的第一行代码(只需右键单击并按 Go to Origin(或只需在数字键盘上按 *))然后我将第一行替换为 JMP 指令到第一个地址PUSH 0 在我注入的代码中。然后,我将替换的指令放在注入代码的末尾。之后,我在 JMP 指令之后的代码行中添加了一条 JMP 指令,该指令跳转到我的注入代码(是的,我只是描述了一个 codecave 或类似的东西)。当我运行它时一切正常。但是,当我将修改后的代码保存到新的可执行文件并再次使用 OllyDbg 运行它时,它不起作用。当我尝试引用我输入的 ASCII 字符串时,地址完全错误。示例如下图所示:

如您所见,我将字符串压入堆栈,但是当我再次将修改后的程序重新加载到调试器中时,字符串的地址发生了变化,但我的代码没有。因此,当我调用 MessageBoxA 函数时,它会出错,因为我为 Text 和 Caption 参数加载了错误的地址。我该如何解决?

4

1 回答 1

5

您遇到的是ASLR的影响。简而言之,这意味着在操作系统(在此示例中为 Windows)上运行的可执行文件在多次执行时不会具有相同的基地址。

所以有几种方法可以将您的代码注入另一个二进制文件,我将在这里解决 2 并且我还将猜测(在阅读评论之后)您正在尝试修补磁盘上的二进制文件。

  1. 修补磁盘上的二进制文件:

    一个。解决此问题的第一种方法是从PE中删除重定位表。我绝对不会推荐这种方式,因为它可能会在将来使可执行文件崩溃,以防它没有被加载到它喜欢的基地址(OptionalHeader.ImageBase)中,这是所有需要重定位的指令将用作添加基地址的默认值一个偏移量。

    假设您有一个0x600与映像基址偏移的字符串,如果可执行文件映射到其首选基址(通常0x00400000),则该字符串将保存在 address 0x00400000。您的编译器链接文件的方式将使用0x00400000 + 0x600so的地址0x00400600。那么当可执行文件被加载到不同的基地址时会发生什么?在这种情况下,windows 可执行加载程序会将基地址的偏移量(实际上是映射减去首选基地址)添加到每个重定位条目(上面的示例将需要一个)。因此,如果可执行文件将被加载到0x00500000加载器中,加载器将添加0x00100000到导致0x00500600.

    湾。第二种方法是在二进制文件中添加一个重定位条目。这样,与 (a) 中描述的方式相反,您不会损害二进制文件,只会添加一个重定位条目,在加载可执行文件时,加载器会将地址更改为正确的地址(如果您添加了正确的入口)。

    C。编写与位置无关的代码并使用此代码修补二进制文件。例子:

    sub     esp, 10*4
    mov     byte [esp], 0x68 ; 'h'
    mov     byte [esp + 1], 0x69 ; 'i'
    mov     byte [esp + 2], 0x00 ; null byte
    mov     byte [esp + 3], 0x79 ; 'y'
    mov     byte [esp + 4], 0x6f ; 'o'
    mov     byte [esp + 5], 0x75 ; 'u'
    mov     byte [esp + 6], 0x00 ; null byte
    mov     eax, esp
    push    0
    push    eax
    add     eax, 3
    push    eax
    push    0
    call    [MessageBoxA]  
    

    该代码会将所需的 2 个字符串写入堆栈并将指针推送到堆栈上的字符串,这样代码就不需要任何重定位,因为它是一段独立的代码。

  2. 修补内存中的二进制文件:

    一个。位置无关代码(见上文)

    湾。使用VirtualAllocEx,此 API 将在调用它后返回一个您可以写入的地址,这样您只需在内存中拥有映射地址并知道在哪里以及如何注入您的代码。

于 2016-12-23T18:25:37.837 回答