A hétvégén a Senkiháziak csapata újra összeállt, hogy összemérje tudását a Föld kétség kívül legidegörlőbb Capture the Flag játékán, a DDTEK inkvizítorai által összeállított Defcon CTF-en. A selejtező idén is 48 órán át tartott, és végül 303 csapatnak sikerült megütnie a minimális, 100 pontos szintet.
A tavalyi szárnypróbálgatás után idén már fontos tapasztalatok birtokában, és valamivel nagyobb/aktívabb csapattal vágtunk neki a küzdelemnek, igaz kicsit későn - a szombat hajnal 2-es kezdés valahogy mindenkinek korainak tűnt.
A feladattípusok ismerete, illetve a másod- és harmadnap kombinált Zen-hatásának köszönhetően viszonylag hamar túllendültünk a 200-as kritikus határon (ami azt jelenti, hogy nem csak a trivia kérdést sikerült megoldani), majd a B200-zal dupláztunk egyet, innen pedig nem volt megállás, végül 2300 ponttal a 39. helyen végeztünk, ami egyrészt mind pozíció, mind pontszám tekintetében jelentős előrelépés az egy évvel ezzelőtti eredményhez képest (akkor 1100 ponttal 60. helyen landoltunk), másrészt úgy érzem, az élmezőnyhöz képest sem teljesítettünk olyan rosszul.
Összességében tehát elégedett vagyok az eredménnyel, de jövőre még keményebben kell tolni, az elmúlt 48 óra szakmai és stratégiai tapasztalatai ebben garantáltan segíteni fognak :)
A megoldott feladatok megoldásait természetesen igyekszem közzétenni (ha a csapat többi tagja is úgy akarja), kezdetnek álljon itt a már emlegetett UR100 és B200:
Frissebb: Dnet közben megírta a GB300-at és az urandom300-at is.
urandom100
Az urandom kategóriában - ahogy a név is mutatja - teljesen véletlenszerű, máshova be nem sorolható feladatok tartoztak. Ezek közül az elsőben egy kérdésre kellett válaszolni: "How many developers;) did it take to secure Windows 8?" (Hány fejlesztőre volt szükség a Windows 8 biztonságossá tételéhez?). Miután a 0 nem működött, tájékozottabb kollegák Steve Ballmer híres beszédére irányították a figyelmet. Ebben a "developers" 14-szer hangzik el, de ez sem volt jó megoldás. A megoldás, az ebben a videóban elhangzó 152 "developers" volt, amit mi végül brute-force módszerrel találtunk ki - a rendszerben volt ratelimit, de nekünk még volt időnk :)
B200
A Binary L33tness feladatai már sokkal szakmaibb kihívás elé állították a próbálkozót: binárisok statikus illetve dinamikus analízisével kellett meghatározni, hogy egy távoli kiszolgálón futó szolgáltatás milyen bemenet hatására adja vissza a key.txt-ben tárolt karaktersorozatot, amiért a pontok jártak. A feladatok egy ideig egy kaptafára épültek: a folyamat bejövő kapcsolat esetén forkolja magát, a gyermek pedig chrootol egy meghatározott felhasználó könyvtárába, és felveszi annak jogait, majd négy "varázsszóra" vár:
Idáig a B200-zal nem volt probléma, minden világosan látszott a visszafejtett kódból. Mivel egy FreeBSD ELF állományról volt szó, gyorsan telepítettem egy virtuális gépet, amin létrehoztam a megkövetelt felhasználót (grease), ez után pedig depth tavalyi módszerével tudtam debugolni:
# set PID=`ps a | grep bin200 | grep -v grep | tail -1 | awk '{print $1}'` ; gdb -q bin200 --pid=$PID -x bin200.script
Ennél és a többi feladatnál is jó szolgáltatot tettek a GDB parancsszkriptjei (lásd -x kapcsoló), melyekben első sorban a breakpointokat gyűjtögettem, de komplexebb (pl. feltételhez kötött) utasítások is rögzíthetők bennük.
A vicces rész ezután következett. A varázsszavak vétele után a szolgáltatás beolvas egy újabb szót, melynek értéke maximum 1024 lehet, majd lefoglal két ekkora puffert, melyeket szintén a socketből olvasott adattal tölt fel. Ha a pufferek tartalma megegyezik az alkalmazás kilép, ellenkező esetben rájuk ereszt egy transzformációs eljárást, ami a nagy komplexitás és a rengeteg bitművelet miatt minimum obfuszkációnak, de inkább kriptónak tűnt:
Amennyiben a transzformációk eredménye megegyezik, a program kiadja a megoldást.
Kriptográfiai eljárások detektálására léteznek automatizált szoftverek, ezeket rá is eresztettem a binárisra, de nem találtak semmit. Itt elkövettem azt a hibát, hogy megpróbáltam találni valalamilyen trükköt, amivel ki lehet cselezni az összehasonlításokat - a dolgot nem könnyítette meg, hogy a decompiler rosszul értelmezte a feltételeket, kikerülhetőnek mutatva őket, miközben az assembly kódban nem volt ilyen hiba. Csak órákkal később jutott eszembe rákeresni a fenti képen is látható egyik konstansra. Néhány irreleváns találat után a Google a Tangle hash algoritmust ajánlotta figyelmembe, melynek inicializációs vektorai éppen megegyeztek a kódban látottakkal. A további keresés hamar rávilágított, hogy az egykori SHA-3 jelöltben komoly ütközéses problémát találtak, ami éppen passzolt a feladathoz: adj két különböző bemenetet, ami azonos hash értéket produkál!
Ezek után nem volt más dolgom, mint előtúrni a Tangle referencia implementációját a web mélyéről (ez nehezebb volt mint gondoltam), majd leforgatni a DTU támadó eszközét, és generálni egy ütközést - meglepő módon a művelet nem igényelt észlelhető számítási/memória teljesítményt. Ez után már csak be kellett küldenem az ütközést okozo byte sorozatot, ügyelve a puffer méretek pontos beállítására, és a szerver máris egy 200 pontot érő kulccsal jutalmazott:
import socket import time HOST = '140.197.217.155' # The remote host #HOST = '172.16.200.131' # The remote host PORT = 18703 # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) print "Sleeping..." # time.sleep(3) #Now you can attach the debugger print "Wake up Neo!" s.send("\x94\xa4\xc2\x65") s.send("\xfe\x73\x2d\x6f") s.send("\xee\xf8\x14\xcb") s.send("\x6e\xc8\xa1\x26") s.send("\x28\x00\x00\x00") s.send("\xc8\x19\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x80") s.send("\xc8\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") data = s.recv(1024) s.close() print '%s' % (repr(data))
A Defcon writeup gyűjteménye itt található.
|Z| 2012.06.04. 15:58:55
EQ · http://rycon.hu 2012.06.05. 00:17:38