shellcode 中的地址在执行期间发生变化

Address in shellcode changing during execution

我的目标是创建调用 WinExec 并启动 notepad.exe 的 shellcode。最简单的代码是(尽管实际上被其他一些 gcc 生产的程序集所包围):

push 0x00646170
push 0x65746F6E 

push 5

lea eax, [esp + 0x4]
push eax

call 0x76E137C0
add esp, 32

它将“notepad[=52=]”压入堆栈,然后是 5,然后是 "notepad" 字符串的地址,最后调用 0x76E137C00x76E137C0 是地址 WinExec 似乎驻留在我的机器上禁用 ASLR 时(32 位 Windows 10 VM)。

我正在使用这段代码,使用 gcc(简单地 gcc shell.c -o shell.exe)组装它,然后 objdumping 它。找到说明后,我将使用它显示的字节:

40141e:       68 70 61 64 00          push   [=11=]x646170
401423:       68 6e 6f 74 65          push   [=11=]x65746f6e
401428:       6a 05                   push   [=11=]x5
40142a:       8d 44 24 04             lea    0x4(%esp),%eax
40142e:       50                      push   %eax
40142f:       e8 8c 23 a1 76          call   76e137c0 <.debug_str+0x76a027c0>
401434:       83 c4 20                add    [=11=]x20,%esp

然后我将其转换为字节串,并尝试执行它:

#include <windows.h>
#include <winbase.h>

int main() {

    char* shellcode =
       "\x68\x70\x61\x64\x00\x68\x6e\x6f\x74\x65\x6a\x05\x8d\x44\x24\x04\x50\xe8\xbc\x37\xe1\x76\x83\xc4\x20";

    ((void(*)())shellcode)();

    return 0;
}

问题 是,如果我然后编译上面的简单 C 程序并 运行 它,没有任何反应。如果我在 Immunity 中打开它并执行步骤,我可以看到指令已被保留, 除了地址

地址在错误的模块中,似乎是函数的一部分。如果我下台并进入 call,我会遇到访问冲突。但是,如果我重新启动,并且在 Immunity 中我将 call 77218816 替换为 call 0x76E137C0,然后让它继续,它工作正常并弹出记事本。

我不知道为什么地址在变化,而其他一切都没有变化。有没有人看到我可能在做什么?



整个初始组装是

    .file   "shell.c"
    .intel_syntax noprefix
    .text
    .def    ___main;    .scl    2;  .type   32; .endef
    .section .rdata,"dr"
    .align 4
LC0:
    .ascii "notepad[=13=]"
    .text
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    lea ecx, [esp+4]

    and esp, -16
    push    DWORD PTR [ecx-4]
    push    ebp

    mov ebp, esp
    push    ecx

    push 0x00646170
    push 0x65746F6E 
    
    push 5
    
    lea eax, [esp + 0x4]
    push eax
    
    call 0x76E137C0
    add esp, 32
    
    sub esp, 8
    mov eax, 0
    mov ecx, DWORD PTR [ebp-4]

    leave

    lea esp, [ecx-4]

    ret

像这样使用 call 是 EIP 相关的。你不是 运行 你的 shellcode 在你编译它的相同地址,所以它不能 call 那样自己。对于快速而肮脏的解决方法,您可以执行 mov eax, 0x76E137C0,然后执行 call eax,这是绝对的。