integer_overflow
Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| integer_overflow [2023/11/15 16:39] – created kresimir | integer_overflow [2025/12/01 11:40] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 2: | Line 2: | ||
| Do integer overflow-a dolazi kada se pokuša pohraniti vrijednost u varijablu koja je veća od maksimalno dopuštene. | Do integer overflow-a dolazi kada se pokuša pohraniti vrijednost u varijablu koja je veća od maksimalno dopuštene. | ||
| - | Sve numeričke vrijednosti | + | Sve numeričke vrijednosti |
| U današnje vrijeme to su najčešće 64 bitni registri. | U današnje vrijeme to su najčešće 64 bitni registri. | ||
| Line 18: | Line 18: | ||
| Byte ima 8 bitova, što znači da je u nju moguće upisati 2^8 (256) različitih vrijednosti: | Byte ima 8 bitova, što znači da je u nju moguće upisati 2^8 (256) različitih vrijednosti: | ||
| - | *unsigned notaciji: [0, 255] | + | *U unsigned notaciji: [0, 255] |
| - | *signed notaciji : [-128, 127] | + | *U signed notaciji: [-128, 127] |
| Najveća vrijednost koju ona može sadržati u sebi jest broj 1111 1111(2) | Najveća vrijednost koju ona može sadržati u sebi jest broj 1111 1111(2) | ||
| - | S obzirom da su svi numerički operandi nalaze u registru (npr. 64 bitnom) zapis vrijednosti varijable a (recimo broj 255) | + | S obzirom |
| - | u registru koji sadržu njenu vrijednost | + | u registru koji sadržu njenu vrijednost |
| Kada bismo tom registru dodali vrijednost 1, zapis bi izgledao ovako: 0000....1 0000 0000(2), što bi značilo da se vrijednost | Kada bismo tom registru dodali vrijednost 1, zapis bi izgledao ovako: 0000....1 0000 0000(2), što bi značilo da se vrijednost | ||
| Line 32: | Line 32: | ||
| Sklopovlje za zbrajanje registara interno koristi tzv. carry flag (rflags/ | Sklopovlje za zbrajanje registara interno koristi tzv. carry flag (rflags/ | ||
| To znači da kada se registar preplavi (odnosno upiše vrijednost veća od 2^64) on ispravlja svoj sadržaj | To znači da kada se registar preplavi (odnosno upiše vrijednost veća od 2^64) on ispravlja svoj sadržaj | ||
| - | (odnosno prikazuje upisanu vrijednost % 2^64 gdje je % operacija modulo-ostatak) i postavlja | + | (odnosno prikazuje upisanu vrijednost % 2^64 gdje je % operacija modulo-ostatak) i postavlja carry flag. |
| Kada bi se taj registar dalje koristio za operacije bile bi prikazane vrijednost manje od 2^64. | Kada bi se taj registar dalje koristio za operacije bile bi prikazane vrijednost manje od 2^64. | ||
| + | |||
| + | ====Tajni chat==== | ||
| + | |||
| + | ===Opis zadatka:=== | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | Ivan je skeniranjem interneta naišao na ovaj tajni chat. Zaista mu se želi pridružiti, | ||
| + | |||
| + | Spoji se na program uz pomoć naredbe telnet (ako koristiš Windows) ili naredbe netcat (ako koristiš Linux): | ||
| + | |||
| + | telnet chal.platforma.hacknite.hr 8084 | ||
| + | | ||
| + | netcat chal.platforma.hacknite.hr 8084 | ||
| + | |||
| + | ===Rješenje: | ||
| + | |||
| + | Zastavica će se ispisati ako vrijedi uvjet (status-> | ||
| + | Potrebno je preplaviti status i postaviti ga na ispravne vrijednosti. | ||
| + | Jedini unos je preko scanf-a: | ||
| + | scanf(" | ||
| + | scanf(" | ||
| + | Objekt status nalazi se iza popis_pozivatelja. | ||
| + | Unos scanf-a ograničen je iteracijom po broju pozivatelja: | ||
| + | for(long long i=0; i< | ||
| + | ... | ||
| + | |||
| + | Također postavljan je uvjet na donju granicu broja pozivatelja: | ||
| + | if(broj_pozivatelja > 0) //Dakle broj pozivatelja ne smije biti negativan | ||
| + | Potrebno je napraviti overflow tako da iteracija omogućuje veći ispis po gomili od veličine popis_pozivatelja: | ||
| + | long long broj_pozivatelja; | ||
| + | |||
| + | 2^64 = 18, | ||
| + | *U unsigned notaciji: [0, 18 446 744 073 709 551 615] | ||
| + | *U signed notaciji : [-9 223 372 036 854 775 808, 9 223 372 036 854 775 807] | ||
| + | |||
| + | Veličina popis_pozivatelja je određena s: | ||
| + | broj_pozivatelja * sizeof(struct pozivatelj) | ||
| + | Sizeof je operacija koja vraća tip size_t (unsigned int) i u ovom slučaju to će biti vrijednost 20 (10 char + 10 char gdje je char riječ definirana kao byte) | ||
| + | Broj_pozivatelja je long long | ||
| + | Rezultat množenja je tip long long (implicit casting - uvijek se upcasta na najkompleksniji operand u operaciji npr. float*long *int *short = float). | ||
| + | |||
| + | Kako bi se izveo overflow na razini registra koji čuva vrijednost umnoška potrebno je unijeti vrijednost za broj_pozivatelja na načina da je | ||
| + | rezultat veći od 2^64 jer: | ||
| + | |||
| + | Broj_pozivatelja*sizeof(struct pozivatelj) = (broj_pozivatelja*sizeof (struct pozivatelj) ) % 2^64 = (broj_pozivatelja*20)%2^64 | ||
| + | |||
| + | 2^64 / 20 = 922337203685477581 kada se zaokruži na gornju granicu. | ||
| + | Time je ostatak 4 unutar malloc-a. | ||
| + | Naravno, moguće je izvesti overflow i s drukčijim brojevima. | ||
| + | ----- | ||
| + | Rješenje je dakle: | ||
| + | -Unos_1: 922337203685477581 | ||
| + | -Unos_2: Unos stringa do adrese status i preplavljivanje varijable moze_citati_flag | ||
| + | |||
| + | {{tajnichat.png}} | ||
| + | |||
integer_overflow.1700066373.txt.gz · Last modified: 2025/12/01 11:40 (external edit)