Zine.net online

Witaj na Zine.net online Zaloguj się | Rejestracja | Pomoc
w Szukaj

mgrzeg.net - Admin on Rails :)

Znajdź najbliższy symbol, czyli jeszcze o bombach

Dziś słów kilka o metodzie, którą roboczo nazwę "Data Driven Rev", a która opiera się na paru prostych sztuczkach z symbolami.

Wprowadzenie

Saper przechowuje gdzieś swoje dane. Ustawienia, położenia bomb - o, to właśnie nas interesuje. Gdzie są bomby?!
W dużym uproszczeniu możemy przyjąć, że saper może przechowywać swoje dane w jednym z kilku miejsc w pamięci procesu: na stercie (heap), na stosie (stack), w obszarze współdzielonym między procesami (shared memory), tudzież plikami mapowanymi w pamięci (memory mapped files), lokalnej pamięci wątku (thread local storage - TLS), a także w segmencie danych (data segment) modułu. Saper to nie jest jednak wysoce skomplikowana aplikacja i możemy spokojnie przyjąć, że nie potrzebuje ani współdzielenia położenia bomb z innymi instancjami sapera, ani nie wiążą się z nimi duże alokacje.
Założenie jest proste: gdzieś w pamięci procesu dane muszą być, więc jak zrobimy migawkę pamięci w jakimś momencie, wykonamy czynność, która powinna nieznacznie zmienić stan aplikacji, po czym ponownie zrzucimy pamięć, to po porównaniu obu zrzutów dostaniemy informację jak wykonana operacja wypłynęła na dane w pamięci.

Symbole

My jednak nie jesteśmy skazani na poruszanie się po pamięci procesu jak dzieci w ciemności - mamy przecież plik z symbolami dostępny na serwerze Microsoftu. I oczywiście zamierzamy je wykorzystać, aby powiązać wyniki porównania zrzutów z informacją symboliczną.

Zacznijmy od przyjrzenia się samym symbolom. Robimy surowy zrzut wszystkich symboli i w wyniku otrzymujemy 276 elementów.

0:000> x winmine!*
01001004          winmine!_imp__RegSetValueExW = <no type information>
0100511c          winmine!yCur = <no type information>
01005b8c          winmine!__onexitend = <no type information>
01001108          winmine!_imp__GetDlgItemTextW = <no type information>
[+272 pozostałe, dla przejrzystości wycięte]

Sięgamy po sprawdzone narzędzie analityczne - Excela i sortujemy wszystkie symbole po adresie, po czym odejmujemy od siebie adresy sąsiadujących symboli, dzięki czemu otrzymamy przybliżone rozmiary odpowiednich elementów (w pliku z symbolami nie mamy informacji o typach danych ani o ich rozmiarze, więc musimy to wydedukować). Poniżej zebrane w tabelce 68 pozycji, a dlaczego akurat te, to za chwilę.

Adres Symbol Rozmiar
1005000 winmine!fStatus 4
1005004 winmine!rgPrefEditID 12
1005010 winmine!rgLevelData 36
1005034 winmine!szXYZZY 156
10050d0 winmine!rgszPref 72
1005118 winmine!xCur 4
100511c winmine!yCur 4
1005120 winmine!szIniFile 24
1005138 winmine!__defaultmatherr 8
1005140 winmine!fButton1Down 4
1005144 winmine!fBlock 4
1005148 winmine!fIgnoreClick 4
100514c winmine!fLocalPause 4
1005150 winmine!idRadCurr 4
1005154 winmine!iXYZZY 4
1005158 winmine!hGrayPen 4
100515c winmine!fUpdateIni 4
1005160 winmine!iButtonCur 4
1005164 winmine!fTimer 4
1005168 winmine!fOldTimerStatus 4
100516c winmine!_dowildcard 4
1005170 winmine!_newmode 4
1005174 winmine!_commode 4
1005178 winmine!_fmode 20
100518c winmine!pHtmlHelpW 4
1005190 winmine!pHtmlHelpA 4
1005194 winmine!cBombLeft 12
10051a0 winmine!rgStepX 400
1005330 winmine!cBombStart 4
1005334 winmine!xBoxMac 4
1005338 winmine!yBoxMac 8
1005340 winmine!rgBlk 864
10056a0 winmine!Preferences 248
1005798 winmine!iStepMac 4
100579c winmine!cSec 4
10057a0 winmine!cBoxVisitMac 4
10057a4 winmine!cBoxVisit 28
10057c0 winmine!rgStepY 400
1005950 winmine!g_hReg 4
1005954 winmine!hResButton 4
1005958 winmine!hResBlks 4
100595c winmine!lpDibLed 4
1005960 winmine!rgDibButton 32
1005980 winmine!MemBlkBitmap 64
10059c0 winmine!rgDibOff 64
1005a00 winmine!lpDibButton 4
1005a04 winmine!lpDibBlks 4
1005a08 winmine!hResLed 24
1005a20 winmine!MemBlkDc 64
1005a60 winmine!rgDibLedOff 48
1005a90 winmine!dxpBorder 4
1005a94 winmine!hMenu 12
1005aa0 winmine!szClass 64
1005ae0 winmine!szTime 64
1005b20 winmine!dyWindow 4
1005b24 winmine!hwndMain 4
1005b28 winmine!hIconMain 4
1005b2c winmine!dxWindow 4
1005b30 winmine!hInst 4
1005b34 winmine!dypMenu 4
1005b38 winmine!bInitMinimized 8
1005b40 winmine!szDefaultName 64
1005b80 winmine!dypCaption 4
1005b84 winmine!dypBorder 4
1005b88 winmine!dypAdjust 4
1005b8c winmine!__onexitend 4
1005b90 winmine!__onexitbegin 4
1005b94 winmine!_adjust_fdiv  

Popatrzmy na pamięć

Super - tabelka z symbolami gotowa. Pytanie tylko, czy w tym gąszczu niewiele mówiących nazw znajdziemy tę, która odkryje nam zaminowane pole. Czas sięgnąć po jeszcze jedno narzędzie analityczne - Process Hacker. Zaglądamy do pamięci winmine.exe i odnajdujemy obszar zajmowany przez obraz programu (zaznaczony czerwoną obwódką na Rys 1.).

Rys 1. Pamięć sapera :)

Podświetlony obszar o rozmiarze 1 strony (4 kB) ma ustawioną ochronę jako RW, czyli do zapisu i do odczytu, co oznacza, że aplikacja może modyfikować ten obszar pamięci i zapisywać tam swoje dane. Moglibyśmy w tym momencie zajrzeć do nagłówka PE, żeby zorientować się, że jest to sekcja danych, obok której znajduje się 16kB segment kodu, ale porównujemy adresy z adresami symboli i szybko dzielimy arkusz z symbolami na dwie części, przy czym w tabelce zostawiamy tylko te symbole, które trafiły do segmentu danych.

Czas na test!

Mając tak przygotowane dane możemy zrobić test związany ze zmianą stanu aplikacji. Nie musimy robić pełnego zrzutu pamięci - zapisujemy z Process Hackera 4 kB obszar danych, zaznaczamy bombę i robimy kolejny zrzut tego samego obszaru pamięci.
Teraz mamy do wyboru - używamy np. Hexedit (ciekawe z jakich narzędzi wy korzystacie?) i porównujemy oba pliki, albo piszemy własne narzędzie, które znajdzie nam różnice.
Tak czy owak odkrywamy, że zmieniły się dwa bajty, a różnice pojawiają się na pozycjach: 0x194 oraz 0x446 względem początku pliku, czyli pod adresami 0x1005194 oraz 0x1005446, biorąc pod uwagę adresy wirtualne.

Najbliższy symbol

Skoro znamy adresy w pamięci, gdzie nastąpiły zmiany, to sprawdźmy, czy jesteśmy w stanie powiązać taki adres z jakimś symbolem.
Z pomocą przychodzi nam tutaj polecenie ln (list nearest symbols):

0:000> ln 0x1005194
(01005194)   winmine!cBombLeft   |  (010051a0)   winmine!rgStepX
Exact matches:
    winmine!cBombLeft = <no type information>
0:000> ln 0x1005446
(01005340)   winmine!rgBlk+0x106   |  (010056a0)   winmine!Preferences

W pierwszym przypadku strzał był precyzyjny - cBombLeft zmieniło się z 0xA na 0x9 :)
W drugim natomiast zmiana nastąpiła w ramach (prawdopodobnie) tablicy rgBlk o rozmiarze 864 bajtów (32*27), na pozycji 0x106, z wartości 0x8F na 0x8E.
Przyglądając się bliżej tablicy rgBlk bez trudu znajdujemy odniesienia do zawartości planszy gry i już wiemy gdzie są poukrywane pozostałe miny :)

Podsumowanie

Mieliśmy komfortową sytuację - wszystkie symbole ładnie przygotowaliśmy w Excelu, więc na dobrą sprawę nie musieliśmy korzystać z polecenia ln, a tylko sięgnąć do arkusza i odczytać odpowiednie symbole.
Zazwyczaj jednak nie chcemy korzystać z Excela, a użycie ln jest proste, szybkie i przyjemne.
Polecenie ln działa w przypadku aplikacji natywnych. A co z .NET? Dzięki bibliotece SOSEX, o której już parokrotnie pisałem, mamy do dyspozycji rozszerzenie !mln:

0:000> !sosex.help mln
SOSEX - Copyright 2007-2011 by Steve Johnson -
http://www.stevestechspot.com/
To report bugs or offer feedback about SOSEX, please email sjjohnson@pobox.com

mln
Usage !sosex.mln [address expression]

Displays the type of CLR data residing at the given address, if it can be determined.
If no address is specified, the current instruction pointer is used as the address.

Sample output:
0:011> !mln 6cd16db4
Method instance: 6cd16d70[System.Threading.ThreadHelper.ThreadStart()]

0:011> !mln 0f85ec88
Stack: debugger thread 11, frame 5

Przyznaję, że planowałem przykład wykorzystania !mln do nieco bardziej rozbudowanego przykładu wyciągania haseł z dumpa KeePassa2, ale to już innym razem.

I na sam koniec - jeśli myślicie, że przykład z poprzedniego wpisu był efektem powyższej analizy, to jesteście w błędzie :) Owszem, korzystałem z ln, ale o tym przy okazji tekstu o security packages i sekretach lsass, o ile ktoś jest zainteresowany ;)

Opublikowane 10 sierpnia 2012 14:47 przez mgrzeg
Filed under: , ,

Powiadamianie o komentarzach

Jeżeli chciałbyś otrzymywać email gdy ta wypowiedź zostanie zaktualizowana, to zarejestruj się tutaj

Subskrybuj komentarze za pomocą RSS

Komentarze:

 

gt said:

Super wpis! Ale bardziej od meritum ujęła mnie napełniająca nostalgią pozycja winmine!szXYZZY :) Ktoś jeszcze pamięta zastosowanie w minesweeperze?

sierpnia 10, 2012 17:19
 

mgrzeg said:

Nie znałem tego, ale już wiem :) Biały pikselek w lewym górnym rogu :)))

sierpnia 11, 2012 01:21
 

Mateusz said:

A czy czasem biały piksel był ostatni raz w XP?

sierpnia 14, 2012 18:11

Co o tym myślisz?

(wymagane) 
(opcjonalne)
(wymagane) 

  
Wprowadź kod: (wymagane)
Wyślij

Subskrypcje

W oparciu o Community Server (Personal Edition), Telligent Systems