SICEH CTF 2016 - Forenzika
Ta objava vsebuje primere rešitev nalog iz kategorije forenzika na tekmovanju SICEH CTF 2016, ki je potekalo v okviru konference Infosek 2016.
1. Ali mi pošlješ zastavico?
Naloga vsebuje capture.pcap
, v katerem lahko vidimo IRC promet:
> tshark -r capture.pcap
1 0.000000 10.0.2.15 → 164.132.77.237 IRC 77 Request (PING)
2 0.000209 164.132.77.237 → 10.0.2.15 TCP 60 6667→42106 [ACK] Seq=1 Ack=24 Win=65535 Len=0
3 0.065103 164.132.77.237 → 10.0.2.15 IRC 121 Response (PONG)
4 0.065124 10.0.2.15 → 164.132.77.237 TCP 54 42106→6667 [ACK] Seq=24 Ack=68 Win=61060 Len=0
5 2.882969 10.0.2.15 → 164.132.77.237 IRC 77 Request (PRIVMSG)
6 2.883164 164.132.77.237 → 10.0.2.15 TCP 60 6667→42106 [ACK] Seq=68 Ack=47 Win=65535 Len=0
7 9.658845 10.0.2.15 → 164.132.77.237 IRC 110 Request (PRIVMSG)
8 9.659053 164.132.77.237 → 10.0.2.15 TCP 60 6667→42106 [ACK] Seq=68 Ack=103 Win=65535 Len=0
9 17.462950 10.0.2.15 → 164.132.77.237 IRC 82 Request (WHO)
10 17.463138 164.132.77.237 → 10.0.2.15 TCP 60 6667→42106 [ACK] Seq=68 Ack=131 Win=65535 Len=0
11 17.494025 164.132.77.237 → 10.0.2.15 IRC 196 Response (354)
12 17.494047 10.0.2.15 → 164.132.77.237 TCP 54 42106→6667 [ACK] Seq=131 Ack=210 Win=63900 Len=0
13 17.526166 164.132.77.237 → 10.0.2.15 IRC 350 Response (354) (354) (315)
14 17.526187 10.0.2.15 → 164.132.77.237 TCP 54 42106→6667 [ACK] Seq=131 Ack=506 Win=65320 Len=0
15 30.058780 10.0.2.15 → 164.132.77.237 IRC 77 Request (PING)
16 30.058982 164.132.77.237 → 10.0.2.15 TCP 60 6667→42106 [ACK] Seq=506 Ack=154 Win=65535 Len=0
17 30.090906 164.132.77.237 → 10.0.2.15 IRC 121 Response (PONG)
18 30.090927 10.0.2.15 → 164.132.77.237 TCP 54 42106→6667 [ACK] Seq=154 Ack=573 Win=65320 Len=0
19 35.677200 164.132.77.237 → 10.0.2.15 IRC 147 Response (PRIVMSG)
20 35.677231 10.0.2.15 → 164.132.77.237 TCP 54 42106→6667 [ACK] Seq=154 Ack=666 Win=65320 Len=0
21 40.740789 10.0.2.15 → 164.132.77.237 IRC 77 Request (PRIVMSG)
22 40.740961 164.132.77.237 → 10.0.2.15 TCP 60 6667→42106 [ACK] Seq=666 Ack=177 Win=65535 Len=0
23 44.774578 10.0.2.15 → 164.132.77.237 IRC 100 Request (PRIVMSG)
24 44.774758 164.132.77.237 → 10.0.2.15 TCP 60 6667→42106 [ACK] Seq=666 Ack=223 Win=65535 Len=0
25 53.757265 164.132.77.237 → 10.0.2.15 IRC 136 Response (PRIVMSG)
26 53.757304 10.0.2.15 → 164.132.77.237 TCP 54 42106→6667 [ACK] Seq=223 Ack=748 Win=65320 Len=0
27 60.113008 10.0.2.15 → 164.132.77.237 IRC 77 Request (PING)
28 60.113230 164.132.77.237 → 10.0.2.15 TCP 60 6667→42106 [ACK] Seq=748 Ack=246 Win=65535 Len=0
29 60.144681 164.132.77.237 → 10.0.2.15 IRC 121 Response (PONG)
30 60.144702 10.0.2.15 → 164.132.77.237 TCP 54 42106→6667 [ACK] Seq=246 Ack=815 Win=65320 Len=0
Poglejmo vsebino IRC poivedb in odgovorov. Za voljo preglednosti bomo poiskali le sporočila udeležencev v pogovoru:
> tshark -r capture.pcap -T fields -e irc.request -e irc.response | grep PRIVMSG
PRIVMSG ##siceh :Hoj!
PRIVMSG ##siceh :A kdo pozna zastavico za prvo nalogo?
:zshfu!~zshfu@unaffiliated/zshfu PRIVMSG ##siceh :+Evo ti: SVNDVEZ7bWwwX3o0XzBncjN2NG5qM30=
PRIVMSG ##siceh :Tnx!
PRIVMSG ##siceh :A to samo skopiram na site?
:zshfu!~zshfu@unaffiliated/zshfu PRIVMSG ##siceh :+Ne, mislim da mora?? decodeat
Glede na nabor znakov in zaključni "=" lahko prepoznamo, da gre za base64 kodiranje in odkrijemo zastavico:
> python -c 'import base64; print(base64.b64decode("SVNDVEZ7bWwwX3o0XzBncjN2NG5qM30="))'
b'ISCTF{ml0_z4_0gr3v4nj3}'
2. Varno shranjeno
Prejeli smo večje število datotek, med drugim dva squashfs datotečna sistema, ki pa ne vsebujeta zastavica. Opazimo večje število parity datotek s končnico par2
, s katerimi lahko rekonstruiramo manjkajočo datoteko:
> par2 r vol1.par2
...
Repair is required.
1 file(s) are missing.
1 file(s) are ok.
You have 683 out of 1707 data blocks available.
You have 1707 recovery blocks available.
Repair is possible.
You have an excess of 683 recovery blocks.
1024 recovery blocks will be used to repair.
...
Target: "vol3" - found.
Repair complete.
Rekonstruirali smo datoteko vol3
, ki je tudi squashfs datotečni sistem. V sistemu najdemo skrito sliko z zastavico:
> unsquashfs vol3 ... created 1 files ... > ls -a squashfs-root . .. .flagy_the_flagface.png
Našli smo zastavico:
3. Sliki
Dobimo sliko, ki je sestavljena iz dveh delov. Na sliki lahko najdemo 7 razlik v barvah med levo in desno sliko. Če sliko pogledamo s heksadecimalnim urejevalnikom ali programom za arhiviranjem ugotovimo, da je sliki pridružena še ena skrita slika:
Slika razkrije vrstni red razlik, ki si sledijo od leve proti desni. Če vzamemo RGB kode barv razlik in jih pretvorimo v ASCII besedilo, dobimo zastavico: ISCTF{b4rv3_s0_z4k0n}.
4. RSA kriptirano
Za reštev naloge je potrebno poznati osnove o tem, kako deluje algoritem RSA. Modul n je zmnožek dveh naključnih praštevil p in q. Ideja je v tem, da je izračun n, če poznamo p in q trivialen, medtem ko je v drugo smer (faktorizacija števila n) to veliko težji postopek. Dolžina ključa je izražena s tem, kako dolgo število je n (s koliko biti ga lahko zapišemo).
$ openssl rsa -noout -text -pubin -in pubkey.pem
Public-Key: (511 bit)
Modulus:
50:9f:9c:47:b8:14:20:72:c4:d7:ed:53:7e:34:d4:
db:97:4c:47:53:2d:3f:3c:3d:4f:9f:da:e5:f7:d1:
8d:ec:63:b8:a0:13:bf:aa:1f:76:6b:b8:42:6e:2b:
1b:d2:de:66:2c:fd:a4:aa:ee:e1:85:ca:9b:92:f4:
82:bf:f9:df
Exponent: 31337 (0x7a69)
V našem primeru je to 511 bitov. N je torej (če ga zapišemo hexadecimalno): 509f9c47b8142072c4d7ed537e34d4db974c47532d3f3c3d4f9fdae5f7d18dec63b8a013bfaa1f766bb8426e2b1bd2de662cfda4aaeee185ca9b92f482bff9df
ali
$ python -c "print 0x$(openssl rsa -noout -text -pubin -in pubkey.pem | grep -v Exponent | tail -n +3 | sed 's/://g' | tr -d ' \n')"
4222594191311997485624992597489635906408741310509894971414696538261716350795724330045640490381259588829035404140033500407093360949250609046741392774134239
511 bitov je sicer razmeroma malo, a da ne bilo treba uporabiti grobe sile pri razbijanju n, lahko opazimo med zanimivi dejstvi naslednje
"- število 69071992818733333851100536223157916181548476378715458801031602869124758841767 deli 42225941913119974856249925974896359064087413105098949714146965382617716350795724330045640490381259588829035404140033500407093360949250609046741392774134239"
Torej je p = 69071992818733333851100536223157916181548476378715458801031602869124758841767
. Drugo praštevilo "q" pa lahko dobimo tako da delimo "n" s "p".
$ echo "4222594191311997485624992597489635906408741310509894971414696538261716350795724330045640490381259588829035404140033500407093360949250609046741392774134239 / 69071992818733333851100536223157916181548476378715458801031602869124758841767" | bc
61133232428857449051886632314082993000036443775405917749161008256504798692617
q = 61133232428857449051886632314082993000036443775405917749161008256504798692617
.
Zdaj lahko enostavno z Razširjenim Evklidovim algoritmom dobimo inverz od e (31337) po modulu fi(n) = fi(p) * fi(q) = (p - 1) * (q - 1).
d = 757013567565204131673140645648810496288869664691725115659053679419035723227164303961482187508171407222410526886138624029282466347111431838889790271910457
Sporočilo lahko potem dešifriramo kot modularno potenciranje z d - m^d mod n.
Oz. najlažje je kar uporabiti orodje RsaTool, ki nam zgradi zaseben ključ.
$ ./rsatool.py -p 69071992818733333851100536223157916181548476378715458801031602869124758841767 -q 61133232428857449051886632314082993000036443775405917749161008256504798692617 -e 31337 -o privkey.pem
Tukaj velja še omeniti, da zasebni ključ po analogiji z javnim ključem (e, n), ni samo (d, n) ampak vsebuje tudi e, p in q (ter nekaj drugih koeficientov, ki pospešijo izračun). Tako da je možno iz zasebnega ključa vedno izračunati javni ključ.
Ugotovimo še, da je flag.enc
base64 encodan, če ga dekodriamo v flag.tmp
, lahko enostavno uporabimo prej ustvarjen privkey.pem
$ openssl rsautl -decrypt -in flag.tmp -inkey privkey.pem
ISCTF{eXp0RT_RE5Tr1ct3d!}