- - - - Temat wykladu: Assembler - wyklad #4, Wykladowca: Gynvael - - - - [21:01] Gynvael: mozemy powoli zaczynac [21:01] Jacek: ok [21:01] Gynvael: tylko za wczasu wrzuce przyklady na serv [21:01] DR460N: Ok. [21:02] Prodigy: Gynvael: slyszalem, ze Ashi gra w sc? :> [21:02] Prodigy: czy to prawda? :> [21:02] Gynvael: tez ;> [21:02] Gynvael: ta [21:02] Gynvael: ma nawet MX310 ;p [21:03] Gynvael: ok21:03 Gynvael: witam wszystkich na kolejnej czesci wykladu z asma [21:03] Gynvael: dzisiaj pobawimy sie w sumie dalej podstawami [21:04] Gynvael: a mianowicie sprobojemy zrobic funkcje do wypisywania liczb naturalnych [21:04] Gynvael: a potem cos na ksztalt printf (ofc uproszczonego) [21:04] Gynvael: ok [21:05]Gynvael: mam nadzieje ze wszyscy pamietaja co to sa flagi procesora [21:05] Gynvael: jakie sa rejestry etc ;> [21:05] Gynvael: http://gynvael.lunarii.org/temp/my_print.asm [21:05] Gynvael: na pierwszy ogien idzie przypomnienie [21:05] Gynvael: czyli prosty programik cos tam wypisujacy [21:06] Gynvael: w funkcji glownej sa dwa wywolania [21:06] Gynvael: najpierw funkcji my_print [21:06] Gynvael: potem my_exit [21:06] Gynvael: push napis [21:06] Gynvael: call my_print [21:06] Gynvael: push 0 [21:06] Gynvael: call my_exit [21:06] Gynvael: widzac to omozna sie domyslic ze obie funkcje oczekuja parametrow na stosie [21:06] Gynvael: i same te parametry ze stosu zdejmuja [21:06] Gynvael: czyli mamy do czynienia z typowym stdcall [21:07] Gynvael: dzialanie funkcji my_print omawialem juz poprzednio [21:07] Gynvael: my_exit po prostu wywoluje sys_exit (int 0x80, eax = 1) z podanym return code'em [21:09] Gynvael: ((chyba wszyscy juz lookneli ;>)_ [21:09] Gynvael: ok [21:09] Gynvael: to byla tylko powtoorka [21:09] Gynvael: wiec lecimy dalej [21:09] Gynvael: http://gynvael.lunarii.org/temp/my_print_int.asm [21:10] Gynvael: tym razem w funkcji glownej 3 wywolania [21:10] Gynvael: najpeirw my_print_int z parametrem 1234 [21:10] Gynvael: nastepnie my_print tylko po to zeby \n wrzucic [21:10] Gynvael: a potem my_exit [21:11] Gynvael: przyjzyjmu sie natomiast funkcji my_print_int [21:11] Gynvael: wiec tak [21:11] Gynvael: najpierw troche o logice dzialania [21:11] Gynvael: sa dwie szkoly konwersji inta na stringa [21:11] Gynvael: pierwsza mowi: [21:12] Gynvael: dziel przez 10 poki mozesz, a reszty z dzielenia ukladaj po kolei [21:12] Gynvael: czyli przykladowo [21:12] Gynvael: majac liczbe 1234 [21:12] Gynvael: 1234:10 = 123 (reszta 4)... "4___" [21:12] Gynvael: 123:10 = 12 (reszta 3)... "43__" [21:12] Gynvael: 12:10 = 1 (reszta 2)... "432_" [21:12] Gynvael: 1:10 = 0 (reszta 1)... "4321" [21:13] Gynvael: po czym na koncu odwroc kolejnosc [21:13] Gynvael: "4321" -> "1234" [21:13] Gynvael: i wyipsz [21:14] Gynvael: to jedna szkola [21:14] Gynvael: druga mowi.. [21:14] Gynvael: zapisuj od typu [21:14] Gynvael: np [21:14] Gynvael: wskaznik -> "4" [21:14] Gynvael: wskaznik -> "34" [21:14] Gynvael: wskaznik -> "234" [21:14] Gynvael: wskaznik -> "1234" [21:14] Gynvael: i wypisz od wskaznika [21:14] Gynvael: z tym ze czasami dodaje sie przed tym jeszcze [21:15] Gynvael: policz ile cyfr jest i przesun wskaznik na koniec ;> [21:15] Gynvael: w przykladzie uzylem drugiej metody z liczeniem cyfr (zeby bylo wiecej kodu ;p) [21:15] Gynvael: co do samego liczenia [21:15] Gynvael: mozna wyliczyc ofc na 2 sposoby [21:15] Gynvael: 1) wyliczyc logarytm o podstawie 10 ;p [21:15] Gynvael: 2) liczyc ile razy mozna podzielic przez 10 ;> [21:16] Gynvael: uzylem tej drugeiej metody z uwagi na to ze prawdopodobnie i tak jest szybsza ;> [21:17] Gynvael: (nie sprawdzalem czy mozna logarytmy koprocesorem liczyc, a jelsi nie mozna to trzeba sie bawic w znalezienie miejsca zerowego pewnej funkcji metodamy analiztycznymi.. eee darujmy to sobie ;p) [21:17] Gynvael: wiec tak [21:17] Gynvael: funkcja dziala nastepujaco: [21:17] Gynvael: 1) tworzy stack frame (bylo ostatnio) [21:17] Gynvael: push ebp [21:17] Gynvael: mov ebp, esp [21:17] Gynvael: to te dwie instrukcje [21:19] Gynvael: nastepnie zapisuje stare wartosci rejestrow na stosie [21:19] Gynvael: to dobry pomysl jesli nei chce sie potem pare godzin sleczec z debuggerem albo nadkladac kodu przy wywolaniach [21:19] Gynvael: ; stare wartosci [21:19] Gynvael: push ecx [21:19] Gynvael: push edx [21:19] Gynvael: push ebx [21:20] Gynvael: push edi [21:22] Gynvael: (mozna logarytmy na koprocq liczyc, jak mi podpowiada na privie Jacek i manual intela w rece ;>) [21:22] Gynvael: potem rezerwujemy (to w sumie za duze slowo) 16 bajtow pamieci na stosie [21:23] Gynvael: (klaniaja sie zmienne lokalne.. w jezykach typu C wlasnie w ten sposob sa tworzone ;> zwykle sub esp, suma_wielkosci) [21:23] Gynvael: sub esp, 0x10 [21:23] Gynvael: nastepnie jest fragment kodu odpowiedzialny za liczenie ilosci cyferek [21:24] Gynvael: mov eax, [ebp+8] <=- wrzucamy do eax wartosc parametru, czyli 1234 [21:24] Gynvael: ebp + 8, poniewaz stos wyglada teraz tak: EBP -> [oldEBP] [ret] [1234] [21:24] Gynvael: kazdy element na stosie zajmuje 4 bajty (min) [21:25] Gynvael: czyli [ebp] to stare ebp wrzucone na stos przy tworzeniu stack frame'a [21:25] Gynvael: [ret] to adres powrotu wrzucony przez call [21:25] Gynvael: czyli [ret+4] ofc [21:25] Gynvael: a nastepny item to wlasnie argument funkcji [21:25] Gynvael: czyli [ret+8] [21:25] Gynvael: xor ecx, ecx [21:25] Gynvael: zerujemy ecx [21:26] Gynvael: bedziemy zwiekszac co dzielenie ecx, dzieki czemu uzyskamy wkoncu ilosc cyfr [21:26] Gynvael: ;> [21:26] Gynvael: mov ebx, 10 <=- 10 to bedzie nasz dzielnik [21:26] Gynvael: .loop_det [21:26] Gynvael: to jest lokalny label [21:26] Gynvael: w sumie to powinno byc .loop_det: [21:26] Gynvael: ale widac : zbedny ;> [21:27] Gynvael: lokalny label rozni sie tym od globalnego [21:27] Gynvael: ze po natrafieniu na nastepny globalny label (np my_print:) wszyswtkie localne sa resetowane [21:27] Gynvael: btw sa zapisywane do tablic symboli do binarki, jako najblizszy_globalny.locaklny [21:27] Gynvael: np my_print_int.loop.det [21:28] Gynvael: np my_print_int.loop_det [21:28] Gynvael: (to ladnei w gdb widac) [21:29] Gynvael: 0x080480c0 in my_print_int.loop_det () [21:29] Gynvael: (gdb) [21:29] Gynvael: 0x080480c2 in my_print_int.loop_det () [21:29] Gynvael: etc [21:29] Gynvael: ok [21:29] Gynvael: lecimy dalej [21:29] Gynvael: zaraz po lokalnym labelu mamy xor edx, edx [21:29] Gynvael: czyli wyzerowanie edx [21:29] Gynvael: chodzi o to ze div ebx ktory widzicie pozniej [21:29] Gynvael: dzieli liczbe 64bitowa, ktorej gorna czesc stanowi EDX a dolna EAX [21:30] Gynvael: wiec nie mozemy doposcic zeby EDX mialo jakas wartosc przy dzieleniu [21:30] Gynvael: bo: [21:30] Gynvael: 1) dostaniemy sfalszowany wynik [21:30] Gynvael: 2) jesli wynik bedziesz zajmowal wiecej niz 32 bity, dostaneimy exceptiona [21:31] Gynvael: # ./asdf [21:31] Gynvael: Floating point exception (core dumped) [21:31] Gynvael: dokaldnei cos takiego [21:31] Gynvael: teraz o samym div ebx [21:32] Gynvael: div ebx wykonuje nastepujace dzielenie [21:32] Gynvael: edx:eax / evx [21:32] Gynvael: wynik trafia do eax (stad ograniczenie do 32 bitow) [21:32] Gynvael: a reszta z dzielenia do edx (dlatego trzeba to co dzielenie zerowac) [21:32] Gynvael: co ciekawe [21:32] Gynvael: div jest jedna z nielicznych operacji arytmetycznych [21:33] Gynvael: ktorych wyniku nie mozna sprawdzac po flagach procka [21:33] Gynvael: ze zacytuje manual intela [21:33] Gynvael: The CF, OF, SF, ZF, AF and PF flags are undefined. [21:34] Gynvael: tzn sa niezmieniane [21:34] Gynvael: a jak mowilem wczesniej, przepelnienie wyniku objawia sie nie poprzez flage OF jak to powinno byc [21:34] Gynvael: tylko poprzez wygenerowanie exeptiona [21:35] Gynvael: a [21:35] Gynvael: blad zrobilem [21:35] Gynvael: -=212455=- <@Gynvael> edx:eax / evx [21:35] Gynvael: to ofc ebx [21:35] Gynvael: edx:eax / ebx [21:35] Gynvael: ;> [21:35] Gynvael: (ah te 'v' i 'b'.. jak by dalej lezec nie mogly =^^=) [21:35] Gynvael: inc ecx [21:35] Gynvael: nastepnie zwiekszamy ilosc cyfr [21:36] Gynvael: (nawet jak jest 0 to jest jedna cyfra) [21:36] Gynvael: test eax, eax wykonujemy "mentalny" and [21:36] Gynvael: jnz .loop_det i jesli jeszcze w eax nie mamy zero [21:36] Gynvael: wracamy na poczatek petli [21:36] Gynvael: w C powyzsza petle mozna by pewnie zapisac tak [21:37] Gynvael: while( ++ecx, eax /= 10 ); ;> [21:37] Gynvael: po tej petli [21:37] Gynvael: mamy w rejestrze ecx ilosc cyferek [21:38] Gynvael: wrzucamy wiec na koniec terminator [21:38] Gynvael: (ofc terminator, czyli \0, nie bylo by konieczne gdyby zamiast wywolania my_print posluzyc sie po prostu int 0x80 i sys_write) [21:38] Gynvael: lea edi, [esp+ecx] [21:39] Gynvael: mov byte [edi], 0 [21:39] Gynvael: dec edi [21:39] Gynvael: lea przypominam to load evective adres [21:39] Gynvael: *efective..) [21:39] Gynvael: *effective [21:39] Gynvael: geez [21:39] Gynvael: ;p [21:39] Gynvael: lea edi, [esp+ecx] to po prostu mov edi, esp+ecx (ale ze tam nei mozna dodawac to trzeba lea.. wygodne ;>) [21:40] Gynvael: po tej operacji mamy w edi adres miejsca gdzie trzeba terminator wstawic [21:40] Gynvael: przypominam ze esp to stack pointer, czyli adres poprzedniego wrzuconego elementu na stosie, a dokladniej rzecz biorac, w tej chwili to jest adres naszych 16stu bajtow zaalokowanych na stosie [21:40] Gynvael: ;> [21:40] Gynvael: mov byte [edi], 0 [21:40] Gynvael: to wrzuci pod adres edi bajt o wartosci 0 [21:40] Gynvael: czyli \0 [21:41] Gynvael: dec edi przesuwa pointer w lewo, tzn na poprzedni bajt [21:42] Gynvael: i teraz znowu mamy petle [21:42] Gynvael: na poczatek do eax znowu wrzucamy argument [21:42] Gynvael: zyli 1234 [21:42] Gynvael: *czyli [21:42] Gynvael: .loop [21:42] Gynvael: xor edx, edx ; dzielone jest EDX:EAX, wiec lepiej zeby EDX=0 [21:42] Gynvael: div ebx ; dzielenie.. w edx mamy reszte [21:42] Gynvael: add edx, 0x30 ; dodajemy do niej '0' [21:42] Gynvael: to poczatek petli [21:43] Gynvael: xor edx, edx i div ebx to wiadomo [21:43] Gynvael: add edx, 0x30 [21:43] Gynvael: w sumie mozna bylo add dl, 0x30 i bylo by troche lepiej [21:43] Gynvael: ale [21:43] Gynvael: 0x30 to kod ascii cyferki '0' [21:43] Gynvael: jak niektorzy wiedza, a niektorzy nie, kolejne cyferki maja kolejne kody [21:43] Gynvael: czyli 0x31 to 1 [21:43] Gynvael: 0x32 to 2 [21:43] Gynvael: 0x33 to 3 [21:43] Gynvael: etc [21:44] Gynvael: w edx mamy zreszte z dzielenia przez 10 [21:44] Gynvael: a tak dokladniej to po prostu ktoras cyferke [21:44] Gynvael: powiedzmy ze jest to 7 [21:44] Gynvael: edx = 7 [21:44] Gynvael: add edx, 0x30 [21:44] Gynvael: czyli edx = 0x37 [21:44] Gynvael: czyli jest to kod ascii znaku '7' [21:45] Gynvael: mov [edi], dl ; i wrzucamy to co dostaniemy do pamiecij [21:45] Gynvael: jak mowi komentarz ;> [21:45] Gynvael: wrzucamy [21:45] Gynvael: do pamieci pod adres [edi] ktcyfre ;> [21:45] Gynvael: *cyfre [21:45] Gynvael: dec edi ; przesuwamy pointer [21:46] Gynvael: znowu przesuwamy pointer w lewo [21:46] Gynvael: test eax, eax ; jeszcze lecimy ? [21:46] Gynvael: jnz .loop [21:46] Gynvael: i test znany z poprzedniej petli [21:46] Gynvael: czyli czy trzeba jeszcze leciec [21:46] Gynvael: potem wypisujemy [21:46] Gynvael: ; wypisujemy [21:46] Gynvael: push esp [21:46] Gynvael: call my_print [21:46] Gynvael: jak widac posluzylem sie my_print ;> [21:46] Gynvael: ; "zwracamy" pamiec biednemy stosowi =^^= [21:46] Gynvael: add esp, 0x10 [21:46] Gynvael: jak w komentarzu ;> [21:47] Gynvael: nastepnie odczytujemy ze stosu stare wartosci rejestrow ktore ruszalismy [21:47] Gynvael: a potem wychodzimy zdejmujac 4 bajty ze stosu (i niszczac stack frame) [21:47] Gynvael: leave [21:47] Gynvael: retn 4 [21:47] Gynvael: tak dziala ta funkcja [21:48] Gynvael: odpalmy to sobie [21:48] Gynvael: SRC=my_print; nasm -f elf ${SRC}.asm && ld ${SRC}.o -o ${SRC} [21:48] Gynvael: e nie ten przyklad ;> [21:48] Gynvael: SRC=my_print_int; nasm -f elf ${SRC}.asm && ld ${SRC}.o -o ${SRC} [21:48] Gynvael: ./my_print_int [21:48] Gynvael: 1234 [21:49] Gynvael: czyli dziala [21:49] Gynvael: ok [21:49] Gynvael: pytanka ? [21:49] Gynvael: aa [21:49] Gynvael: ofc nie jest to jedyna metoda na taka konwersje ;> [21:49] Gynvael: ale to imho calkiem ok przyklad [21:49] Gynvael: ;> [21:49] Ingo: ok [21:49] Ingo: nasm jest dla windows [21:49] Jacek: co będzie na next wykladzie? [21:50] Ingo: Jacek: najedz sie tym wykladem potem zapytaj o nastepny [21:50] Gynvael: Ingo: jest jest, ale tych intow tam nie ma.. pod winda sie inaczej pisze ;> [21:50] Gynvael: wkoncu winda to zupelnie inny system [21:50] Gynvael: a asm jest bardzo zalezny od systemu, procka etc [21:51] Ingo: eee [21:51] Gynvael: Jacek: masm32 i windwos czesc pierwsza ;> [21:51] Gynvael: do linuxa wrocimy jeszcze potem [21:51] Jacek: aha [21:51] Gynvael: przy okazji gnu assemblera [21:51] Ingo: czyli skompilowales program dal linuxa kompilatorem pod windowsa? [21:51] Gynvael: Ingo: ne, to pod linuxem kompilowalem [21:51] Gynvael: ;> [21:52] phoenix__: hi all [21:52] Gynvael: nasm jest dla windy [21:52] Gynvael: nasm jest dla wiale tez ndla linuxa [21:52] Gynvael: dla dosa [21:52] Gynvael: etc [21:52] Gynvael: wersji tego troche wypooscili [21:52] Gynvael: wersji tego troche wypoos;> [21:52] Gynvael: eh [21:52] Gynvael: mam lagi nas shellu --; [21:52] ant_: to jest 4 wyklad o asmie tak? [21:52] phoenix__: Gynvael: ja tez ;D [21:52] phoenix__: to jest o win ? ;> ne ? ;'> [21:53] Jacek: ja już pisałem swojego "printf-a" w asmie [21:53] Jacek: dawniej [21:53] phoenix__: Gynvael: chodzi juz micek ? ;> [21:53] Jacek: nawet mógł wypisywać litery z opóźnieniem ;) [21:53] phoenix__: cos mi sie wydaje ze nie [21:54] phoenix__: Gynvael: moge priv ? ; [21:54] phoenix__: > [21:54] micek: phoenix__: chodzi [21:54] Gynvael: ant_: tak [21:54] Gynvael: phoenix__: o linuxie [21:54] Gynvael: micek: priv [21:54] phoenix__: micek: a co bylo ? ;> [21:54] phoenix__: aha [21:54] micek: oki [21:54] Gynvael: Jacek: w ktorym asmie ?;> [21:54] phoenix__: to jutro logi poczytam [21:54] Jacek: TASM [21:54] Gynvael: pod jaki os ? [21:54] Jacek: DOS [21:54] micek: phoenix__: dostawca internetowy cos miesza i mi co chwile net siada, nie wiem co jest grane dokladnie [21:55] ant_: micek: joł [21:55] ant_: ave :) [21:55] micek: ant_: ello :- [21:55] micek: ) [21:55] Gynvael: Jacek: ;> nice [21:56] Prodigy: o micek [21:56] Prodigy: siema [21:56] Gynvael: ok [21:56] Gynvael: lecimy dalej [21:56] Jacek: ja uciekam [21:56] Gynvael: jesli pytan brak [21:56] Gynvael: papa [21:57] Gynvael: http://gynvael.lunarii.org/temp/my_printf.asm [21:57] Gynvael: teraz sprobojemy zrobic cos na ksztalt printf [21:57] Gynvael: tego z C [21:57] Gynvael: male wprowadzenie dla ludzi nie znajacych C [21:57] Gynvael: printf to taki multi-tool do wyrzucania na ekran slicznie sformatowanego textu [21:57] Gynvael: pierwszym argumentem jest tzw ciag formatujacy [21:58] Gynvael: jest to w sumie normalny napis ze znacznikami typu %i %s %u %x %p etc [21:58] Gynvael: a nastepnymi sa rzeczy ktore maja byc za znaczniki w odpowiedniesposob podstawione [21:58] Gynvael: np %u to liczba naturalna [21:58] Gynvael: printf("%u asdf %u",1,2); [21:58] Gynvael: cos takiego wyrzuci na ekran "1 asdf 2" [21:59] Gynvael: bez cudzyslowioow ofc [21:59] Gynvael: ok [21:59] Gynvael: jako ze printf ma mozliwosci duzo wieksze [21:59] Gynvael: a my czas ograniczony [22:00] Gynvael: to nasz printf bedzie reagowal tylko na znaczniki %u (liczba naturalna) i %s [22:00] Gynvael: (czyli string, inny napis) [22:00] Gynvael: dzialanie tego powinno byc mniej weiecej takie: [22:00] Gynvael: 1) zapisuj do pamieci tekst az natrafisz na znacznik %s albo %u [22:00] Gynvael: 2) jesli nie natrafisz, wyjdz z petli [22:01] Gynvael: 3) jesli natrafisz, wypisz wszystko co masz w pamieci i [22:01] Gynvael: 4) jesli to %u to pobierz argument ze stosu i uzyj print_int zeby go wypisac [22:01] Gynvael: 5) a jesli to %s to pobeiz argument (adres) ze stosu i uzyj print zeby go wypisac [22:01] Gynvael: 6) idz na poczatek petli [22:02] Gynvael: teraz tak [22:02] Gynvael: jak to zaimplementowac [22:02] Gynvael: po pierwsze [22:02] Gynvael: sam zapis do paemieci, czyli tzw bufforowanie [22:02] Gynvael: potrzebuje buforka [22:02] Gynvael: jego sobie stworzymy na stosie [22:02] Gynvael: powiedzmy 0x100 bajtow + \0 na koncu [22:02] Gynvael: i potrzebuje licznika bajtow [22:03] Gynvael: powiedzmy ze ecx do tego uzyjemy [22:03] Gynvael: na poczatek ecx ma wartosc 0x100 (czyli 256 ;>) [22:03] Gynvael: a powiedzmy po dodaniu 10 znakow [22:03] Gynvael: ecx ma wartosc 246 [22:03] Gynvael: gdy ecx == 0, to znaczy ze buffer sie zapelnil [22:03] Gynvael: i mozna wypisac wszystko na ekran i go wyczyscic [22:04] Gynvael: dodatkowo bedzie potrzwebny pointer na miejsce w buforze gdzie aktualnie bajty zapisujemy [22:04] Gynvael: niech rejestr edi bedzie za to odpowiedzialy [22:05] Gynvael: (destination index ;>) [22:05] Gynvael: to sprawa buforowania [22:05] Gynvael: teraz co do samych argumentow dodatkowych na stosie [22:05] Gynvael: zalozmy niech rejestr esi wskazuje na pierwszy z nich [22:05] Gynvael: i potem co bedzie potrzebny, to neich esi sie przesuwa dalej [22:05] Gynvael: e w8 [22:05] Gynvael: niech edx sie tym zajmie ;> [22:06] Gynvael: a esi uzyjemy do analizy ciagu formatujacego [22:06] Gynvael: i juz [22:06] Gynvael: teraz po kolei [22:06] Gynvael: sub esp, 0x104 [22:06] Gynvael: mov edi, esp [22:06] Gynvael: mov ecx, 0x100 [22:06] Gynvael: mov esi, [ebp+8] [22:06] Gynvael: lea edx, [ebp+12] [22:06] Gynvael: tworzyumy buffor na stosie o wielkosci 260 bajtow [22:06] Gynvael: edi = adres buforka [22:06] Gynvael: ecx = ilosc wolnego miejsca w buforku [22:06] Gynvael: esi = adres pierwszego bajtu ciagu formatujacego [22:07] Gynvael: edx = adres pierwszego dodatkowego argumentu [22:07] Gynvael: cos takiego tu mamy [22:07] Gynvael: .loop [22:07] Gynvael: mov ax, [esi] [22:07] Gynvael: test al, 0xff [22:07] Gynvael: jz .break [22:07] Gynvael: mov ax, [esi] <=- zczytujemy 2 bajty z ciagu formatujacego [22:07] Gynvael: dwa bajty, zeby wrazie czego jak natrafimy na % moc sprawdzic czy to %u czy %s bez dodatkowego odczytu [22:08] Gynvael: do al trafi pierwszy bajt [22:08] Gynvael: do ax drugi [22:08] Gynvael: test al, 0xff [22:08] Gynvael: cos takiego albo test al,al [22:08] Gynvael: to sposob na sprawdzenie czy w al == 0 [22:08] Gynvael: jesli tak, to jz .break [22:08] Gynvael: czyli wyszkocz z petli [22:08] Gynvael: (dojechalismy do konca ciagu formatujacego) [22:09] Gynvael: cmp al, 0x25 ; '%' [22:09] Gynvael: je .marker [22:09] Gynvael: .nomarker [22:09] Gynvael: cmp to porownanie ofc [22:09] Gynvael: (mentalne odejmowanie hehe) [22:09] Gynvael: sprawdzamy czy al == '%' [22:10] Gynvael: czyli czy to poczatek jakiegos znacznika [22:10] Gynvael: jesli tak [22:10] Gynvael: skaczemu do lokalnego miejsca .marker [22:10] Gynvael: zaraz po tym widac etykiete .nomarker [22:10] Gynvael: tam trafimy jesli sie okaze ze to byl falszywy alarm [22:10] Gynvael: czyli ze to nei jest %s ani %u [22:10] Gynvael: tylko cos innego [22:10] Gynvael: np jakies %k [22:10] Gynvael: lecimy dalej [22:11] Gynvael: zalozmy ze nie znalescismy zadnego markera [22:11] Gynvael: mov [edi], al [22:11] Gynvael: inc edi [22:11] Gynvael: dec ecx [22:11] Gynvael: jnz .skipflush [22:11] Gynvael: call .flush [22:11] Gynvael: .skipflush [22:11] Gynvael: wtedy wykonywane jest cos takiego [22:11] Gynvael: wrzucamy wczytany bajt do buforka [22:11] Gynvael: zwiekszamy adres (edi) [22:11] Gynvael: po czym zmmniejszamy ilosc dostepnych bajtow w buforze [22:12] Gynvael: jesli skonczylo sie miejsce, tzn dec ecx dalo w wyniku 0 i zostala ustawiona flaga ZF [22:12] Gynvael: to skok do .skipflush sie NIEWYKONA [22:12] Gynvael: i zostanie wykonana instrukcja call .flush [22:12] Gynvael: o .flush za chwile ;> [22:12] Gynvael: jesli nie trzeba flushowac bufforka [22:12] Gynvael: albo juz to zrobiliymy [22:13] Gynvael: to dochodzimy do kodu [22:13] Gynvael: inc esi [22:13] Gynvael: jmp .loop [22:13] Gynvael: czyli przesuwamyesi na nastepny bajt ciagu formatujacego [22:13] Gynvael: i idziemy na poczatek petli [22:13] Gynvael: teraz zalozmy ze jednak ten marker sie pojawil [22:13] Gynvael: czyli zostanie wykonany skok do .marker [22:14] Gynvael: cmp ah, 0x75 ; 'u' [22:14] Gynvael: je .marker_uint [22:14] Gynvael: cmp ah, 0x73 ; 's' [22:14] Gynvael: je .marker_string [22:14] Gynvael: jmp .nomarker [22:15] Gynvael: to s sumie prawie ze standardowy switch/case albo if/elseif/else [22:15] Gynvael: czyli [22:15] Gynvael: a [22:15] Gynvael: tu jest porownanie z ah [22:15] Gynvael: czyli z drugim wczytnym znakiem [22:15] Gynvael: ;> [22:15] Gynvael: czyli [22:15] Gynvael: jesli mamy do czynienia z %u, to idziemy do marker_uint [22:16] Gynvael: jesli z %s, to do markser_string [22:16] Gynvael: a jesli nie, to falszywy alarm [22:16] Gynvael: i wracamy do nomarker [22:16] Gynvael: .marker_uint i .marer_string duzo sie nie roznia [22:17] Gynvael: tylko tym czy wywoluja print czy print_int [22:17] Gynvael: ;> [22:17] Gynvael: wiec przeanalizujemy tlyko jeden [22:17] Gynvael: .marker_uint [22:17] Gynvael: inc esi [22:17] Gynvael: inc esi [22:17] Gynvael: call .flush [22:17] Gynvael: push dword [edx] [22:17] Gynvael: call my_print_int [22:18] Gynvael: add edx, 4 [22:18] Gynvael: jmp .loop [22:18] Gynvael: czyli [22:18] Gynvael: najpierw przesuwamy esi o 2 bajty [22:18] Gynvael: czyli omijamy %u [22:18] Gynvael: potem wywolujemy czysczenie buforka [22:18] Gynvael: push dword [edx] wrzuca na stos to na co wskazuje edx [22:19] Gynvael: czyli ten argument dodatkowy [22:19] Gynvael: potem jest wywolany znany juz my_print_int [22:19] Gynvael: po czym przesuwamy edx na nastepny item na stosie [22:19] Gynvael: cyzli 4 bajty dalej [22:19] Gynvael: i idziemy na poczatek petli [22:19] Gynvael: mniej wiecej tyle [22:19] Gynvael: teraz zostalo nam tylko .flush do analizy [22:19] Gynvael: .flush jest stylizowane na funkcje [22:19] Gynvael: .flush mov byte [edi], 0 lea edi, [esp+4] push edi call my_print mov ecx, 0x100 ret [22:20] Gynvael: grr.. [22:20] Gynvael: .flush [22:20] Gynvael: mov byte [edi], 0 [22:20] Gynvael: lea edi, [esp+4] [22:20] Gynvael: push edi [22:20] Gynvael: call my_print [22:20] Gynvael: mov ecx, 0x100 [22:20] Gynvael: ret [22:20] Gynvael: czyli [22:20] Gynvael: w momencie wywolania /flush [22:20] Gynvael: edi pokazuje na nastepny znak w buforze ktory zostanie uzyty [22:21] Gynvael: wrzucamy tam terminator stringow, czyli \0 [22:21] Gynvael: potem do edi wrzucamy adres buforka (poczatkowy) [22:21] Gynvael: jest tutaj lea edi, [esp] [22:21] Gynvael: jest tutaj lea edi, [esp+4] [22:21] Gynvael: a nie lea edi, [esp] [22:21] Gynvael: poniewaz .flush jest call'owany, a jak pamietacie call wrzuca adres powrotu na stos [22:22] Gynvael: czyli esp przesuwa sie o 4 w lewo [22:22] Gynvael: wiec to 4 trzeba dodac [22:22] Gynvael: potem push edi [22:22] Gynvael: i call my_print [22:22] Gynvael: to wrzuca na ekran wszystko co bylo w buforku [22:22] Gynvael: nastepnie resetujemy w ecx ilosc wolnych miejsc w buforq [22:22] Gynvael: i wracamy tam gdzie nas wywolano [22:23] Gynvael: ;> [22:23] Gynvael: i tyle [22:23] Gynvael: SRC=my_printf; nasm -f elf ${SRC}.asm && ld ${SRC}.o -o ${SRC} [22:23] Gynvael: ./my_printf [22:23] Gynvael: rejestr eax == 1234 [22:23] Gynvael: ciag formatujacy mieliscmy [22:23] Gynvael: format: db '%s == %u', 10, 0 [22:23] Gynvael: taki [22:24] Gynvael: wiec uznajmy ze dziala [22:24] Gynvael: teraz pare uwag [22:24] Gynvael: my_printf jest cdecl, nei stdcall [22:24] Gynvael: tzn programista wywolujac ja, musi posprzatac argumenty wrzucone na stos samodzielnie [22:24] Gynvael: stad add esp, 0x0C po call my_printf [22:24] Gynvael: 0x0c to 12... [22:24] Gynvael: 3 argumenty na stos, kazdy po 4 bajty, czyli 12 bajtow [22:24] Gynvael: ;> [22:25] Gynvael: argumenty wrzucamy od tylu [22:25] Gynvael: czyli ejsli teraz mielismy [22:25] Gynvael: my_printf("%s == %u\n", "rejestr eax", 1234) [22:25] Gynvael: to najpierw wrzucamy 1234 [22:25] Gynvael: w tym wypadku to mov eax, 1234 push eax [22:26] Gynvael: potem push text [22:26] Gynvael: a na koncu push format [22:26] Gynvael: section .data [22:26] Gynvael: format: db '%s == %u', 10, 0 [22:26] Gynvael: text: db 'rejestr eax', 0 [22:26] Gynvael: ;> [22:26] Gynvael: ok [22:26] Gynvael: tyle [22:26] Gynvael: pytanka ? [22:26] ant_: jeszcze jeden przyklad? [22:26] ant_: czy to juz koniec? [22:27] Gynvael: w sumie na dzisiaj tyle [22:27] ant_: :) [22:27] Gynvael: sorx za tak krootko [22:27] phoenix__: tyo mozesz juz mi pomoc ;PPPPPPPPPPPP [22:27] Gynvael: ;> [22:27] Gynvael: ;p [22:27] Gynvael: w8 [22:27] Gynvael: jeszcze ogloszenie [22:28] Gynvael: od nastepnego tygodnia bedzie masm32 WinApi [22:28] phoenix__: gyn przedstawia ogloszenie parafialne [22:28] Gynvael: pod winde [22:28] Gynvael: bedzie tego z 2-3 wyklady [22:28] Gynvael: a potem przejde do crackingu i reversingu pod winda [22:28] Gynvael: tez z 2-3 wyklady [22:28] Gynvael: potem wrocimy do linuxa i pobawimy sie gnu assemblerem (2-3 wyklady) [22:29] Gynvael: potem jeden badz dwa wyklady z shellcodingu pod linuxem [22:29] Gynvael: czyli exploity sie klaniaja [22:29] Gynvael: 2-3 wyklady pod dosa i 13h [22:29] Gynvael: i jeden lub dwa wyklady o ipisanniu systemow operacyjnych [22:29] Gynvael: jak widac za duzo nad kazdym tematem sie nie rozwodze [22:29] Gynvael: wiec w sumie to jest bardziej wstep i przejrzenie zagadnien [22:30] Gynvael: niz gruntowny tutorek od a do z [22:30] Gynvael: ;> [22:30] Gynvael: ok [22:30] Gynvael: tyle [22:30] ant_: buuuuuuu w$ buuu... buuuu... w$ buuu yeah linux! :) yeah shellcode! buuu dos... yeah systemy! :) - czyli krotkie podsumowanie :) [22:30] defc0n: narx [22:30] Gynvael: thx za cierpliwosc hehehe - - - - ---- KONIEC WYKLADU ---- - - - -