SharifCTF 7 – Bsniff

Bsniff was a packet capture file consisting of DNS requests to blockchain.info and GET requests of the form blockchain.info/q/addressbalance/[bitcoin address]?confirmations=6. Here is a Wireshark screenshot with those things:
screen-shot-2016-12-19-at-11-34-16-pm

Looking at the HTTP packet details, we can see that the User-Agent is python-requests, suggesting that this pcap basically consists of a Python script making requests to the blockchain API, asking for the bitcoin balance of a bunch of addresses. Clearly these bitcoin addresses are the interesting part of the pcap, so let’s use scapy to extract them:

>>> a = readpcap('bsniff.pcap')
>>> addresses = []
>>> for p in a:
...     try:
...         s = p.load
...         if s.find('GET /q/addressbalance/')==0:
...             conf_ind = s.find('?confirmations')
...             address = s[22:conf_ind]
...             addresses.append(address)
...     except:
...         pass
... 

Actually, it turns out that this adds each address twice because each packet is duplicated, as you can see in the Wireshark screenshot (I assume this is because of the out-of-order TCP packets, though I’m not sure why that happened). We can confirm and fix this:

>>> for i in range(0,len(addresses),2):
...     if addresses[i]!=addresses[i+1]:
...         print 'uh oh'
...
>>> addresses = [addresses[2*i] for i in range(len(addresses)/2)]

At this point we spent a bunch of time looking up various addresses on blockchain, trying to see if they were related to each other in some way or if they made transactions recently. It seemed like most of them were part of the Discus Fish mining pool, but we didn’t find anything particularly interesting that could lead to a flag. Eventually, Jon noticed that some of the HTTP responses returned a 500 Internal Server Error instead of 200 OK, which was pretty weird:

screen-shot-2016-12-19-at-11-52-40-pm

Looking more closely, the bitcoin address being requested here is “1AKe3rg4SzdSzR9?nG3wddKkbnstFW3JzU,” which is not a valid address because it contains a question mark. We can filter these packets out:

>>> questions = [add for add in addresses if '?' in add]
>>> len(questions)
41

The obvious thing to try now is filling in the question marks to make valid bitcoin addresses, and this turns out to be right. We used requests to find the correct characters:

>>> import requests
>>> alphas = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> tups = [] # tups will contain (address, corresponding character that fills the question mark) tuples
>>> for question in questions:
...      found = False
...      for c in alphas:
...          req_address = 'https://blockchain.info/q/addressbalance/'+question.replace('?',c)+'?confirmations=6'
...          r = requests.get(req_address)
...          if r.status_code==200:
...              found = True
...              tups.append((question,c))
...              break
...      if not found:
...          print 'nothing found for', question
... 
>>> ''.join([tup[1] for tup in tups])
'be6ai1ed31a1fb718r18efeFe627Sb2ec5d39dhTC'

Unfortunately, directly reading the missing characters in packet order doesn’t give a flag. However, we can see the letters “SharifCTF” and a bunch of hex characters, so these have to be the correct characters, just in the wrong order. We were stuck here for a bit and tried wrong things like taking bitcoin balances, but eventually we looked more closely at the addresses corresponding to the first few characters:

S -> 1?wF9bkpiG6YULrDsC5Z7C1kG3vcR4pP5
h -> 1D?1XsL3scgZqCGJfB7Hx5vYNy7Qf9becd
(skipping "a" because it appears multiple times)
r -> 1GBZ?hceFBsexguZEJz4k4cTWSEfKq1fkx 
i -> 17eNk?Xo1Kc7KL59H1ndqkXE8USob2dghC

The question marks are in the 2nd, 3rd, etc. positions! Let’s sort by question mark position:

>>> ''.join([tup[1] for tup in sorted(tups, key=lambda tup:tup[0].find('?'))])
'8Sfhae8ri11fdC5T7F932dbee1b12de3ea7e1cb66'

Okay, so the “SharifCTF” part and the hex characters of the flag share some question mark positions, but we can manually extract the “SharifCTF” part to get the final flag: SharifCTF{8fe811d57932dbee1b12de3ea7e1cb66}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s