This is an old revision of the document!
Primjer - Zadatak s Hacknite platforme - Packer
Dana je binarna datoteka bez prevelikog konteksta (osim da je obfuscirana). Iako naziv zadatka odaje o čemu je riječ, korisno je znati kako prepoznati pakiranu datoteku. Najčešći pokazatelj je izlaz funkcije strings koja vraća besmislene stringove (ne postoje nazivi funkcija itd…). Drugi pokazatelj su besmislene instrukcije koje se izvršavaju tokom debuggiranja. Ideja je da se time oteža ručni reversing. Dva su načina kako se pakirane datoteke mogu otpakirati. Prvi je da se sazna kojim programom je datoteka zapakirana, a drugi je ručno unpackanje. Proći će se oba načina na primjeru zadatka Packer.
1. Otkrivanje packera
Kako bi se otkrio koji paker je korišten mogu se iskoristiti alati/usluge za analizu, poput VirusTotal. VirusTotal jest web aplikacija koja analizira malware korištenjem pattern matchinga i sl. Također, prepoznaje poznate packere ako su korišteni za obfusciranje datoteke. Rezultat analize nam vraća naziv kiteshield. Kiteshield je open source packer za datoteke ELF formata. Može se pronaći ovdje ovdje. Kako bi se datoteka unpackala mogu se pronaći razni writeupovi na temu (npr. ovdje). Korištenjem skripte za unpackanje jednostavno se dobije originalna main funkcija.
Jednom kada se dobije originalna main funkcija, lagano se dođe do flaga.
2. Ručno unpackanje
Recimo da se radi o packeru koji nije poznat, tj. ne postoje već dostupne skripte za unpackanje. Ne preostaje ništa osim ručne analize koda. Dobri packeri otežavaju ručnu analizu korištenjem puno nebitnih instrukcija što čini kod nerazumljivim. Međutim, većina packera imaju zajedničko svojstvo da pozivaju syscall-ove kojima alociraju prostor u memoriji (mmap) u koje se zapisuju dekriptirani payload tj. binarna datoteka, postavljaju potrebne permissione (mprotect), otvaraju razne datoteke poput libc.so (read) itd… Znajući to, debuggiranje se može olakšati zaustavljanjem na pozivima instrukcije syscall.
Prolaskom kroz program vide se sljedeći syscall pozivi:
1. getpid 2. stat 3. open 4. read 5. close 6. exit
Nakon poziva read program izlazi te je očito da se radi o nekoj vrsti anti-debugging mjere. Prije exita poziva se syscall read s putanjom /proc/%d/status gdje je %d pid programa. Primjer djelomičnog ispisa jest sljedeći:
Unutar ispisa jedini indikator radi li se od debuggiranju jest TracerPid. Ispis statusa programa koji trenutačno nisu debuggirani imaju postavljen TracerPid na vrijednost 0. Kada bi se ispis izmijenio na 0, postoji mogućnost da se mjera zaobiđe.
Uz pomoć naredbe patch ručno se izmijeni njegova vrijednost.
Tok programa se izmijenio, sada se umjesto exita poziva syscall fork.
Nastavljanjem kroz program, pozivaju se razni syscallovi sve dok ne dođe do syscallova wait i exit.
Postavljanjem follow-fork-mode na child nakon syscall-a fork debuggiranje se prebacuje ne forkani process.
Praćenjem syscallova vidimo sličan uzorak kao i u parent procesu. Nakon poziva setrlimit ponovno se dohvaća pid te gleda /proc/%d/status.
Istom metodom izmijeni se TrackerPid i nastavi s debuggiranjem. Dolazi se do raznih poziva mmap, memset i read. Prolaskom kroz njih virtualna memorija sada liči na normalan proces.
Očito je da je proces unpackanja završio. Korištenjem naredbe “dump binary memory dump.out 0x0000000800000000 0x0000000800005000” dobije se dump binarne datoteke.
Iako je zbog načina obfuskacije koju kiteshield koristi kod obfusciran (ne može se pokrenuti) za ovaj zadatak to je dovoljno jer je string za flag hardkodiran te se može dobiti naredbom strings.
“The second layer of encryption (referred to in the codebase as the “inner layer”) consists of individual encryption of almost every function in the input binary (identified via the symbol table at pack-time). A ptrace-based runtime engine is triggered on every function entry and exit via replacement of each function's entry instruction and all its return instructions with int3 instructions (which deliver a SIGTRAP when executed). Upon receiving a trap, the runtime engine looks up the current function and encrypts or decrypts it as needed such that only functions within the current call stack are decrypted at any point in time.”
Ideja je da int3 instrukcije šalju signal ptraceru koji dinamički dekriptira funkciju koja se izvršava. Izgled main funkcije u dobivenom dumpu jest:
Jasno je da je funkcija ne izvršiva zbog invalidnih instrukcija.
Za usporedbu, ovo je izgled iste funkcije kroz binarnu datoteku dobivenu korištenjem jednih od skritpti za unpackanje kiteshielda:









