我是调试新手。我看过这段代码,指出该代码在执行时会产生一个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
请在这里清楚说明寄存器和存储器中实际发生的情况。
最佳答案
; 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
中执行指向环境块的指针。回想一下,在前面的代码中,这些寄存器都被初始化为包含指向堆栈中各个位置的指针。