0
    jmp    0x2a                     # 3 bytes
    popl   %esi                     # 1 byte
    movl   %esi,0x8(%esi)           # 3 bytes
    movb   $0x0,0x7(%esi)           # 4 bytes
    movl   $0x0,0xc(%esi)           # 7 bytes
    movl   $0xb,%eax                # 5 bytes
    movl   %esi,%ebx                # 2 bytes
    leal   0x8(%esi),%ecx           # 3 bytes
    leal   0xc(%esi),%edx           # 3 bytes
    int    $0x80                    # 2 bytes
    movl   $0x1, %eax               # 5 bytes
    movl   $0x0, %ebx               # 5 bytes
    int    $0x80                    # 2 bytes
    call   -0x2f                    # 5 bytes
    .string \"/bin/sh\"             # 8 bytes

所以跳转到调用然后“字符串地址将作为返回地址推入堆栈”。是这个地址保存在 esi 为什么要弹出 esi ?

4

2 回答 2

1

这是编写与位置无关的代码(无论位于什么地址都可以成功执行的代码)的常用方法。

call指令做了两件事:

  1. 将返回地址(紧跟在调用之后的指令的地址)压入堆栈
  2. 跳转到指定的地址。

所以调用之后,字符串“/bin/sh”的地址就在栈上了。下一条指令pop esi将该地址从堆栈中取出,并将其放入esi寄存器中,以便可以使用它。

于 2012-08-06T23:07:24.860 回答
0

好吧,当call执行时,它会将返回地址(调用操作码之后的地址)压入堆栈,以便在ret遇到时(在正常操作中),从中断处继续执行。这是标准的 x86 调用约定。

在您的代码中,推送的返回地址是“/bin/sh”的位置。pop %esi将该值放入 esi 寄存器,然后将其作为指针传递给 linux 系统上的 syscall 0xbexecve执行字符串中命名的命令。

有很多关于x86 调用约定的好资源,我希望您对 linux x86 会特别感兴趣。

于 2012-08-06T23:10:31.830 回答