User Tools

Site Tools


rev2_ghidra

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rev2_ghidra [2025/10/31 17:08] mbunicrev2_ghidra [2025/12/01 11:40] (current) – external edit 127.0.0.1
Line 1: Line 1:
 ==== rev2 ==== ==== rev2 ====
  
-Uz zadatak je dana samo izvršna datoteka "rev2". Preporučuje se korištenje linuxa, ili ako imate Windows, koristite WSL ili virtualnu mašinu s Linuxom.+Uz zadatak je dana samo izvršna datoteka "rev2". Preporučuje se korištenje Linuxa, ili ako imate Windows, koristite WSL ili virtualnu mašinu s Linuxom.
  
-Pokretanjem programa, program nas pita za password ispisuje krivi passwordpri unosu netočnog passworda.+Pokretanjem programa, tražse lozinka i nakon unosaispisuje se poruka o pogrešnoj lozinki.
  
 {{ rev2_ghidra:slika1.png?nolink&500 | Slika 1. pokretanje programa }} {{ rev2_ghidra:slika1.png?nolink&500 | Slika 1. pokretanje programa }}
Line 15: Line 15:
 {{ rev2_ghidra:slika2.png?nolink&500 | Slika 2. rezultat file naredbe }} {{ rev2_ghidra:slika2.png?nolink&500 | Slika 2. rezultat file naredbe }}
  
-Program je statically likedznači da se može samostalno pokretati. Također je stripped, što znači da imena varijabli i funkcija neće biti sačuvane, što će malo otežati reverzno inženjerstvo nad programom.+Program je statically linkedzato se može samostalno pokretati. Također je stripped, zato imena varijabli i funkcija neće biti sačuvane, što će malo otežati reverzno inženjerstvo nad programom.
  
-Nakon toga se može pokrenuti naredbastrings da se vidi ima li zanimljivih stringova u datoteci.+Nakon toga se može pokrenuti naredba strings da se vidi ima li zanimljivih stringova u datoteci.
  
 <file> <file>
Line 23: Line 23:
 </file> </file>
  
-No ni jedan vraćeni rezultat ne izgleda kao da previše otkriva. Može se također odmah pretražiti jeli se se među vraćenim stringovima pojavljuje "flag" ili "ctf" tekst.+No niti jedan vraćeni rezultat ne izgleda kao da previše otkriva. Može se također odmah pretražiti pojavljuje li se među vraćenim stringovima pojavljuje "flag" ili "ctf" tekst.
  
 <file> <file>
Line 29: Line 29:
 </file> </file>
  
-zastavica "-i" je case insensitive-e "flag" -e"ctf", znači traži string koji sadrži "flag" ILI "ctf" ILI "passw" u sebi.+zastavica "-i" je case-insensitive opcija. Opcija -e za "flag""ctf""pass" definira da se traži string koji sadrži bilo koji od tih substringova u sebi.
  
 {{ rev2_ghidra:slika3.png?nolink&500 | Slika 3. rezultat strings naredbe }} {{ rev2_ghidra:slika3.png?nolink&500 | Slika 3. rezultat strings naredbe }}
  
-Ovo nam također ništa  korisno ne otkriva o programu, osim što prikazuje tekst koji se ispisuje pri unosu passworda i ispisu pri krivom unosu passworda.+Ovo nam također ništa korisno ne otkriva o programu, osim što prikazuje tekst koji se ispisuje pri unosu passworda i ispisu pri krivom unosu passworda.
  
 Nakon toga se može probati naredba "strace" koja prati sistemske pozive koje program radi. Nakon toga se može probati naredba "strace" koja prati sistemske pozive koje program radi.
Line 43: Line 43:
 {{ rev2_ghidra:slika4.png?nolink&500 | Slika 4. - rezultat strace naredbe }} {{ rev2_ghidra:slika4.png?nolink&500 | Slika 4. - rezultat strace naredbe }}
  
-Također se ne prvi pogled ne mogu pronaći dodatne korisne informacije o programu u ispisu.+Također se na prvi pogled ne mogu pronaći dodatne korisne informacije o programu u ispisu.
  
-Slijedeći korak je korištenje besplatnog Ghidra softwarea za reverzno inženjerstvo nad programom (ako niste upoznati s alatom, pogledajte materijale o ovom alatu također dostupne na wiki stranicama na linku-  https://www.cert.hr/wp-content/uploads/2021/01/ghidra.pdf .)+Sljedeći korak je korištenje besplatnog Ghidra alata za reverzno inženjerstvo nad programom (ako niste upoznati s alatom, pogledajte materijale o ovom alatu na poveznici -  https://www.cert.hr/wp-content/uploads/2021/01/ghidra.pdf .)
  
 {{ rev2_ghidra:slika5.png?nolink&500 | Slika 5. Ghidra alat }} {{ rev2_ghidra:slika5.png?nolink&500 | Slika 5. Ghidra alat }}
Line 51: Line 51:
 Dvoklikom na rev2 datoteku u sučelju, otvara se sučelje za pregled dekompajliranog koda programa. Dvoklikom na rev2 datoteku u sučelju, otvara se sučelje za pregled dekompajliranog koda programa.
  
-{{ rev2_ghidra:slika6.png?nolink&500 | Slika 5. sučelje za analizu koda i bitni dijelovi }}+{{ rev2_ghidra:slika6.png?nolink&500 | Slika 6. sučelje za analizu koda i bitni dijelovi }}
  
 Na slici vidimo entry point, dio koda koji se prvi izvršava pri pokretanju programa, u Decompile sučelju vidi se da entry point funkcija samo poziva funkciju "FUN_004017e0", dvoklikom na ime te funkcije u Decompile sučelju se otvara ta funkcija, koja se poziva odmah pri pokretanju programa. Na slici vidimo entry point, dio koda koji se prvi izvršava pri pokretanju programa, u Decompile sučelju vidi se da entry point funkcija samo poziva funkciju "FUN_004017e0", dvoklikom na ime te funkcije u Decompile sučelju se otvara ta funkcija, koja se poziva odmah pri pokretanju programa.
  
-{{ rev2_ghidra:slika7.png?nolink&500 | Slika 6. pregled funkcije }}+{{ rev2_ghidra:slika7.png?nolink&500 | Slika 7. pregled funkcije }}
  
 Pregledom dekompajliranog koda ove funkcije, može se zaključiti da je ovo main funkcija, vidi se dio koda koji ispisuje "Enter password: ", i dio koda odmah ispod, koji bi mogao biti fgets funkcija za čitanje korisničkog unosa, koji zatim sprema na varijablu pbVar5. Pregledom dekompajliranog koda ove funkcije, može se zaključiti da je ovo main funkcija, vidi se dio koda koji ispisuje "Enter password: ", i dio koda odmah ispod, koji bi mogao biti fgets funkcija za čitanje korisničkog unosa, koji zatim sprema na varijablu pbVar5.
Line 65: Line 65:
 </file> </file>
  
-Na početku main funkcije, di se definiraju varijable, može se vidjeti definicija varijable local_118+Na početku main funkcije, gdje se definiraju varijable, može se vidjeti definicija varijable local_118
  
 <file> <file>
Line 77: Line 77:
 </file> </file>
  
-također, vidi se da je drugi argument poziva funkcije  FUN_00404ee0, 0x100 hex vrijednost, što je u decimalnom 264, što odgovara duljini input buffera također.+također, vidi se da je drugi argument poziva funkcije  FUN_00404ee0, 0x100 hex vrijednost, što je u decimalnom 264, koliko je i duljina input buffera.
  
 Treći argument je pointer  PTR_DAT_004aa6d8, dvoklikom na ovu varijablu, otvara se vrijednost na koju ovaj pointer pokazuje. Treći argument je pointer  PTR_DAT_004aa6d8, dvoklikom na ovu varijablu, otvara se vrijednost na koju ovaj pointer pokazuje.
  
-{{ rev2_ghidra:slika8.png?nolink&500 | Slika 7. vrijednost na koju pointer   PTR_DAT_004aa6d8 pokazuje }}+{{ rev2_ghidra:slika8.png?nolink&500 | Slika 8. vrijednost na koju pointer   PTR_DAT_004aa6d8 pokazuje }}
  
 vrijednost je vrijednost je
Line 97: Line 97:
 </file> </file>
  
-odgovarala+odgovarala kodu:
  
 <file> <file>
Line 103: Line 103:
 </file> </file>
  
-Sad se može označiti varijabla local_118, pritisnuti gumb L i preimenovati u input_buffer.+Može se označiti varijabla local_118, pritisnuti gumb L i preimenovati u input_buffer.
  
-{{ rev2_ghidra:slika9.png?nolink&500 | Slika 8.  Preimenovanje varijable u Ghidri }}+{{ rev2_ghidra:slika9.png?nolink&500 | Slika 9.  Preimenovanje varijable u Ghidri }}
  
-Također se varijable pbVar5 može preimenovati u user_input, PTR_DAT_004aa6d8 u stdin i  +Također se varijabla pbVar5 može preimenovati u user_input, PTR_DAT_004aa6d8 u stdin i  
-FUN_00404ee0 u fgets. Varijablu lVar2 nećemo preimenovati, jer se prvo koristi kao exit value fgets funkcije, a nakon toga se koristi za spremanje vraćene vrijednosti thunk_FUN_00412860 funkcije, te se ta vračena vrijednost potom uspoređuje s 0x15.+FUN_00404ee0 u fgets. Varijablu lVar2 nećemo preimenovati, jer se prvo koristi kao exit value fgets funkcije, a nakon toga se koristi za spremanje vraćene vrijednosti thunk_FUN_00412860 funkcije, te se ta vraćena vrijednost potom uspoređuje s 0x15.
  
-Kako bi se olakšalo praćenje važnih varijabli, varijable koje su bitne u izvođenju programa mogu se označiti i pritiskom desnog klika i opcije highlight, mogu se postaviti da budu bolje naznačenje u ostatku programa.+Kako bi se olakšalo praćenje važnih varijabli, varijable koje su bitne u izvođenju programa mogu se označiti i pritiskom desnog klika i opcije highlight, mogu se postaviti da budu istaknuto označenu ostatku programa.
  
-fgets funkcija pri uspješnom izvršavanjuvraća pointer na string buffer, a ako je vraćena vrijednost NULL, dogodila se greška, što odgovara ovom djelu koda+fgets funkcija pri uspješnom izvršavanju vraća pointer na string buffer, a ako je vraćena vrijednost NULL, dogodila se greška, što odgovara ovom dijelu koda
  
 <file> <file>
Line 122: Line 122:
 </file> </file>
  
-Ako je fgets vratio NULL,  varijabla uVar3 se postavlja u 1 i skače se na kraj main funkcije, te se varijabla uVar3 vrača kao return vrijednost main funkcije, znači da se varijabla uVar3 može preimenovati u main_func_ret_val.+Ako je fgets vratio NULL,  varijabla uVar3 se postavlja u 1 i skače se na kraj main funkcije, te se varijabla uVar3 vraća kao return vrijednost main funkcije, zato se varijabla uVar3 može preimenovati u main_func_ret_val.
  
-Ako se fgets uspješno izvršio, izvršava se else block, koji počinje ovim kodom+Ako se fgets uspješno izvršio, izvršava se else blok, koji počinje ovim kodom
  
 <file> <file>
Line 136: Line 136:
 dvoklikom na adresu DAT_0047f021 na kojoj je vrijednost drugog argumenta proslijeđenog ovoj funkciji, može se vidjeti vrijednost na toj adresi dvoklikom na adresu DAT_0047f021 na kojoj je vrijednost drugog argumenta proslijeđenog ovoj funkciji, može se vidjeti vrijednost na toj adresi
  
-{{ rev2_ghidra:slika10.png?nolink&500 | Slika 9. vrijednost na adresi   DAT_0047f021 }}+{{ rev2_ghidra:slika10.png?nolink&500 | Slika 10. vrijednost na adresi   DAT_0047f021 }}
  
 Vrijednost je "0x0d0a00", što zapravo u hex vrijednost odgovara "\r\n", odnosno CR LF, kraju unesenog stringa ( 0x0d je "\r", 0x0a je \n"). Vrijednost je "0x0d0a00", što zapravo u hex vrijednost odgovara "\r\n", odnosno CR LF, kraju unesenog stringa ( 0x0d je "\r", 0x0a je \n").
Line 150: Line 150:
 U tom slučaju bi varijabla  lVar2 sadržavala duljinu korisničkog unosa, pa bi se onda u sljedećoj liniji, na kraj stringa korisničkog unosa postavio NULL byte umjesto CR LF, kako se CR LF u ostatku programa ne bi koristio. U tom slučaju bi varijabla  lVar2 sadržavala duljinu korisničkog unosa, pa bi se onda u sljedećoj liniji, na kraj stringa korisničkog unosa postavio NULL byte umjesto CR LF, kako se CR LF u ostatku programa ne bi koristio.
  
-Nakon toga, u if statementu, vrijednost varijable  lVar2 se uspoređuje s 0x15, odnosno 21 u dekadskom zapisu, što točno odgovara duljini FLAG formata +Nakon toga, u if statementu, vrijednost varijable lVar2 se uspoređuje s 0x15, odnosno 21 u dekadskom zapisu, što točno odgovara duljini FLAG formata 
  
 <file> <file>
Line 156: Line 156:
 </file> </file>
  
-Ako je duljina korisničkog jednaka 21, ulazi se u do - while block, unutar kojega se nalazi switch sa 7 caseva, ako nije skače se na funkciju koja ispisuje "wrong password", znači da je prvi uvjet da duljina korisničkog unosa mora biti duljine 21 znak.+Ako je duljina korisničkog unosa jednaka 21, ulazi se u do - while blok, unutar kojega se nalazi switch sa 7 caseva. Ako uvjet nije zadovoljen, skače se na funkciju koja ispisuje "Wrong password!". Zato je prvi uvjet da duljina korisničkog unosa mora biti duljine 21 znak.
  
-Pregledom switcha, na kraju switcha se odmah može vidjeti case 0, koji samo ispisuje wrong password+Pregledom switcha, na kraju switcha se odmah može vidjeti case 0, koji samo ispisuje poruku "Wrong password!"
  
-{{ rev2_ghidra:slika11.png?nolink&500 | Slika 10. Switch case 0 }}+{{ rev2_ghidra:slika11.png?nolink&500 | Slika 11. Switch case 0 }}
  
-Na  početku do blocka, se nalazi ova linija+Na  početku do bloka, se nalazi ova linija
  
 <file> <file>
Line 168: Line 168:
 </file> </file>
  
-koja postavlja varijablu bVar1 na dereferenciranu vrijednost user_input pointera, koji je pointer na string buffer. Znači da će varijable se  bVar1 sadržavati vrijednost charactera iz user inputa, zato se  +koja postavlja varijablu bVar1 na dereferenciranu vrijednost user_input pointera, koji je pointer na string buffer. Varijabla bVar1 će sadržavati vrijednost charactera iz user inputa, zato se može preimenovati u user_input_char.
-može preimenovati u user_input_char.+
  
-U switchu postoji 7 caseva, a case se određuje prema vrijednosti puVar2.+U switchu postoji 7 caseva, a case se određuje prema vrijednosti puVar2.
  
-{{ rev2_ghidra:slika12.png?nolink&500 | Slika 10. - switch value }}+{{ rev2_ghidra:slika12.png?nolink&500 | Slika 12. - switch value }}
  
-{{ rev2_ghidra:slika13.png?nolink&500 | Slika 12. -switch }}+{{ rev2_ghidra:slika13.png?nolink&500 | Slika 13. -switch }}
  
 Vidi se da se u svakom caseu uzima user_input_char, radi operacija s njime i operandom puVar2 + 1 i rezultat se uspoređuje s puVar2 + 2, osim u casevima 6 i 7, gdje se u caseu 6 samo radi operacija nad vrijednošću  user_input_char i uspoređuje s puVar2 + 2, a caseu 7 vrijednost  user_input_char se zbraja s  puVar2 + 2 i uspoređuje s "\n". Vidi se da se u svakom caseu uzima user_input_char, radi operacija s njime i operandom puVar2 + 1 i rezultat se uspoređuje s puVar2 + 2, osim u casevima 6 i 7, gdje se u caseu 6 samo radi operacija nad vrijednošću  user_input_char i uspoređuje s puVar2 + 2, a caseu 7 vrijednost  user_input_char se zbraja s  puVar2 + 2 i uspoređuje s "\n".
  
-case 1 operacija je XOR (^), u case 2 operacije je ADD (+) u case 3 operacije je SUB (-), u case operacija je MUL (*), u case 5 operacija je bitwise SHIFT (<< i >>), u case 6 operacija je bitwise NOT (~) i u case 7 operacije je također ADD (+), kao što je prethodno opisano.+caseu 1 operacija je XOR (^), u caseu 2 operacije je ADD (+) u caseu 3 operacije je SUB (-), u caseu operacije je MUL (*), u caseu 5 operacija je bitwise SHIFT (<< i >>), u caseu 6 operacija je bitwise NOT (~) i u caseu 7 operacije je također ADD (+), kao što je prethodno opisano.
  
 odlaskom na adresu gdje je Stack[-0x158] i dvoklikom na XREF[3,12] odlaskom na adresu gdje je Stack[-0x158] i dvoklikom na XREF[3,12]
  
-{{ rev2_ghidra:slika14.png?nolink&500 | Slika 13. Stack[-0x158] }}+{{ rev2_ghidra:slika14.png?nolink&500 | Slika 14. Stack[-0x158] }}
  
 Također možemo vidjeti opis switch caseva, koji je upravo bio opisan. Također možemo vidjeti opis switch caseva, koji je upravo bio opisan.
  
-{{ rev2_ghidra:slika15.png?nolink&500 | Slika 14. switch caseovi. }}+{{ rev2_ghidra:slika15.png?nolink&500 | Slika 15. switch caseovi. }}
  
 Još je preostalo pronaći što je varijabla koja određuje koji switch case će biti odabran, operandi u switch caseovima i očekivani rezultati operacija, koji su svi određeni u varijabli puVar2. Još je preostalo pronaći što je varijabla koja određuje koji switch case će biti odabran, operandi u switch caseovima i očekivani rezultati operacija, koji su svi određeni u varijabli puVar2.
  
-Varijabla puVar2 je definirana pri početku programa i pokazuje na adresu varijable local_158, koji sadržava hex vrijednosti.+Varijabla puVar2 je definirana pri početku programa i pokazuje na adresu varijable local_158, koja sadržava hex vrijednosti.
  
-{{ rev2_ghidra:slika16.png?nolink&500 | Slika 15. - puVar2 i local_158 }}+{{ rev2_ghidra:slika16.png?nolink&500 | Slika 16. - puVar2 i local_158 }}
  
-No pošto je program stripped, moguće je da je Ghdira krivo rekonstruirala ove varijable, ne njihove vrijednosti nego kako su definirane, varijable nakon local_158 se ne spominju dalje u main funkciji, a nalaze se odmah ispod local_158 na koju pokazuje puVar2.+Budući da je program stripped, moguće je da je Ghidra krivo rekonstruirala ove varijable, ne njihove vrijednostinego kako su definirane, varijable nakon local_158 se ne spominju dalje u main funkciji, a nalaze se odmah ispod local_158 na koju pokazuje puVar2.
  
-Na samoj kraju do blocka, nakon switcha casea-7, se user_input pointer povećava za 1, znači da se za sljedeću iteraciju do blocka koristiti slijedeći character iz user inputa +Na samom kraju do bloka, nakon switcha casea-7, se user_input pointer povećava za 1, tako će se za sljedeću iteraciju do bloka koristiti sljedeći character iz user inputa
  
-početak do blocka+početak do bloka
  
 <file> <file>
Line 205: Line 204:
 </file> </file>
  
-a puVar2 se povećava za 3 u svakoj iteraciji, što taman odgovara 3 vrijednosti koje se koriste  +a puVar2 se povećava za 3 u svakoj iteraciji, što taman odgovara 3 vrijednosti koje se koriste u svakom do bloku,  puVar2 + 0 određuje koji switch case će se izvršiti,  puVar2 + 1 je operand,  puVar2 + 2 je očekivana vrijednost.
-u svakom do blocku,  puVar2 + 0 određuje koji switch case će se izvršiti,  puVar2 + 1 je operand,  puVar2 + 2 je očekivana vrijednost.+
  
-{{ rev2_ghidra:slika17.png?nolink&500 | Slika 16. inkrementiranje puVar2 i user_input pointera }}+{{ rev2_ghidra:slika17.png?nolink&500 | Slika 17. inkrementiranje puVar2 i user_input pointera }}
  
-Pošto će se svaki user input character imati jednu vlastitu iteraciju, a puVar2 se povećava za 3 nakon svake iteracije, znamo da user input charactera ima 21, veličina puVar2 byteova koje se koriste su 3 * 21 = 63. +Budući da će se svaki user input character imati jednu vlastitu iteraciju, a puVar2 se povećava za 3 nakon svake iteracije, zna se da user input ima 21 character. Količina puVar2 bajtova koje se koriste su 3 * 21 = 63. 
 Ovo se također može vidjeti na slici ispod, while se izvršava sve dok varijabla pbVar2 koja se povećava za 3 nije jednaka adresi spremljenoj na local_119, koja je RSP uvećan za 0x3f, odnosno 63 u dekadskom zapisu, zato što ima 63 byte vrijednosti spremljenih na stacku. Ovo se također može vidjeti na slici ispod, while se izvršava sve dok varijabla pbVar2 koja se povećava za 3 nije jednaka adresi spremljenoj na local_119, koja je RSP uvećan za 0x3f, odnosno 63 u dekadskom zapisu, zato što ima 63 byte vrijednosti spremljenih na stacku.
  
-{{ rev2_ghidra:slika18.png?nolink&500 | Slika 17. - local_119 }}+{{ rev2_ghidra:slika18.png?nolink&500 | Slika 18. - local_119 }}
  
-Na slici 15. se vidi da je puVar2 pointer na local_158, sada znamo da local_158 zapravo sadržava 63 byteova, te možemo napraviti retype local_158 varijable.+Na slici 16. se vidi da je puVar2 pointer na local_158, sada znamo da local_158 zapravo sadržava 63 bajtova te možemo napraviti retype local_158 varijable.
  
-{{ rev2_ghidra:slika19.png?nolink&500 | Slika 18 - retype local_158 }}+{{ rev2_ghidra:slika19.png?nolink&500 | Slika 19 - retype local_158 }}
  
 Znamo da sadržava byte vrijednost i duljine je 63, pa type možemo postaviti u  Znamo da sadržava byte vrijednost i duljine je 63, pa type možemo postaviti u 
Line 225: Line 223:
 </file> </file>
  
-{{ rev2_ghidra:slika20.png?nolink&500 | Slika 19 - local_158 byte[63] retype }}+{{ rev2_ghidra:slika20.png?nolink&500 | Slika 20 - local_158 byte[63] retype }}
  
-{{ rev2_ghidra:slika21.png?nolink&500 | Slika 20. Promijenjeni prikaz local_158 }}+{{ rev2_ghidra:slika21.png?nolink&500 | Slika 21Promijenjeni prikaz local_158 }}
  
 Sada je promijenjen prikaz i može se jasno vidjeti da su ovdje zapravo pohranjene vrijednosti: Sada je promijenjen prikaz i može se jasno vidjeti da su ovdje zapravo pohranjene vrijednosti:
Line 237: Line 235:
 Vrijednosti su u trojkama, prva vrijednost je operacija koja će se izvršiti, odnosno vrijednost 0-7 koja određuje koji switch case 0-7 će se izvršiti, druga vrijednost je operand, treća vrijednost je očekivani rezultat. Za svaki od 21 user input charactera, postoji odgovarajuća trojka. Vrijednosti su u trojkama, prva vrijednost je operacija koja će se izvršiti, odnosno vrijednost 0-7 koja određuje koji switch case 0-7 će se izvršiti, druga vrijednost je operand, treća vrijednost je očekivani rezultat. Za svaki od 21 user input charactera, postoji odgovarajuća trojka.
  
-Pregled prvih triju vrijednosti je prikazan na slici 21.+Pregled prvih triju vrijednosti je prikazan na slici ispod.
  
-{{ rev2_ghidra:slika22.png?nolink&500 | Slika 21. - prvih tri vrijednosti local_158 }}+{{ rev2_ghidra:slika22.png?nolink&500 | Slika 22. - prvih tri vrijednosti local_158 }}
  
-Ovdje se može vidjeti da je prva vrijednost 2, što znači da će se izvršiti switch case 2, koji je ADD (+), operand je 0x92, a očekivani rezultat je 0xd5.+Ovdje se može vidjeti da je prva vrijednost 2, zbog koje će se izvršiti switch case 2, koji je ADD (+), operand je 0x92, a očekivani rezultat je 0xd5.
  
-Što znači+Odnosno
  
 <file> <file>
Line 249: Line 247:
 </file> </file>
  
-odnosno+Iz ovoga se može zaključiti koji je očekivani znak korisničkog unosa
  
 <file> <file>
Line 257: Line 255:
 0xd5 - 0x92 je 0x43, odnosno 67 u dekadskom zapisu, što odgovara ASCII vrijednosti "C", što je početak forme flaga CTF2025.... 0xd5 - 0x92 je 0x43, odnosno 67 u dekadskom zapisu, što odgovara ASCII vrijednosti "C", što je početak forme flaga CTF2025....
  
-Sada se ili ovako "ručno" može ovaj postupak ponoviti za preostalih 20 znakova, ili se može iskoristiti python da to riješi umjesto nas.+Sada se ili ovako "ručno" može ovaj postupak ponoviti za preostalih 20 znakova, ili se može iskoristiti Python da to riješi umjesto nas.
  
-python programu, definiramo liniju+Python programu, definiramo liniju
  
 <file> <file>
Line 265: Line 263:
 </file> </file>
  
-I nakon toga možemo samo prekopirati sve linije koje sadržavaju definirane vrijednosti varijable local_158, kao što su prikazane na slici 20.+I nakon toga možemo samo prekopirati sve linije koje sadržavaju definirane vrijednosti varijable local_158, kao što su prikazane na slici 21.
  
-Ovime već imamo validan python kod, u kojem smo definirali sve spremljene operacije, operande i rezultate koji se trebaju izvršiti kao u programu.+Ovime već imamo validan Python kod, u kojem smo definirali sve spremljene operacije, operande i rezultate koji se trebaju izvršiti kao u programu.
  
-{{ rev2_ghidra:slika23.png?nolink&500 | Slika 21. - prijenos varijable local_158 u python }}+{{ rev2_ghidra:slika23.png?nolink&500 | Slika 23. - prijenos varijable local_158 u Python }}
  
 Dodavanjem ovog koda na kraj, možemo dobiti ispis operacija i očekivanih rezultata koji se izvršavaju u programu. Dodavanjem ovog koda na kraj, možemo dobiti ispis operacija i očekivanih rezultata koji se izvršavaju u programu.
  
-{{ rev2_ghidra:slika24.png?nolink&500 | Slika 22. - simulacija programske logike rev2 zadatka }}+{{ rev2_ghidra:slika24.png?nolink&500 | Slika 24. - simulacija programske logike rev2 zadatka }}
  
-Pokretanjem koda sada dobivamo ispis svih operacija nad korsiničkim unosom i očekivane rezultate tih operacija:+Pokretanjem koda sada dobivamo ispis svih operacija nad korisničkim unosom i očekivane rezultate tih operacija:
  
-{{ rev2_ghidra:slika25.png?nolink&500 | Slika 23. - programska logika rev2 zadatka }}+{{ rev2_ghidra:slika25.png?nolink&500 | Slika 25. - programska logika rev2 zadatka }}
  
-Sada se samo Python programski kod sa slike 22 može promijeniti da radi inverz operacija za svih 7 slučaja, tako nađe korisnički input koji bi riješio postavljenje jednadžbe i ispiše krajnji rezultat.+Sada se samo Python programski kod za ispis operacija programa može promijeniti da radi inverz operacija za svih 7 slučaja, te tako nađe korisnički input koji bi riješio postavljene jednadžbe i ispiše krajnji rezultat. 
 + 
 +<code> 
 +local_158 = [0] * 63 
 + 
 +local_158[0x38] = 0xca 
 +local_158[0x39] = 7 
 +local_158[0x3a] = 0 
 +local_158[0x3b] = 0xcc 
 +local_158[0] = 2 
 +local_158[1] = 0x92 
 +local_158[2] = 0xd5 
 +local_158[3] = 7 
 +local_158[4] = 0 
 +local_158[5] = 0xac 
 +local_158[6] = 7 
 +local_158[7] = 0 
 +local_158[8] = 0xba 
 +local_158[9] = 7 
 +local_158[10] = 0 
 +local_158[0xb] = 0xce 
 +local_158[0xc] = 1 
 +local_158[0xd] = 0x42 
 +local_158[0xe] = 0x72 
 +local_158[0xf] = 1 
 +local_158[0x30] = 1 
 +local_158[0x31] = 0xb3 
 +local_158[0x32] = 0x87 
 +local_158[0x33] = 4 
 +local_158[0x34] = 0x89 
 +local_158[0x35] = 0xf8 
 +local_158[0x36] = 6 
 +local_158[0x37] = 0 
 +local_158[0x10] = 0x7f 
 +local_158[0x11] = 0x4d 
 +local_158[0x12] = 7 
 +local_158[0x13] = 0 
 +local_158[0x14] = 0xcb 
 +local_158[0x15] = 4 
 +local_158[0x16] = 0xf1 
 +local_158[0x17] = 0xab 
 +local_158[0x18] = 6 
 +local_158[0x19] = 0 
 +local_158[0x1a] = 0xce 
 +local_158[0x1b] = 4 
 +local_158[0x1c] = 0x6b 
 +local_158[0x1d] = 0xbc 
 +local_158[0x1e] = 1 
 +local_158[0x1f] = 0x7d 
 +local_158[0x3c] = 2 
 +local_158[0x3d] = 0x98 
 +local_158[0x3e] = 0xf5 
 +local_158[0x20] = 0x44 
 +local_158[0x21] = 1 
 +local_158[0x22] = 0xe5 
 +local_158[0x23] = 0xd4 
 +local_158[0x24] = 7 
 +local_158[0x25] = 0 
 +local_158[0x26] = 200 
 +local_158[0x27] = 4 
 +local_158[0x28] = 0xdd 
 +local_158[0x29] = 7 
 +local_158[0x2a] = 5 
 +local_158[0x2b] = 7 
 +local_158[0x2c] = 0x9a 
 +local_158[0x2d] = 7 
 +local_158[0x2e] = 0 
 +local_158[0x2f] = 0xcc 
 + 
 +def reconstructUserInput(operation, operand, expected_result): 
 +    def ret(b): 
 +        return chr(b & 0xFF) 
 +    match operation: 
 +        case 1:  # XOR 
 +            return ret(expected_result ^ operand) 
 +        case 2:  # ADD 
 +            return ret((expected_result - operand) & 0xFF) 
 +        case 3:  # SUB 
 +            return ret((expected_result + operand) & 0xFF) 
 +        case 4:  # MUL 
 +            # solve (user * operand) & 0xFF == expected_result 
 +            # since all values are printable and operand is invertible modulo 256, use brute force 
 +            for x in range(256): 
 +                if (x * operand) & 0xFF == expected_result: 
 +                    return ret(x) 
 +        case 5:  # SHIFT (rotate-left) 
 +            n = operand & 7 
 +            for x in range(256): 
 +                if ((x << n) | (x >> (8 - n))) & 0xFF == expected_result: 
 +                    return ret(x) 
 +        case 6:  # BITWISE NOT (no operand) 
 +            return ret((~expected_result) & 0xFF) 
 +        case 7:  # ADD (no operand) 
 +            return ret((-expected_result) & 0xFF) 
 + 
 +i = 0 
 +user_input_solve = "" 
 +while i < 63: 
 +    operation = local_158[i] 
 +    operand = local_158[i + 1] 
 +    expected_result =local_158[i + 2] 
 + 
 +    userInput = reconstructUserInput(operation, operand, expected_result) 
 + 
 +    print(userInput) 
 +     
 +    user_input_solve += userInput 
 + 
 +    i += 3 
 + 
 +print("\nSolution: ",user_input_solve) 
 + 
 +</code>
  
-{{ rev2_ghidra:slika26.png?nolink&500 | Slika 24. - Inverz operacija zadatka }} 
  
-Pokretanjem ovog programadobiva se rješenje zadatka+Pokretanjem ovog programa dobiva se rješenje zadatka
  
-{{ rev2_ghidra:slika27.png?nolink&500 | Slika 25. - rješenje zadatka }}+{{ rev2_ghidra:slika26.png?nolink&500 | Slika 26. - rješenje zadatka }}
  
-Napomena:+==Napomena==
  
-Preporučuje se da kad radite reversing, probate otvoriti datoteku i drugim alatima za reverzno inženjerstvo, jer će nekad neki drugi alat bolje dekompajlirati programski kod i razumljivije prikazati logiku programa koji rješavate, na slici ispod je prikaz rev2 zadatka otvorenog pomoću alata Binary Ninja.+Preporučuje se da kad radite reversing, probate otvoriti datoteku i drugim alatima za reverzno inženjerstvo, jer će nekad neki drugi alat bolje dekompajlirati programski kod i razumljivije prikazati logiku programa koji rješavate, na slici ispod je prikaz rev2 zadatka otvorenog pomoću alata Binary Ninja.
  
-{{ rev2_ghidra:slika28.png?nolink&500 | Slika 26. - Binary Ninja prikaz rev2 }}+{{ rev2_ghidra:slika27.png?nolink&500 | Slika 27. - Binary Ninja prikaz rev2 }}
  
-Može se vidjeti da je Binary Ninja odmah uspješno rekonstruirala dužinu i sadržaj local_158 varijable, koja sadrži trojke operacija, operand, očekivan rezultat, što je u Ghidri bilo potrebno ručno postaviti.+Može se vidjeti da je Binary Ninja odmah uspješno rekonstruirala duljinu i sadržaj local_158 varijable, koja sadrži trojke operacija, operand, očekivani rezultat, što je u Ghidri bilo potrebno ručno postaviti.
  
rev2_ghidra.1761930497.txt.gz · Last modified: 2025/12/01 11:40 (external edit)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki