任何人都可以清楚地解释这个反汇编吗?

时间:2016-12-07 18:02:41

标签: debugging assembly x86 disassembly shellcode

我是新手调试。我通过这段代码说明它在执行时会产生一个shell提示符。

0:  31 c0                   xor    eax,eax
2:  50                      push   eax
3:  68 2f 2f 73 68          push   0x68732f2f
8:  68 2f 62 69 6e          push   0x6e69622f
d:  89 e3                   mov    ebx,esp
f:  50                      push   eax
10: 53                      push   ebx
11: 89 e1                   mov    ecx,esp
13: b0 0b                   mov    al,0xb
15: cd 80                   int    0x80 

请清楚地解释寄存器和内存中实际发生的事情。

2 个答案:

答案 0 :(得分:3)

一些硬编码的值被压入堆栈,然后推送指向堆栈本身的指针。最后,EAX寄存器保留最终加载值,EBX,ECX和ESP指向堆栈中的位置。

    STACK (from highest address to lowest):
                                    0
                                    0x68732f2f
                        /->     /-> 0x6e69622f
                        |       |   0             (arg[1])
                        |  /->  \-- arg[0]
                        |  |   
    EAX = 0xb           |  |   
    EBX(arg[0]) = ------/  |  
    ECX(&arg[0]) = --------/ 
    ESP = Same as ECX

正如@PaulR建议的那样,它必须是execve,所以它在C中与它接近:

char *arg[2] = { "/bin//sh", 0 };
execve(arg[0], &arg[0], envp);

envp值在此代码段中不可用。它可以是EDX中的任何内容。如果这是整个程序,可能是EDX在输入时为零 - 在linux上为null指针被解释为空的环境列表。)

答案 1 :(得分:3)

; Push 0 onto the stack
xor    eax,eax      ; a classic x86 optimization trick to clear/zero a register
push   eax          ; push that zeroed register onto the stack

; Push two constant values onto the stack
push   0x68732f2f   ; 0x68732f2f == 1,752,379,183
push   0x6e69622f   ; 0x6e69622f == 1,852,400,175

; Save the current value of the stack pointer (ESP) in the EBX register.
mov    ebx,esp

; Push another 0 onto the stack (remember, EAX still contains 0).
push   eax

; Push the value of the previous stack pointer onto the stack.
; (This is the same as pushing ESP+4, since the previous PUSH instruction
;  implicitly decremented the stack pointer by 32 bits.)
push   ebx

; Save the current value of the stack pointer (ESP) in the ECX register.
; (Presumably, it is either used again later in the function, or the interrupt
;  that we're about to call requires some input value to be passed in ECX.)
mov    ecx,esp

现在堆栈如下所示(在x86上,堆栈向下增长,因此最旧的值位于顶部):

╔═════════════════╗           direction of growth
║        0        ║                   |
╠═════════════════╣                   |
║    0x68732F2F   ║                   V
╠═════════════════╣
║    0x6E69622F   ║ <----
╠═════════════════╣     |
║        0        ║     |
╠═════════════════╣     |
║ pointer to ...  ║  ----
╚═════════════════╝            (lowest address)
; Place the value 0xB (11) in the AL register, which is the bottom 8 bits of EAX.
; The value in EAX specifies the sub-function to be executed when the interrupt is raised.
; (Note that setting only the bottom 8 bits is safe because we already zeroed EAX.)
mov    al,0xb

; Raise an interrupt, passing control to interrupt vector 0x80.
; On Unix systems, this is how you make a system call.
; This is why we went through all the trouble of pushing those values onto
; the stack: this is how parameters are passed through to the system call.
int    0x80 

不是Unix大师,我必须查找系统调用号码(在本例中为0xB)才能看到它的作用。结果是,0xB映射到sys_execve,它执行指定的二进制文件。它期望指向文件的指针在EBX中执行,指向ECX中的命令行参数的指针,以及指向EDX中的环境块的指针。回想一下,在上面的代码中,这些寄存器都被初始化为包含指向堆栈各个位置的指针。