Reputation: 97
i am new to debugging. I came through this code which states that it spawns a shell prompt when executed.
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
Please clearly explain what is actually going on in the registers and the memory here.
Upvotes: 2
Views: 1672
Reputation: 244732
; 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
The stack now looks like the following (on x86, the stack grows downwards, so the oldest value is at the top):
╔═════════════════╗ 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
Not being a Unix guru, I'd have to look up the system call number (in this case, 0xB) to see what it does. Turns out, 0xB maps to sys_execve
, which executes the specified binary. It expects a pointer to the file to execute in EBX
, a pointer to the command-line parameters in ECX
, and a pointer to the environment block in EDX
. Recall that, in the foregoing code, these registers were all initialized to contain pointers into various places on the stack.
Upvotes: 3
Reputation: 12347
A few hard-coded values are being pushed onto the stack, then a pointer into the stack itself is pushed. Finally, the EAX register is left with the final loaded value, and EBX, ECX and ESP are left pointing to locations on the stack.
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
As @PaulR suggests, that must be an execve
and so it'd be something close to this in C:
char *arg[2] = { "/bin//sh", 0 };
execve(arg[0], &arg[0], envp);
(The envp
value is not available in this code snippet. It would be whatever is in EDX. If that's the entire program, presumably EDX is zero on entry - and on linux, a null pointer is interpreted as an empty environment list.)
Upvotes: 3