[PYTHON] I've been demonstrating Write up for #seccon CTF online qualifying on #ssmjp

I have been demonstrating how to use dpkt to solve "Find the key!", A 200-point problem on the network and Web of the SECCON CTF online qualifying held in late January.

For more information on SECCON CTF itself, please see the official website http://2013.seccon.jp/. Also, for problems and how to solve them, many people have already written write up, so please see that as well.

The problem was that the pcap file was passed in and found the key in it. The content of the pcap file is Ping communication, HTTP communication is tunneled to the data part of Ping, and the image kagi.png was GET in it. The point was that the image should be restored.

First, open the file in question.

>>> import dpkt
>>> p=dpkt.pcap.Reader(open("seccon_q1_pcap.pcap","rb"))

If you look at the packet with Wireshark, you can see that the packet larger than about 100 bytes contains the desired data. Therefore, the data part of the packet larger than 100 bytes is extracted from the list.

>>> pl=[]
>>> for t,b in p.readpkts():
...     ip=dpkt.ethernet.Ethernet(b).data
...     if ip.len > 100:
...             pl.append(ip.data.data.data)

If you look at the contents of the list, you can see that there are images from pl [2] to pl [6].

First, look at pl [2]. This also includes the HTTP response header, so I'll remove it. Since the first 1 byte of a PNG file starts with 0x89 and the next 3 bytes are ASCII and PNG, search for PNG and extract from the 1 byte before it.

>>> pl[2].index("PNG")
285
>>> PNG=pl[2][284:]

Then from pl [3] to pl [6], but if you connect them all to PNG, it won't work. Contains something other than (a part of) the PNG image. The content of kagi.png is known to be 2795 bytes from the Content-Length value in the response header.

>>> pl[2][216:238]
'Content-Length: 2795\r\n'

On the other hand, if you connect all pl [3] to pl [6], it will be larger than the above value.

>>> len(PNG)
768
>>> l=len(PNG)
>>> for n in range(3,7):
...     l+=len(pl[n])
... 
>>> l
2908

So, if you look at how much extra each packet from pl [3] to pl [6] has, you can see that 28 bytes should be removed. ..

>>> 2908 - 2795
113
>>> 113 / 4
28

You can tell if there is a remainder 1 and whether to remove it at the beginning or the end by looking at the end of pl [6].

>>> pl[6][-10:]
'\x00IEND\xaeB`\x82\x00'

So I found that I should connect pl [3-6] [28:] and remove the last byte.

285
>>> PNG=pl[2][284:]
>>> for n in range(3,7):
...     PNG=PNG+pl[n][28:]
... 
>>> len(PNG)
2796
>>> PNG=PNG[:-1]
>>> open("kagi.png ","w").write(PNG)

After that, open the written kagi.png with an appropriate image viewer and you can see the flag.

As I noticed later, even if I check the position where the HTTP response starts with pl [2], I can see that the first 28 bytes should be removed.

>>> pl[2][:50]
'\xd5 \x08\x80\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x02\x00\x00\x00\x01\x00\x00\x04\x00\x00\x01\x028HTTP/1.1 200 OK\r\nDate:'
>>> pl[2].index("HTTP")
28

Recommended Posts

I've been demonstrating Write up for #seccon CTF online qualifying on #ssmjp
Seccon beginners ctf 2020 write up (mask)
CTF beginners just study pwn ~ "cheer_msg" from SECCON 2016 Online qualifying ~