Zine.net online

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

mgrzeg.net - Admin on Rails :)

Memory dump a screenshot

Kilku śmiałków postanowiło odpowiedzieć na moje wyzwanie rzucone w poprzednim wpisie, nadszedł zatem czas na moje rozwiązanie. Postanowiłem jednak, że odpowiem pełnymi zdaniami, a inni sami ustalą, która z odpowiedzi jest najbliższa prawdy (a przynajmniej mojej wersji prawdy ;)). Zaczynamy od zrzutów ekranu

1. Mając do dyspozycji pełny memory.dmp można wygenerować zrzuty ekranu dla wszystkich aktywnych sesji z momentu padu systemu, a także co się działo w systemie w ostatnich sekundach przed padem.

Dziś kilka słów o pierwszej - tłuściutkiej części zdania.

Intro

W Windows 7 obsługa okien realizowana jest w dużej mierze w obrębie win32k.sys. Aby dostać się do struktur win32k, musimy pogrzebać nieco głębiej w systemie. Potrzebny nam zatem będzie kernel debugger i łyk wiedzy o wewnętrznych strukturach win32k.

W czasie tworzenia procesu Win32, po wstępnym przygotowaniu przez system struktury EPROCESS, CSRSS tworzy obiekt CSR_PROCESS, po czym win32k dodaje do własnej listy procesów odpowiedni obiekt W32PROCESS. Podobnie dzieje się z wątkami - tam, gdzie mamy do czynienia z wątkiem GUI, tworzony jest obiekt W32THREAD i dowiązywany do odpowiedniej listy. W ramach struktury nt!_EPROCESS możemy znaleźć pole Win32Process, które prowadzi nas wprost do struktury win32k!tagPROCESSINFO.

W poszukiwaniu okien

Bez dalszych opowieści, weźmy zatem pełny dump systemu (przygotowany z poziomu debuggera jądra podłączonego do działającego systemu, bezpośrednio po ctrl+break) i przyjrzyjmy się kalkulatorowi.

kd> !process 0 0 calc.exe
PROCESS fffffa8003951060
    SessionId: 1  Cid: 0bf8    Peb: 7fffffd9000  ParentCid: 0b50
    DirBase: 1a014000  ObjectTable: fffff8a002b7b0e0  HandleCount:  75.
    Image: calc.exe

kd> .process /P fffffa8003951060
Implicit process is now fffffa80`03951060

kd> dt nt!_EPROCESS fffffa8003951060 Win32Process
   +0x258 Win32Process : 0xfffff900`c1acd9b0 Void

Mamy zatem obiekt win32k!tagPROCESSINFO powiązany z procesem calc.exe. Przy okazji uwaga odnośnie układu pamięci wirtualnej jądra x64 - pole Win32Process wskazuje na adres w 512 GB obszarze sesji, przeznaczonym właśnie m.in. na win32k.sys (za Russinovichem oraz http://www.codemachine.com/article_x64kvas.html).

Przeglądając zawartość struktury win32k!tagPROCESSINFO uświadamiamy sobie, że nie mamy powiązania z oknami należącymi do tego procesu. Mamy jednak adres pulpitu startowego, dzięki czemu możemy próbować dojść do procesu od strony okien :)

kd> dt win32k!tagPROCESSINFO 0xfffff900`c1acd9b0 rpdeskStartup
   +0x110 rpdeskStartup : 0xfffffa80`034c07a0 tagDESKTOP

tu przechodzimy dalej do tagDESKTOPINFO

kd> dt win32k!tagDESKTOP 0xfffffa80`034c07a0 pDeskInfo
   +0x008 pDeskInfo : 0xfffff900`c0600a70 tagDESKTOPINFO

i stąd zaczynamy listować wszystkie okna, zaczynając od pola spwnd

kd> dt win32k!tagDESKTOPINFO 0xfffff900`c0600a70 spwnd
   +0x010 spwnd : 0xfffff900`c0600b90 tagWND

Przechodzimy po kolei wszystkie okna (spwndNext, spwndChild), aby wreszcie trafić na okno:

kd> dt win32k!tagWND fffff900c061f730
   +0x000 head             : _THRDESKHEAD
   +0x028 state            : 0x50020009
   +0x028 bHasMeun         : 0y1
   +0x028 bHasVerticalScrollbar : 0y0
   +0x028 bHasHorizontalScrollbar : 0y0
   +0x028 bHasCaption      : 0y1
   +0x028 bSendSizeMoveMsgs : 0y0
   +0x028 bMsgBox          : 0y0
   +0x028 bActiveFrame     : 0y0
   +0x028 bHasSPB          : 0y0
   +0x028 bNoNCPaint       : 0y0
   +0x028 bSendEraseBackground : 0y0
   +0x028 bEraseBackground : 0y0
   +0x028 bSendNCPaint     : 0y0
   +0x028 bInternalPaint   : 0y0
   +0x028 bUpdateDirty     : 0y0
   +0x028 bHiddenPopup     : 0y0
   +0x028 bForceMenuDraw   : 0y0
   +0x028 bDialogWindow    : 0y0
   +0x028 bHasCreatestructName : 0y1
   +0x028 bServerSideWindowProc : 0y0
   +0x028 bAnsiWindowProc  : 0y0
   +0x028 bBeingActivated  : 0y0
   +0x028 bHasPalette      : 0y0
   +0x028 bPaintNotProcessed : 0y0
   +0x028 bSyncPaintPending : 0y0
   +0x028 bRecievedQuerySuspendMsg : 0y0
   +0x028 bRecievedSuspendMsg : 0y0
   +0x028 bToggleTopmost   : 0y0
   +0x028 bRedrawIfHung    : 0y0
   +0x028 bRedrawFrameIfHung : 0y1
   +0x028 bAnsiCreator     : 0y0
   +0x028 bMaximizesToMonitor : 0y1
   +0x028 bDestroyed       : 0y0
   +0x02c state2           : 0x80000700
   +0x02c bWMPaintSent     : 0y0
   +0x02c bEndPaintInvalidate : 0y0
   +0x02c bStartPaint      : 0y0
   +0x02c bOldUI           : 0y0
   +0x02c bHasClientEdge   : 0y0
   +0x02c bBottomMost      : 0y0
   +0x02c bFullScreen      : 0y0
   +0x02c bInDestroy       : 0y0
   +0x02c bWin31Compat     : 0y1
   +0x02c bWin40Compat     : 0y1
   +0x02c bWin50Compat     : 0y1
   +0x02c bMaximizeMonitorRegion : 0y0
   +0x02c bCloseButtonDown : 0y0
   +0x02c bMaximizeButtonDown : 0y0
   +0x02c bMinimizeButtonDown : 0y0
   +0x02c bHelpButtonDown  : 0y0
   +0x02c bScrollBarLineUpBtnDown : 0y0
   +0x02c bScrollBarPageUpBtnDown : 0y0
   +0x02c bScrollBarPageDownBtnDown : 0y0
   +0x02c bScrollBarLineDownBtnDown : 0y0
   +0x02c bAnyScrollButtonDown : 0y0
   +0x02c bScrollBarVerticalTracking : 0y0
   +0x02c bForceNCPaint    : 0y0
   +0x02c bForceFullNCPaintClipRgn : 0y0
   +0x02c FullScreenMode   : 0y000
   +0x02c bCaptionTextTruncated : 0y0
   +0x02c bNoMinmaxAnimatedRects : 0y0
   +0x02c bSmallIconFromWMQueryDrag : 0y0
   +0x02c bShellHookRegistered : 0y0
   +0x02c bWMCreateMsgProcessed : 0y1
   +0x030 ExStyle          : 0xe0080900
   +0x030 bWS_EX_DLGMODALFRAME : 0y0
   +0x030 bUnused1         : 0y0
   +0x030 bWS_EX_NOPARENTNOTIFY : 0y0
   +0x030 bWS_EX_TOPMOST   : 0y0
   +0x030 bWS_EX_ACCEPTFILE : 0y0
   +0x030 bWS_EX_TRANSPARENT : 0y0
   +0x030 bWS_EX_MDICHILD  : 0y0
   +0x030 bWS_EX_TOOLWINDOW : 0y0
   +0x030 bWS_EX_WINDOWEDGE : 0y1
   +0x030 bWS_EX_CLIENTEDGE : 0y0
   +0x030 bWS_EX_CONTEXTHELP : 0y0
   +0x030 bMakeVisibleWhenUnghosted : 0y1
   +0x030 bWS_EX_RIGHT     : 0y0
   +0x030 bWS_EX_RTLREADING : 0y0
   +0x030 bWS_EX_LEFTSCROLLBAR : 0y0
   +0x030 bUnused2         : 0y0
   +0x030 bWS_EX_CONTROLPARENT : 0y0
   +0x030 bWS_EX_STATICEDGE : 0y0
   +0x030 bWS_EX_APPWINDOW : 0y0
   +0x030 bWS_EX_LAYERED   : 0y1
   +0x030 bWS_EX_NOINHERITLAYOUT : 0y0
   +0x030 bUnused3         : 0y0
   +0x030 bWS_EX_LAYOUTRTL : 0y0
   +0x030 bWS_EX_NOPADDEDBORDER : 0y0
   +0x030 bUnused4         : 0y0
   +0x030 bWS_EX_COMPOSITED : 0y0
   +0x030 bUIStateActive   : 0y0
   +0x030 bWS_EX_NOACTIVATE : 0y0
   +0x030 bWS_EX_COMPOSITEDCompositing : 0y0
   +0x030 bRedirected      : 0y1
   +0x030 bUIStateKbdAccelHidden : 0y1
   +0x030 bUIStateFocusRectHidden : 0y1
   +0x034 style            : 0x14ca0000
   +0x034 bReserved1       : 0y0000000000000000 (0)
   +0x034 bWS_MAXIMIZEBOX  : 0y0
   +0x034 bReserved2       : 0y0000000000000000 (0)
   +0x034 bWS_TABSTOP      : 0y0
   +0x034 bReserved3       : 0y0000000000000000 (0)
   +0x034 bUnused5         : 0y0
   +0x034 bWS_MINIMIZEBOX  : 0y1
   +0x034 bReserved4       : 0y0000000000000000 (0)
   +0x034 bUnused6         : 0y0
   +0x034 bWS_GROUP        : 0y1
   +0x034 bReserved5       : 0y0000000000000000 (0)
   +0x034 bUnused7         : 0y10
   +0x034 bWS_THICKFRAME   : 0y0
   +0x034 bReserved6       : 0y0000000000000000 (0)
   +0x034 bUnused8         : 0y10
   +0x034 bWS_SIZEBOX      : 0y0
   +0x034 bReserved7       : 0y0000000000000000 (0)
   +0x034 bUnused9         : 0y010
   +0x034 bWS_SYSMENU      : 0y1
   +0x034 bWS_HSCROLL      : 0y0
   +0x034 bWS_VSCROLL      : 0y0
   +0x034 bWS_DLGFRAME     : 0y1
   +0x034 bWS_BORDER       : 0y1
   +0x034 bMaximized       : 0y0
   +0x034 bWS_CLIPCHILDREN : 0y0
   +0x034 bWS_CLIPSIBLINGS : 0y1
   +0x034 bDisabled        : 0y0
   +0x034 bVisible         : 0y1
   +0x034 bMinimized       : 0y0
   +0x034 bWS_CHILD        : 0y0
   +0x034 bWS_POPUP        : 0y0
   +0x038 hModule          : 0x00000000`ff6f0000 Void
   +0x040 hMod16           : 0
   +0x042 fnid             : 0
   +0x048 spwndNext        : 0xfffff900`c062a730 tagWND
   +0x050 spwndPrev        : 0xfffff900`c06226d0 tagWND
   +0x058 spwndParent      : 0xfffff900`c0600b90 tagWND
   +0x060 spwndChild       : 0xfffff900`c0622a10 tagWND
   +0x068 spwndOwner       : (null)
   +0x070 rcWindow         : tagRECT
   +0x080 rcClient         : tagRECT
   +0x090 lpfnWndProc      : 0x00000000`ff6f1c58     int64  +ff6f1c58
   +0x098 pcls             : 0xfffff900`c061f590 tagCLS
   +0x0a0 hrgnUpdate       : (null)
   +0x0a8 ppropList        : 0xfffff900`c0627c10 tagPROPLIST
   +0x0b0 pSBInfo          : (null)
   +0x0b8 spmenuSys        : (null)
   +0x0c0 spmenu           : 0xfffff900`c061f860 tagMENU
   +0x0c8 hrgnClip         : (null)
   +0x0d0 hrgnNewFrame     : (null)
   +0x0d8 strName          : _LARGE_UNICODE_STRING
   +0x0e8 cbwndExtra       : 0n0
   +0x0f0 spwndLastActive  : 0xfffff900`c061f730 tagWND
   +0x0f8 hImc             : 0x00000000`000501d1 HIMC__
   +0x100 dwUserData       : 0
   +0x108 pActCtx          : (null)
   +0x110 pTransform       : (null)
   +0x118 spwndClipboardListenerNext : (null)
   +0x120 ExStyle2         : 0x18
   +0x120 bClipboardListener : 0y0
   +0x120 bLayeredInvalidate : 0y0
   +0x120 bRedirectedForPrint : 0y0
   +0x120 bLinked          : 0y1
   +0x120 bLayeredForDWM   : 0y1
   +0x120 bLayeredLimbo    : 0y0
   +0x120 bHIGHDPI_UNAWARE_Unused : 0y0
   +0x120 bVerticallyMaximizedLeft : 0y0
   +0x120 bVerticallyMaximizedRight : 0y0
   +0x120 bHasOverlay      : 0y0
   +0x120 bConsoleWindow   : 0y0
   +0x120 bChildNoActivate : 0y0

Tu nas interesują pola:
   +0x000 head             : _THRDESKHEAD
dalej
   +0x070 rcWindow         : tagRECT
oraz
   +0x0d8 strName          : _LARGE_UNICODE_STRING
i skoro już tu jesteśmy - niech mi ktoś powie, co określa pole
   +0x028 bHasMeun         : 0y1
bo nic mi nie przychodzi do głowy ;) (tak przy okazji - okno kalkulatora posiada menu)

Z pierwszego z pól wyciągamy kolejno:

kd> dt win32k!_THRDESKHEAD fffff900c061f730 pti
   +0x010 pti : 0xfffff900`c1ea7930 tagTHREADINFO
kd> dt win32k!tagTHREADINFO 0xfffff900`c1ea7930 ppi
   +0x158 ppi : 0xfffff900`c1acd9b0 tagPROCESSINFO
kd> dt win32k!tagPROCESSINFO 0xfffff900`c1acd9b0 Process
   +0x000 Process : 0xfffffa80`03951060 _EPROCESS
kd> dt nt!_EPROCESS 0xfffffa80`03951060 UniqueProcessId ImageFileName
   +0x180 UniqueProcessId : 0x00000000`00000bf8 Void
   +0x2e0 ImageFileName   : [15]  "calc.exe"

i jesteśmy w domu! :)

Drugie pole to struktura opisująca położenie lewego górnego oraz prawego dolnego rogu okna:

kd> dt win32k!tagRECT fffff900c061f730+0x070
   +0x000 left             : 0n154
   +0x004 top              : 0n140
   +0x008 right            : 0n382
   +0x00c bottom           : 0n462

Trzecie pole to struktura typu win32k!_LARGE_UNICODE_STRING, w której znajduje się tytuł okna. Zrzucamy ją zatem

kd> dt win32k!_LARGE_UNICODE_STRING fffff900c061f730+0x0d8
   +0x000 Length           : 0x14
   +0x004 MaximumLength    : 0y0000000000000000000000000010110 (0x16)
   +0x004 bAnsi            : 0y0
   +0x008 Buffer           : 0xfffff900`c0622690  -> 0x43

a następnie z pola Buffer wyciągamy odpowiedni tekst:

kd> du 0xfffff900`c0622690
fffff900`c0622690  "Calculator"

Nie ukrywam, że do znalezienia odpowiedniego okna napisałem drobne rozszerzenie windbg, które przeczesało mi po kolei okna należące do desktopu powiązanego z procesem.

Oczywiście, mając informację o tytułach okien, ich położeniu i rozmiarach, możemy pokusić się o wygenerowanie grafiki, która będzie przedstawiać odpowiedni dekstop.

Volatility

I dokładnie z tego mechanizmu korzysta polecenie screenshot z pakietu Volatility, zaczyna jednak nieco wyżej - listuje po kolei wszystkie stacje okienkowe, następnie należące do nich desktopy i dla każdego z nich generuje plik .png. Do wykonania zrzutu korzystamy z polecenia

>python vol.py -f win7x86.dmp --profile=Win7SP1x86 screenshot -D screnshots/
Volatile Systems Volatility Framework 2.3_alpha
Wrote screenshots\session_0.msswindowstation.mssrestricteddesk.png
Wrote screenshots\session_0.Service-0x0-3e4$.Default.png
Wrote screenshots\session_0.Service-0x0-3e5$.Default.png
Wrote screenshots\session_0.Service-0x0-3e7$.Default.png
Wrote screenshots\session_0.WinSta0.Default.png
Wrote screenshots\session_0.WinSta0.Disconnect.png
Wrote screenshots\session_0.WinSta0.Winlogon.png
Wrote screenshots\session_1.WinSta0.Default.png
Wrote screenshots\session_1.WinSta0.Disconnect.png
Wrote screenshots\session_1.WinSta0.Winlogon.png

Poniżej porównanie: rzeczywisty zrzut ekranu

Rys 1. Rzeczywisty zrzut ekranu

i zrzut wygenerowany przez Volatility z memory dumpa

Rys 2. Zrzut ekranu wygenerowany przez Volatility

Różnicę widać gołym okiem i ocenę, czy jest to zrzut ekranu, czy nie pozostawiam Wam.

Zapewne zauważyliście, że do wykonania zrzutu skorzystałem z dumpa x86, podczas gdy opis obejmował x64. Z jakiejś przyczyny Volatility dla wersji x64 nie potrafi prawidłowo zinterpretować strName i - przynajmniej u mnie - generuje zrzut bez nazw okien.

A na koniec zagadka: do czego służyło mi polecenie

kd> .process /P fffffa8003951060

i co bym otrzymał dalej, gdybym go nie wykonał?

Opublikowane 23 sierpnia 2013 21:26 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:

 

Grzechooo said:

Ciekawi mnie, czy możnaby wyciągnąć tapetę dla każdego pulpitu. Pewnie można, podłubię nieco przy jakimś dumpie ;)

sierpnia 24, 2013 12:44

Co o tym myślisz?

(wymagane) 
(opcjonalne)
(wymagane) 

  
Wprowadź kod: (wymagane)
Wyślij

Subskrypcje

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