Techniques-> JMP,CALL,POP

In this shellcode, we talk about a simple hello world program.

As opposed to just using simple assembly, we'll keep the shellcoding rules in our mind while we try to print hello world on the screen.

  1. Remove all 0x00s

  2. Make sure there are no hardcoded addresses of "Hello World". So we have to dynamically try to figure out the address of "hello World"

Remember this hello world code from 2nd article?

global start

section .text

        _start:
        mov rax,1 ;syscall for write.
        mov rdi,1 ;int fd, which is 1 for stdout since we are not storign the  message anywhere rather printing it out
        mov rsi,hello_world ; The  buffer to be printed
        mov rdx,length ; The length of   hello world buffer we calculated in data section
        syscall ; Executes the syscall 1 with arguments we gave. At this point rax  will store the return value from the executed syscall
        mov rax, 60 ; syscall number for exit
        mov rdi, 11 ; Custom error code. Could be anything. 0 in most cases.
        syscall

section .data
        hello_world: db "Hello world! This is Harshit"
        length: equ $-hello_world

Here, we are hardcoding the address of hello_world in rsi. In a shellcode we can not do that.

So, a JMP->CALL->POP technique would be used.

Why this?

Here is how it works: JMP would jump to the specific location where string is defined. That area has a "CALL" instruction which is used to call the shellcode section. This section has a POP instruction.

Remember when you use CALL, the address of that location gets stored on the stack. When we reach POP, we move that address from the stack back into RSI and then we can successfully print it out.

Upon inspecting the objdump, we can see there are a few 0s now that need to be removed.

Here is the updated code

Let's add this shellcode in our C code and test

gcc -fno-stack-protector -z execstack skeleton.c -o skeleton

This is how we can create this small shellcode.

In stack pointer, we can see it initialized by 0x000000..1 right now.

Notice how rsp changes when call shellcode is performed. It stores the memory address of the hello_world array in the call_shellcode section on stack

Further notice what happens to rsi when pop is called. The memory address of hello_world is stored in RSI now.

And then it executes and exits.

Last updated

Was this helpful?