HackCon 2016 - Army of Binaries

By: ohai 8 years ago
CTF

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.

img

So I decide what the hell and give it a shot.

img

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

img

Flag is HACKCON{rolling_up_strings_like_a_pro}


Comments: 6

Unmoderated: 0 Spam: 3

By: AMA 8 years ago

i ama comment


By: ohai 8 years ago

Strong comment

that was a super strong comment…


By: ohai 8 years ago

for py in thon: stuff()


By: anon-peoples 4 years ago

[codeblock]#include <stdio.h>[/codeblock] ok


By: anon-peoples 4 years ago

<scriXpt>alert(1);</script>


By: anon-peoples 4 years ago

img