Ram
Ram

Reputation: 97

Can anyone clearly explain this disassembly?

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

Answers (2)

Cody Gray
Cody Gray

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

Gil Hamilton
Gil Hamilton

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

Related Questions