Search code examples
debuggingassemblyx86disassemblyshellcode

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.


Solution

  • ; 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.