It’s been a while. Kinda let this thing go but it’s come back out of a need to get flask working with uwsgi with nginx (sorry, tornado, you’re dead to me). Anywho, the bulk of the site has been reconstructed, this time in python. I’ll drop some source on github here once I finish cleaning everything up. Also, figured I needed something fresh to talk about to give this thing a test so I took a time out and hit up HackCon. The army of binaries challenge looked right up my alley so I went with it.
The service presents you a random binary every time asking you to get the correct input so as to run the “yes” condition in the binary. The game has 31 rounds. Go fight! nc 52.88.137.165 8000
NC’ing to the box we are greeted with a binary being dumped to the screen. There’s a bit of text mixed in there as well. So my first point of business was to capture the binary (only the binary, not the extra text) to a file to see how it operated. So we end up with something like:
binary = recvuntil(csock, 'You got it? ')
with open('bin.bin', 'wb') as f:
f.write(binary[:-12])
Running strings on the binary yields the standard faire but also what appears to be a hash.
So I decide what the hell and give it a shot.
Fantabulous, it works. At this time I also noticed the .c file referenced in strings corresponds. Looks like something we can key in on, hopefully all the way through all 31 binaries.
So I decided to go with this and ended up with a quick, down and dirty script to test it out. Here it is, in all its glory:
#!/usr/bin/env python
import socket, subprocess
host,port = '52.88.137.165', 8000
def recvuntil(s, c):
b = ''
while not b.endswith(c):
x = s.recv(1)
if not x:
raise Exception('close early')
b += x
return b
def main():
flag = ''
for i in range(31):
x = recvuntil(csock, 'Round ')
round_num = recvuntil(csock, '\n').strip()
print 'Round: %s' % (round_num)
binary = recvuntil(csock, 'You got it? ')
with open( round_num + '_bin.bin', 'wb') as f:
f.write(binary[:-12])
print 'wrote binary\n'
for stuff in subprocess.check_output(['strings', round_num + '_bin.bin']).split():
if stuff.endswith('.c') and not stuff.startswith('crtstuff'):
print 'sending: %s' % (stuff[:-2])
csock.send(stuff[:-2] + '\n')
break
subprocess.check_output(['rm', round_num + '_bin.bin'])
if round_num == '31':
for num in range(100):
flag += csock.recv(1)
if flag.endswith('}'):
break
print flag
if __name__ == '__main__':
csock = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
csock.connect ( (host, port) )
csock.settimeout(5)
main()
So it snags a binary, writes it to disk (yuck, I know), runs strings on it (yup, also yuck) grabbing out the referenced .c file, submits that value back to the server, rinse, repeat til we get to the end. This probably could have been done fairly trivially in pwntools.
And now the fruits of our labor
Flag is HACKCON{rolling_up_strings_like_a_pro}