Search code examples
bashshellassemblybuffer-overflowstack-smash

Loading "/bin/sh" into a register


I'm trying to write ASM code to spawn a shell.

I've figured out that the syscall number for __execve is 0x3b or 59.

I need to send "/bin/sh" as the first parameter, a pointer to {"/bin/sh", NULL} as the second parameter and NULL as the third parameter.

By the convetions of x86_64 ASM on the Intel architecture - the first parameter is written into the RDI register, the second parameter is written into the RSI register and the final parameter is written into the RDX register.

This is my code:

global _start

section .text

_start:

jmp message

mystart:
    xor     rax, rax
    push    rax
    push    rax
    pop     rdx     ; third parameter - NULL
    pop     rdi     ; first parameter - "/bin/sh"
    mov     rax, rdi    
    push    rax
    push    rsp
    pop     rsi     ; second parameter - pointer to {"/bin/sh", NULL}
    xor     rax, rax
    mov     al, 0x3b
    syscall


    xor rax, rax
    mov al, 0x3c
    xor rdi, rdi
    mov dil, 0x0a
    syscall

message:

    call mystart
    db "/bin/sh"

section .data

I use the following instructions to compile and link the code.

yasm -f elf64 shell.asm -o shell.o
ld -o shell.out shell.o

The GDB dump of the _start function is as follows:

Dump of assembler code for function _start:
 0x0000000000400080 <+0>:   jmp    0x4000a3 <_start+35>
 0x0000000000400082 <+2>:   xor    rax,rax
 0x0000000000400085 <+5>:   push   rax
 0x0000000000400086 <+6>:   push   rax
 0x0000000000400087 <+7>:   pop    rdx
 0x0000000000400088 <+8>:   pop    rdi
 0x0000000000400089 <+9>:   mov    rax,rdi
 0x000000000040008c <+12>:  push   rax
 0x000000000040008d <+13>:  push   rsp
 0x000000000040008e <+14>:  pop    rsi
 0x000000000040008f <+15>:  xor    rax,rax
 0x0000000000400092 <+18>:  mov    al,0x3b
 0x0000000000400094 <+20>:  syscall 
 0x0000000000400096 <+22>:  xor    rax,rax
 0x0000000000400099 <+25>:  mov    al,0x3c
 0x000000000040009b <+27>:  xor    rdi,rdi
 0x000000000040009e <+30>:  mov    dil,0xa
---Type <return> to continue, or q <return> to quit---
 0x00000000004000a1 <+33>:  syscall 
 0x00000000004000a3 <+35>:  call   0x400082 <_start+2>
 0x00000000004000a8 <+40>:  pop    rsp
 0x00000000004000a9 <+41>:  (bad)  
 0x00000000004000aa <+42>:  (bad)  
 0x00000000004000ab <+43>:  .byte 0x69
 0x00000000004000ac <+44>:  outs   dx,BYTE PTR ds:[rsi]
 0x00000000004000ad <+45>:  pop    rsp
 0x00000000004000ae <+46>:  (bad)  
 0x00000000004000af <+47>:  jae    0x400119

As you can see the (bad) instructions are caused by db "/bin/sh", what is wrong with this string? What is a (bad) instruction? How do I debug such problems in the future?


Solution

  • ① You cannot load a string into a register, only a pointer to a string.

    ② Your stack magic is merely wrong. Move one of the doubled push rax to just below pop rdi, and the program works for me.