我是新手调试。我通过这段代码说明它在执行时会产生一个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
请清楚地解释寄存器和内存中实际发生的事情。
答案 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
中的环境块的指针。回想一下,在上面的代码中,这些寄存器都被初始化为包含指向堆栈各个位置的指针。