codezen.fr code hacking, zen coding

30Apr/12Off

PlaidCTF 2012 – Practical Packets 200 – Torrents Writeup

Posted by aXs

"It turns out that robots, like humans, are cheap and do not like paying for their movies and music. We were able to intercept some torrent downloads but are unsure what the file being downloaded was. Can you figure it out?"

We get a pcap file with the P2P part of a BitTorrent exchange between 2 peers.

Hopefully Wireshark has a fairly complete BitTorrent dissector which we will use to get the "pieces" of data.

According to the protocol specification, data is transferred in pieces that have an index and an offset. We need to extract each pieces with its index and offset and a Python script will reorder them.

tshark -r torrent.pcap -R 'bittorrent.piece.data' -T fields -e bittorrent.piece.index -e bittorrent.piece.begin -e bittorrent.piece.data -E separator=\| > torrents.dump
#!/usr/bin/python

import sys
import struct

if len(sys.argv) ==2:
  print "Parsing "+str(sys.argv[1])
else:
  print "Usage: python "+sys.argv[0]+" file.pcap"
  exit(10)

pcap=file(sys.argv[1],"r")
out=file(sys.argv[1]+".hex","w")

data = {}
for p in pcap:
  a = p.split("|")

  index = int(a[0], 16)
  offset = int(a[1], 16)

  print 'Index', index, 'Offset', offset

  order = "%08x" % index + "_" + "%08x" % offset
  data[order] = a[2].split(":")

for key in sorted(data.iterkeys()):
  print key + "\n"
  for b in data[key]:
    out.write(chr(int(b,16)))

pcap.close()
out.close()

$ file torrents.dump.hex
torrents.dump.hex: bzip2 compressed data, block size = 900k
$ mkdir key ; cd key ; tar xvfj ../torrents.dump.hex
key.mp3
key.txt
$ cat key.txt
t0renz0_v0n_m4tt3rh0rn

The key is: t0renz0_v0n_m4tt3rh0rn

PS: notice the useless MP3 file just to make the archive and so the bittorrent transfer bigger 😉

Share
4Mar/12Off

Insomni’hack 2012 Network PCAP Write-ups

Posted by aXs

In this challenge we 2 files: 1 PCAP, 1 Python

The PCAP file contains a dialog between a client and server that goes like this:

> = client to server
< = server to client > 8e67bb26b358e2ed20fe552ed6fb832f397a507d:3daf723376f823eceeb314c8fa60e47b1ba23633
< 5f367ff47fff772986cca54219fa167175353dc7 > 78be5fe51f264a4067463bad57022348
< 3290452b9a9f6d18523347dd1daa54a1e09195a7 > 94817a6b1d833e1ffb4fcb2aa7dd14143dc5759e>_<8b060ba4b309e73abd079d8f0128056c07b78cad < Bienvenue, superuser. Le lieu du rendez-vous n'est pas encore defini. The original Python file goes like this:

#!/usr/bin/python2

import SocketServer
import socket, sys, hashlib, random


if __name__ == "__main__":
    HOST, PORT = sys.argv[1], 9999
    USER = raw_input("Utilisateur : ").strip()
    PASS = raw_input("Mot de passe : ").strip()
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((HOST, PORT))

    try:    
        data = hashlib.sha1(USER).hexdigest()+":"+hashlib.sha1(hashlib.md5(hashlib.sha1(PASS).hexdigest()+hashlib.sha1(PASS).hexdigest()+hashlib.md5(USER).hexdigest()).hexdigest()).hexdigest()
        sock.sendall(data + "\n")

        challenge = sock.recv(41).strip()
        sock.sendall(hashlib.md5(hashlib.sha1(PASS).hexdigest()+"SuperSalt"+hashlib.md5(USER+challenge).hexdigest()).hexdigest() + "\n")

        challenge = sock.recv(41).strip()
        sock.sendall(hashlib.sha1(PASS).hexdigest()+">_<"+hashlib.sha1(challenge+hashlib.md5(USER).hexdigest()).hexdigest() + "\n")
        print sock.recv(1024)
    except:
        print sock.recv(1024)

    sock.close()

We need to get updated information on the meeting location so we need to do a replay attack on this service.

We are going to map the network stream to the python code:

Handshake

> 8e67bb26b358e2ed20fe552ed6fb832f397a507d:3daf723376f823eceeb314c8fa60e47b1ba23633

sha1(user) : sha1(sha1(pass)+sha1(pass)+md5(user))

Challenge 1:

< 5f367ff47fff772986cca54219fa167175353dc7 > 78be5fe51f264a4067463bad57022348

md5(sha1(pass)+"SuperSalt"+md5(user+challenge))

Challenge 2:

< 3290452b9a9f6d18523347dd1daa54a1e09195a7 > 94817a6b1d833e1ffb4fcb2aa7dd14143dc5759e>_<8b060ba4b309e73abd079d8f0128056c07b78cad sha1(pass)+">_<"+sha1(challenge+md5(user)) We can deduce: sha1(user) = 8e67bb26b358e2ed20fe552ed6fb832f397a507d sha1(pass) = 94817a6b1d833e1ffb4fcb2aa7dd14143dc5759e Google bruteforcing sha1(user) gives "superuser", which match the plain text welcome message "Bienvenue, superuser". We can also Google bruteforce the challenges but that's useless. user = "superuser" challenge1 = "4283399" challenge2 = "3593819" So we know USER, now we need PASS. But we only have sha1(pass) and it cannot be Google bruteforced. But do we really need to know PASS ? If you look closely in the code above, you will see we only use the sha1 of PASS, never anything else. Since we know USER, we can carry a replay attack. We remove all reference to PASS and put directly the sha1(pass) string.

#!/usr/bin/python2

import SocketServer
import socket, sys, hashlib, random


if __name__ == "__main__":
    HOST, PORT = "10.13.37.12", 9999
    USER = "superuser"
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((HOST, PORT))

    try:    
        sock.sendall("8e67bb26b358e2ed20fe552ed6fb832f397a507d:3daf723376f823eceeb314c8fa60e47b1ba23633" + "\n")

        challenge = sock.recv(41).strip()
        sock.sendall(hashlib.md5("94817a6b1d833e1ffb4fcb2aa7dd14143dc5759eSuperSalt"+hashlib.md5(USER+challenge).hexdigest()).hexdigest() + "\n")

        challenge = sock.recv(41).strip()
        sock.sendall("94817a6b1d833e1ffb4fcb2aa7dd14143dc5759e>_<"+hashlib.sha1(challenge+hashlib.md5(USER).hexdigest()).hexdigest() + "\n")
        print sock.recv(1024)
    except:
        print sock.recv(1024)

    sock.close()

All done.

Share