Windows GUI
Sessions
Stations
Desktops
Windows
Malware and the GUI
Manages
Outermost layer of the GUI landscape
Contains unique session ID
Created when a user logs into the machine
Sessions are tied to a particular users and resources can be attributed to them.
Atom table - Group of strings shared between applications
One or more windows stations
handle table
Interactive
Applications requiring input
Each has its own
User interface objects
Windows can be invisible or visible, have screen coordinates and procedures for messaging
user32.dll
gdi32.dll
Equivalent to ntdl.dll for native APIs
Contain stubs to route through the SSDT[1] into win32k.sys.
Recall the volatility plugin SSDT
SSDT[1] contains all of the GUI functions
SSDT[1] at 9153b000 with 825 entries
Entry 0x1000: 0x914c7cbd (NtGdiAbortDoc) owned by win32k.sys
Entry 0x1001: 0x914dfc7e (NtGdiAbortPath) owned by win32k.sys
Entry 0x1002: 0x91337252 (NtGdiAddFontResourceW) owned by win32k.sys
Entry 0x1003: 0x914d6ab6 (NtGdiAddRemoteFontToDC) owned by win32k.sys
Entry 0x1004: 0x914e1421 (NtGdiAddFontMemResourceEx) owned by win32k.sys
Entry 0x1005: 0x914c84da (NtGdiRemoveMergeFont) owned by win32k.sys
Entry 0x1006: 0x914c856e (NtGdiAddRemoteMMInstanceToDC) owned by win32k.sys
Entry 0x1007: 0x913ef93b (NtGdiAlphaBlend) owned by win32k.sys
Entry 0x1008: 0x914e0c57 (NtGdiAngleArc) owned by win32k.sys
Entry 0x1009: 0x913a36eb (NtGdiAnyLinkedFonts) owned by win32k.sys
Entry 0x100a: 0x913a3608 (NtGdiFontIsLinked) owned by win32k.sys
Debugging information only appears in Windows 7
All other windows versions are undocumented
Makes GUI forensics difficult...
| Plugin | Description |
|--------------|----------------------------------------------------|
| sessions | Lists details on user logon sessions |
| wndscan | Enumerates window stations and their properties |
| deskscan | Analyzes desktops and associated threads |
| atomscan | Scans for atoms (globally shared strings) |
| atoms | Prints session and window station atom tables |
| messagehooks | Lists desktop and thread window message hooks |
| eventhooks | Prints details on windows event hooks |
| windows | Enumerates windows |
| wintree | Prints Z-Order desktop windows trees |
| gahti | Dumps the USER handle type information |
| userhandles | Dumps the USER handle table objects |
| gditimers | Examines the use of GDI timers |
| screenshot | Saves a pseudo screenshot based on GDI windows |
Outer layer of the GUI landscape
User log on creates a new session
Container for processes, objects, stations and desktops.
Memory samples contain active and terminated logon sessions including processes, modules, pool allocations, etc...
_MM_SESSION_SPACE
_EPROCESS.Session contain pointers to _MM_SESSION_SPACE
>>> dt("_MM_SESSION_SPACE")
'_MM_SESSION_SPACE' (8192 bytes)
0x0 : ReferenceCount ['long']
0x4 : u ['__unnamed_20df']
0x8 : SessionId ['unsigned long']
0xc : ProcessReferenceToSession ['long']-
0x10 : ProcessList ['_LIST_ENTRY']
0x18 : LastProcessSwappedOutTime ['_LARGE_INTEGER']
0x20 : SessionPageDirectoryIndex ['unsigned long']
0x24 : NonPagablePages ['unsigned long']
0x28 : CommittedPages ['unsigned long']
0x2c : PagedPoolStart ['pointer', ['void']]
0x30 : PagedPoolEnd ['pointer', ['void']]
0x34 : SessionObject ['pointer', ['void']]
0x38 : SessionObjectHandle ['pointer', ['void']]
0x3c : ResidentProcessCount ['long']
0x40 : SessionPoolAllocationFailures ['array', 4, ['unsigned long']]
0x50 : ImageList ['_LIST_ENTRY']
0x58 : LocaleId ['unsigned long']
0x5c : AttachCount ['unsigned long']
0x60 : AttachGate ['_KGATE']
0x70 : WsListEntry ['_LIST_ENTRY']
0x80 : Lookaside ['array', 25, ['_GENERAL_LOOKASIDE']]
0xd00 : Session ['_MMSESSION']
0xd38 : PagedPoolInfo ['_MM_PAGED_POOL_INFO']
0xd70 : Vm ['_MMSUPPORT']
0xddc : Wsle ['pointer', ['_MMWSLE']]
0xde0 : DriverUnload ['pointer', ['void']]
0xe00 : PagedPool ['_POOL_DESCRIPTOR']
0x1f40: PageTables ['pointer', ['_MMPTE']]
0x1f44: SpecialPool ['_MI_SPECIAL_POOL']
0x1f68: SessionPteLock ['_KGUARDED_MUTEX']
0x1f88: PoolBigEntriesInUse ['long']
0x1f8c: PagedPoolPdeCount ['unsigned long']
0x1f90: SpecialPoolPdeCount ['unsigned long']
0x1f94: DynamicSessionPdeCount ['unsigned long']
0x1f98: SystemPteInfo ['_MI_SYSTEM_PTE_TYPE']
0x1fc8: PoolTrackTableExpansion ['pointer', ['void']]
0x1fcc: PoolTrackTableExpansionSize ['unsigned long']
0x1fd0: PoolTrackBigPages ['pointer', ['void']]
0x1fd4: PoolTrackBigPagesSize ['unsigned long']
0x1fd8: IoState ['Enumeration', {'target': 'long', 'choices': {1: 'IoSessionStateCreated', 2: 'IoSessionStateInitialized', 3: 'IoSessionStateConnected', 4: 'IoSessionStateDisconnected', 5: 'IoSessionStateDisconnectedLoggedOn', 6: 'IoSessionStateLoggedOn', 7: 'IoSessionStateLoggedOff', 8: 'IoSessionStateTerminated', 9: 'IoSessionStateMax'}}]
0x1fdc: IoStateSequence ['unsigned long']
0x1fe0: IoNotificationEvent ['_KEVENT']
0x1ff0: SessionPoolPdes ['_RTL_BITMAP']
0x1ff8: CpuQuotaBlock ['pointer', ['_PS_CPU_QUOTA_BLOCK']]
>>>
Important points are
SessionId: Unique SID for the session. Remember session 0 is isolated for system services
ProcessList: each session has its own process list. Each process belongs to one session except System and smss.exe...
ImageList: A list of _IMAGE_ENTRY_IN_SESSION structures for each device... each session has its own list, so two copies of win32k.sys
>>> dt("_IMAGE_ENTRY_IN_SESSION")
'_IMAGE_ENTRY_IN_SESSION' (None bytes)
0x0 : Link ['_LIST_ENTRY']
0x8 : Address ['pointer', ['address']]
0xc : LastAddress ['pointer', ['address']]
0x18 : DataTableEntry ['pointer', ['_LDR_DATA_TABLE_ENTRY']]
>>> dt("_LDR_DATA_TABLE_ENTRY")
'_LDR_DATA_TABLE_ENTRY' (120 bytes)
0x0 : InLoadOrderLinks ['_LIST_ENTRY']
0x8 : InMemoryOrderLinks ['_LIST_ENTRY']
0x10 : InInitializationOrderLinks ['_LIST_ENTRY']
0x18 : DllBase ['pointer', ['void']]
0x1c : EntryPoint ['pointer', ['void']]
0x20 : SizeOfImage ['unsigned long']
0x24 : FullDllName ['_UNICODE_STRING']
0x2c : BaseDllName ['_UNICODE_STRING']
0x34 : Flags ['unsigned long']
0x38 : LoadCount ['unsigned short']
0x3a : TlsIndex ['unsigned short']
0x3c : HashLinks ['_LIST_ENTRY']
0x3c : SectionPointer ['pointer', ['void']]
0x40 : CheckSum ['unsigned long']
0x44 : LoadedImports ['pointer', ['void']]
0x44 : TimeDateStamp ['UnixTimeStamp', {'is_utc': True}]
0x48 : EntryPointActivationContext ['pointer', ['_ACTIVATION_CONTEXT']]
0x4c : PatchInformation ['pointer', ['void']]
0x50 : ForwarderLinks ['_LIST_ENTRY']
0x58 : ServiceTagLinks ['_LIST_ENTRY']
0x60 : StaticLinks ['_LIST_ENTRY']
0x68 : ContextInformation ['pointer', ['void']]
0x6c : OriginalBase ['unsigned long']
0x70 : LoadTime ['WinTimeStamp', {'is_utc': True}]
Remote Desktop Protocol (RDP) allows remote connectivity to a windows machine.
RDP uses its own video driver to render display through network packets
All environment variables are determined by RCP-Tcp connection settings.
Commonly used by attackers... MetaSploit makes it easy to get RDP sessions
TCP and UDP Port 3389!
RDPDD.dll and rdppclip.exe are running in a session.
RDPDD is the display driver
rdpclip handles remote clipboard operations
Volatility plugin to list details on user logon sessions
Shows important fields in _MM_SESSION_SPACE
[root&windows]#volatility -f Win7.bin --profile=Win7SP0x86 sessions
Volatility Foundation Volatility Framework 2.4
**************************************************
Session(V): 88e63000 ID: 0 Processes: 29
PagedPoolStart: 80000000 PagedPoolEnd ffbfffff
Process: 348 csrss.exe 2013-10-15 18:45:53 UTC+0000
Process: 400 wininit.exe 2013-10-15 18:45:53 UTC+0000
Process: 504 services.exe 2013-10-15 18:45:53 UTC+0000
Process: 520 lsass.exe 2013-10-15 18:45:53 UTC+0000
Process: 528 lsm.exe 2013-10-15 18:45:53 UTC+0000
[SNIP]
**************************************************
Session(V): 88e76000 ID: 1 Processes: 23
PagedPoolStart: 80000000 PagedPoolEnd ffbfffff
Process: 412 csrss.exe 2013-10-15 18:45:53 UTC+0000
Process: 468 winlogon.exe 2013-10-15 18:45:53 UTC+0000
Process: 320 taskhost.exe 2013-10-15 18:45:59 UTC+0000
Process: 1916 dwm.exe 2013-10-15 18:45:59 UTC+0000
Use getsids on a process to get information about its owner
Example: for Session ID 1 on process 1916 (dwm.exe)
[root&windows]#volatility -f Win7.bin --profile=Win7SP0x86 getsids -p 1916
Volatility Foundation Volatility Framework 2.4
dwm.exe (1916): S-1-5-21-2833823845-3085568943-3082117713-1000 (Daniel)
dwm.exe (1916): S-1-5-21-2833823845-3085568943-3082117713-513 (Domain Users)
dwm.exe (1916): S-1-1-0 (Everyone)
dwm.exe (1916): S-1-5-32-544 (Administrators)
dwm.exe (1916): S-1-5-32-545 (Users)
dwm.exe (1916): S-1-5-4 (Interactive)
dwm.exe (1916): S-1-2-1 (Console Logon (Users who are logged onto the physical console))
dwm.exe (1916): S-1-5-11 (Authenticated Users)
dwm.exe (1916): S-1-5-15 (This Organization)
dwm.exe (1916): S-1-5-5-0-163520 (Logon Session)
dwm.exe (1916): S-1-2-0 (Local (Users with the ability to log in locally))
dwm.exe (1916): S-1-5-64-10 (NTLM Authentication)
dwm.exe (1916): S-1-16-8192 (Medium Mandatory Level)
Would look like..
python vol.py -f rdp.mem --profile=Win2003SP2x86 sessions
**************************************************
Session(V): f79ff000 ID: 2 Processes: 10
PagedPoolStart: bc000000 PagedPoolEnd bc3fffff
Process: 7888 csrss.exe 2012-05-23 02:51:43
Process: 3272 winlogon.exe 2012-05-23 02:51:43
Process: 6772 rdpclip.exe 2012-05-23 02:52:00
Image: 0x8a2fecc0, Address bf800000, Name: win32k.sys
Image: 0x877d0478, Address bf9d3000, Name: dxg.sys
Image: 0x8a1bdf38, Address bff60000, Name: RDPDD.dll
Image: 0x8771a970, Address bfa1e000, Name: ATMFD.DLL
Common for malware authors to use RDP file transfer
Also FTP, Dropbox, S3... [insert name of file hoster]
Find command history / MRUs to help discover how information was sent out
Extracts command history by scanning for _CONSOLE_INFORMATION structures
_CONSOLE_INFORMATION collects the entire screen buffer! Can see output of each command!
>>> dt("_CONSOLE_INFORMATION")
'_CONSOLE_INFORMATION' (None bytes)
0x18 : ProcessList ['_LIST_ENTRY']
0x98 : CurrentScreenBuffer ['pointer', ['_SCREEN_INFORMATION']]
0x9c : ScreenBuffer ['pointer', ['_SCREEN_INFORMATION']]
0xd4 : HistoryList ['_LIST_ENTRY']
0xdc : ExeAliasList ['_LIST_ENTRY']
0xe4 : HistoryBufferCount ['unsigned short']
0xe6 : HistoryBufferMax ['unsigned short']
0xe8 : CommandHistorySize ['unsigned short']
0xec : OriginalTitle ['pointer', ['String', {'length': 256, 'encoding': 'utf16'}]]
0xf0 : Title ['pointer', ['String', {'length': 256, 'encoding': 'utf16'}]]
>>> dt("_SCREEN_INFORMATION")
'_SCREEN_INFORMATION' (None bytes)
0x8 : ScreenX ['short']
0xa : ScreenY ['short']
0x3c : Rows ['pointer', ['array', <function <lambda> at 0xa5298ec>, ['_ROW']]]
0xdc : Next ['pointer', ['_SCREEN_INFORMATION']]
Shows console window title
Name and pid of processes
Alias associated with command executed
Screen coordinates of cmd.exe console
$ python vol.py -f xp-laptop-2005-07-04-1430.img consoles
[csrss.exe @ 0x821c11a8 pid 456 console @ 0x4e23b0]
OriginalTitle: '%SystemRoot%\\system32\\cmd.exe'
Title: 'C:\\WINDOWS\\system32\\cmd.exe - dd if=\\\\.\\PhysicalMemory of=c:\\xp-2005-07-04-1430.img conv=noerror'
HistoryBufferCount: 2
HistoryBufferMax: 4
CommandHistorySize: 50
[history @ 0x4e4008]
CommandCount: 0
CommandCountMax: 50
Application: 'dd.exe'
[history @ 0x4e4d88]
CommandCount: 20
CommandCountMax: 50
Application: 'cmd.exe'
Cmd #0 @ 0x4e1f90: 'dd'
Cmd #1 @ 0x4e2cb8: 'cd\\'
Cmd #2 @ 0x4e2d18: 'dr'
Cmd #3 @ 0x4e2d28: 'ee:'
Cmd #4 @ 0x4e2d38: 'e;'
Cmd #5 @ 0x4e2d48: 'e:'
Cmd #6 @ 0x4e2d58: 'dr'
Cmd #7 @ 0x4e2d68: 'd;'
Cmd #8 @ 0x4e2d78: 'd:'
Cmd #9 @ 0x4e2d88: 'dr'
Cmd #10 @ 0x4e2d98: 'ls'
Cmd #11 @ 0x4e2da8: 'cd Docu'
Cmd #12 @ 0x4e2dc0: 'cd Documents and'
Cmd #13 @ 0x4e2e58: 'dr'
Cmd #14 @ 0x4e2e68: 'd:'
Cmd #15 @ 0x4e2e78: 'cd dd\\'
Cmd #16 @ 0x4e2e90: 'cd UnicodeRelease'
Cmd #17 @ 0x4e2ec0: 'dr'
Cmd #18 @ 0x4e2ed0: 'dd '
Cmd #19 @ 0x4e4100: 'dd if=\\\\.\\PhysicalMemory of=c:\\xp-2005-07-04-1430.img conv=noerror'
Contained within sessions
Stations are security boundaries for processes and desktops
Can detect clipboard activity and frequency of its usage
tagWINDOWSTATION is the structure for stations .
win32k!grpWinStaList has the linked list of stations
Only one station can interact with the user at the console (Winsta0)
>>> dt("tagWINDOWSTATION")
'tagWINDOWSTATION' (88 bytes)
0x0 : dwSessionId ['unsigned long'] #window station to owning session _MM_SESSION_SPACE.SessionId
0x4 : rpwinstaNext ['pointer', ['tagWINDOWSTATION']] #Doubly linked list
0x8 : rpdeskList ['pointer', ['tagDESKTOP']] #pointer to windows station's first desktop
0xc : pTerm ['pointer', ['tagTERMINAL']]
0x10 : dwWSF_Flags ['unsigned long'] #interative desktop flag (WSF_NOIO)
0x14 : spklList ['pointer', ['tagKL']]
0x18 : ptiClipLock ['pointer', ['tagTHREADINFO']]
0x1c : ptiDrawingClipboard ['pointer', ['tagTHREADINFO']]
0x20 : spwndClipOpen ['pointer', ['tagWND']]
0x24 : spwndClipViewer ['pointer', ['tagWND']]
0x28 : spwndClipOwner ['pointer', ['tagWND']]
0x2c : pClipBase ['pointer', ['array', <function <lambda> at 0xb73723e4>, ['tagCLIP']]] #clipboard strucutres
0x30 : cNumClipFormats ['unsigned long']
0x34 : iClipSerialNumber ['unsigned long'] #increments by 1 each time clipboard is used
0x38 : iClipSequenceNumber ['unsigned long']
0x3c : spwndClipboardListener ['pointer', ['tagWND']]
0x40 : pGlobalAtomTable ['pointer', ['void']] #atom table for the station
0x44 : luidEndSession ['_LUID']
0x4c : luidUser ['_LUID']
0x54 : psidUser ['pointer', ['void']]
Stations permitted to interact with the user have three desktops
Enumerates window stations and their properties using pool scanning
$ python vol.py -f rdp.mem --profile=Win2003SP2x86 wndscan
**************************************************
WindowStation: 0x8581e40, Name: WinSta0, Next: 0x0
SessionId: 2, AtomTable: 0xe7981648, Interactive: True
Desktops: Default, Disconnect, Winlogon
ptiDrawingClipboard: pid - tid -
spwndClipOpen: 0x0, spwndClipViewer: 6772 rdpclip.exe
cNumClipFormats: 4, iClipSerialNumber: 9
pClipBase: 0xe6fe8ec8, Formats: CF_UNICODETEXT,CF_LOCALE,CF_TEXT,CF_OEMTEXT
[snip/fabricated]
**************************************************
WindowStation: 0x3e7c81f0, Name: WinSta0, Next: 0x85a358d8
SessionId: 0, AtomTable: 0x91101ba8, Interactive: True
Desktops: Default, Disconnect, Winlogon
ptiDrawingClipboard: pid - tid -
spwndClipOpen: 0x0, spwndClipViewer: 0x0
cNumClipFormats: 0, iClipSerialNumber: 0
pClipBase: 0x0, Formats:
First = 9 clipboard uses, all from RDP.
Second = no clipboard
Malware snoops on clipboard operations for obvious reasons
Can hook with SetClipboardData.
HANDLE WINAPI SetClipboardData(
_In_ UINT uFormat,
_In_opt_ HANDLE hMem #handle to memory region where uFormat is copied
);
Obvious though...
Malware can also call GetClipboardData at a fast paced interval to get the contents of the clipboard!
Microsoft suggests creating a clipboard viewer or format listener to receive notations when the clipboard changes.
HWND WINAPI SetClipboardViewer(
_In_ HWND hWndNewViewer #A handle to the window to be added to the clipboard chain.
);
BOOL WINAPI AddClipboardFormatListener(
_In_ HWND hwnd #A handle to the window to be placed in the clipboard format listener list.
);
Both receive WM_DRAWCLIPBOARD messages and can then open the clipboard.
CLIPBRDWNDCLASS will be used by using these APIs and a process will need to have access to these windows
$ python vol.py -f memory.dmp --profile=Win7SP1x86
wintree | grep CLIPBRDWNDCLASS
Volatility Foundation Volatility Framework 2.4
.#10062 explorer.exe:372 CLIPBRDWNDCLASS
.#100f0 explorer.exe:372 CLIPBRDWNDCLASS
.#1011e vmtoolsd.exe:2224 CLIPBRDWNDCLASS
.#1014a SnagIt32.exe:2300 CLIPBRDWNDCLASS
Session-specific paged pool area loaded into kernel space.
Session-private GUI objects are allocated from here.
Container for application windows and user interface objects.
Malware likes to create
tagDESKTOP
>>> dt("tagDESKTOP")
'tagDESKTOP' (132 bytes)
0x0 : dwSessionId ['unsigned long'] #Session id from _MM_SESSION_SPACE
0x4 : pDeskInfo ['pointer', ['tagDESKTOPINFO']] #Information on desktop's global hooks
0x8 : pDispInfo ['pointer', ['tagDISPLAYINFO']]
0xc : rpdeskNext ['pointer', ['tagDESKTOP']] #linked list of desktops (all desktops in the same window station)
0x10 : rpwinstaParent ['pointer', ['tagWINDOWSTATION']] #windows station where desktop belongs
0x14 : dwDTFlags ['unsigned long']
0x18 : dwDesktopId ['unsigned long']
0x1c : spmenuSys ['pointer', ['tagMENU']]
0x20 : spmenuDialogSys ['pointer', ['tagMENU']]
0x24 : spmenuHScroll ['pointer', ['tagMENU']]
0x28 : spmenuVScroll ['pointer', ['tagMENU']]
0x2c : spwndForeground ['pointer', ['tagWND']]
0x30 : spwndTray ['pointer', ['tagWND']]
0x34 : spwndMessage ['pointer', ['tagWND']]
0x38 : spwndTooltip ['pointer', ['tagWND']]
0x3c : hsectionDesktop ['pointer', ['void']]
0x40 : pheapDesktop ['pointer', ['tagWIN32HEAP']] #desktop heap!
0x44 : ulHeapSize ['unsigned long']
0x48 : cciConsole ['_CONSOLE_CARET_INFO']
0x5c : PtiList ['_LIST_ENTRY'] #linked list of tagTHREADINFO strucutres
0x64 : spwndTrack ['pointer', ['tagWND']]
0x68 : htEx ['long']
0x6c : rcMouseHover ['tagRECT']
0x7c : dwMouseHoverTime ['unsigned long']
0x80 : pMagInputTransform ['pointer', ['_MAGNIFICATION_INPUT_TRANSFORM']]
Analyzes desktops and associated threads
Scans for windows stations and walks rpdeskList
[root&windows]#volatility -f Win7.bin --profile=Win7SP0x86 deskscan
Volatility Foundation Volatility Framework 2.4
**************************************************
Desktop: 0x3dd44e68, Name: msswindowstation\mssrestricteddesk, Next: 0x0
SessionId: 0, DesktopInfo: 0xfe600578, fsHooks: 0
spwnd: 0xfe600618, Windows: 29
Heap: 0xfe600000, Size: 0x80000, Base: 0xfe600000, Limit: 0xfe680000
**************************************************
Desktop: 0x3e047630, Name: Service-0x0-3e4$\Default, Next: 0x0
SessionId: 0, DesktopInfo: 0xff700578, fsHooks: 0
spwnd: 0xff700618, Windows: 24
Heap: 0xff700000, Size: 0x80000, Base: 0xff700000, Limit: 0xff780000
3168 (svchost.exe 1204 parent 504)
3156 (svchost.exe 1204 parent 504)
3096 (FXSSVC.exe 3092 parent 504)
2000 (msdtc.exe 1980 parent 504)
1984 (msdtc.exe 1980 parent 504)
1208 (svchost.exe 1204 parent 504)
716 (svchost.exe 700 parent 504)
740 (svchost.exe 700 parent 504)
**************************************************
Desktop: 0x3e090420, Name: Service-0x0-3e5$\Default, Next: 0x0
SessionId: 0, DesktopInfo: 0xff780578, fsHooks: 0
spwnd: 0xff780618, Windows: 27
Heap: 0xff780000, Size: 0x80000, Base: 0xff780000, Limit: 0xff800000
864 (svchost.exe 908 parent 504)
3748 (svchost.exe 3744 parent 504)
3244 (svchost.exe 3232 parent 504)
3248 (svchost.exe 3232 parent 504)
1380 (svchost.exe 908 parent 504)
1828 (svchost.exe 908 parent 504)
1760 (svchost.exe 908 parent 504)
1704 (svchost.exe 908 parent 504)
1724 (svchost.exe 908 parent 504)
1428 (svchost.exe 1340 parent 504)
1436 (svchost.exe 908 parent 504)
1344 (svchost.exe 1340 parent 504)
1012 (svchost.exe 748 parent 504)
1004 (audiodg.exe 1000 parent 748)
912 (svchost.exe 908 parent 504)
800 (svchost.exe 748 parent 504)
752 (svchost.exe 748 parent 504)
**************************************************
Desktop: 0x3e43f4e0, Name: WinSta0\Default, Next: 0x85a3f710
SessionId: 1, DesktopInfo: 0xfea00578, fsHooks: 32768
spwnd: 0xfea00618, Windows: 795
Heap: 0xfea00000, Size: 0xc00000, Base: 0xfea00000, Limit: 0xff600000
3916 (dllhost.exe 884 parent 632)
3888 (dllhost.exe 884 parent 632)
1020 (dllhost.exe 884 parent 632)
3492 (explorer.exe 352 parent 1848)
3208 (explorer.exe 352 parent 1848)
3480 (explorer.exe 352 parent 1848)
3140 (explorer.exe 352 parent 1848)
3500 (explorer.exe 352 parent 1848)
Shows desktops
Winlogon = login prompt for user... if successful, it puts user into Default
Default contains explorer.exe
Desktops can be hidden from the user by using alternative desktops
Requires SwitchDesktop and the name to the proper desktop (Not as easy as Linux)
BOOL WINAPI SwitchDesktop(
_In_ HDESK hDesktop
);
From book on page 427
Bypassed Default desktop boundaries and evaded AV.
Atoms are strings that can be shared between processes in the same session.
Atoms Tables are hash buckets
Atoms allow us to
_RTL_ATOM_TABLE stores information on atoms.
User mode and kernel mode can both have atom tables
>>> dt("_RTL_ATOM_TABLE")
'_RTL_ATOM_TABLE' (112 bytes)
0x0 : Signature ['unsigned long'] #0x6d6f7441 (Atom) Pool tag is AtmT.
0x8 : CriticalSection ['_RTL_CRITICAL_SECTION']
0x18 : NumBuckets ['unsigned long'] #Number of _RTL_ATOM_TABLE_ENTRYs
0x20 : Buckets ['array', <function>, ['pointer', ['_RTL_ATOM_TABLE_ENTRY']]]
>>> dt("_RTL_ATOM_TABLE_ENTRY")
'_RTL_ATOM_TABLE_ENTRY' (24 bytes)
0x0 : HashLink ['pointer64', ['_RTL_ATOM_TABLE_ENTRY']] #Used to enum all atoms in the bucket
0x8 : HandleIndex ['unsigned short']
0xa : Atom ['unsigned short'] #integer for the specific entry. Can be used with AddAtom and FindAtom
0xc : ReferenceCount ['unsigned short'] #Incremented each time a string is added and decremented when one is taken away
0xe : Flags ['unsigned char']
0xf : NameLength ['unsigned char']
0x10 : Name ['String', {'length':<function>, 'encoding': 'utf16'}] #name of the atom
Pool tag scanner for atoms
--sort-by=atom shows atoms from multiple atom tables sorted by ID
--sort-by=refcount shows how many items atoms appear
[root&windows]#volatility -f stuxnet.vmem --profile=WinXPSP3x86 atomscan
Volatility Foundation Volatility Framework 2.4
Offset(P) AtomOfs(V) Atom Refs Pinned Name
---------- ---------- ---------- ------ ------ ----
0xcc05da8 0xe1000d10 0xc010 1 1 OleDraw
0xcc05da8 0xe100e080 0xc0e9 1 0 image/x-wmf
0xcc05da8 0xe1013830 0xc01b 1 1 ScrollBar
0xcc05da8 0xe1014800 0xc028 1 1 SysICS
0xcc05da8 0xe1017360 0xc00f 1 1 Link Source Descriptor
0xcc05da8 0xe101a810 0xc020 1 1 DDEMLMom
0xcc05da8 0xe220dd28 0xc10b 2 0 C:\WINDOWS\system32\NETSHELL.dll
0xcc05da8 0xe2371b50 0xc103 14 0 AC_ItemActivate
0xcc05da8 0xe2387c08 0xc122 2 0 Rich Text Format Without Objects
Lots of them..
RegisterClassEx is used to register a new window class and that name is added to atom table.
Offset(P) AtomOfs(V) Atom Refs Pinned Name
---------- ---------- ---------- ------ ------ ----
0xe17d40a0 0xc0ff 2 0
Mutexes are common with malware, but easy to spot!
Atoms are harder to spot and malware is starting to use them Pg: 434
Tigger used atoms
Can check to see if an atom name exists on the system with GlobalFindAtomA and can create one with GLobalAddAtomA
ATOM WINAPI GlobalAddAtom(
_In_ LPCTSTR lpString
);
ATOM WINAPI GlobalFindAtom(
_In_ LPCTSTR lpString
);
[root&windows]#volatility -f stuxnet.vmem --profile=WinXPSP3x86 atomscan | grep AFX64
Volatility Foundation Volatility Framework 2.4
0xcc05da8 0xe20514d8 0xc118 2 0 AFX64c313
Windows are containers for
They have
Windows are commonly used for disabling AV, debugger attacks, USB insertions..
Can
Detect Anti-monitoring software
Contains metadata
>>> dt("tagWND")
'tagWND' (296 bytes)
0x0 : head ['_THRDESKHEAD']
[snip]
0x30 : ExStyle ['unsigned long'] #Style flags (Droppable files, transparent.. etc)
0x34 : style ['unsigned long'] #More style flags!
[snip]
0x48 : spwndNext ['pointer64', ['tagWND']]
0x50 : spwndPrev ['pointer64', ['tagWND']]
0x58 : spwndParent ['pointer64', ['tagWND']]
0x60 : spwndChild ['pointer64', ['tagWND']]
0x68 : spwndOwner ['pointer64', ['tagWND']]
0x70 : rcWindow ['tagRECT'] #position of the window within desktop
0x80 : rcClient ['tagRECT'] #position of the window within desktop
0x90 : lpfnWndProc ['pointer64', ['void']] #Window procedure function
0x98 : pcls ['pointer64', ['tagCLS']] #pointer to tagCLS for windows class
[snip]
0xd8 : strName ['_LARGE_UNICODE_STRING'] #string name
[snip]
0x118 : spwndClipboardListenerNext ['pointer64', ['tagWND']]
0x120 : ExStyle2 ['unsigned long']
0x120 : bChildNoActivate ['BitField', {'end_bit': 12, 'start_bit': 11, 'native_type': 'long'}]
0x120 : bClipboardListener ['BitField',{'end_bit': 1, 'start_bit': 0, 'native_type': 'long'}]
HWND WINAPI CreateWindowEx(
_In_ DWORD dwExStyle,
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int x,
_In_ int y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam
);
Styles
Enumerate all windows (desktops)
[root&windows]#volatility -f stuxnet.vmem --profile=WinXPSP3x86 windows
Volatility Foundation Volatility Framework 2.4
**************************************************
Window context: 0\Service-0x0-3e7$\Default
Window Handle: #e00e8 at 0xbc940720, Name: AFX64c313
ClassAtom: 0xc118, Class: AFX64c313
SuperClassAtom: 0xc118, SuperClass: AFX64c313
pti: 0xe1e81380, Tid: 1420 at 0x82126bf0
ppi: 0xe163f008, Process: services.exe, Pid: 668
Visible: No
Left: 92, Top: 146, Bottom: 923, Right: 695
Style Flags: WS_MINIMIZEBOX,WS_TABSTOP,WS_DLGFRAME,WS_BORDER,WS_THICKFRAME,WS_CAPTION,WS_SYSMENU,WS_MAXIMIZEBOX,WS_GROUP,WS_OVERLAPPED,WS_CLIPSIBLINGS
ExStyle Flags: WS_EX_LTRREADING,WS_EX_RIGHTSCROLLBAR,WS_EX_WINDOWEDGE,WS_EX_LEFT
Window procedure: 0x13fe695
Shows parent/child relationships between windows in the desktop
[root&windows]#volatility -f stuxnet.vmem --profile=WinXPSP3x86 wintree
Volatility Foundation Volatility Framework 2.4
**************************************************
**************************************************
Window context: 0\WinSta0\Default
#1000c (visible) csrss.exe:600 -
#10004 (visible) csrss.exe:600 -
.SAS window winlogon.exe:624 SAS window class
.Winlogon generic control dialog winlogon.exe:624 -
..#4004c (visible) winlogon.exe:624 6.0.2600.5512!Static
.MCI command handling window winlogon.exe:624 -
#10006 csrss.exe:600 Message
.#10008 csrss.exe:600 -
.#1000a csrss.exe:600 -
.#10026 winlogon.exe:624 WinscardSessionChangeWndClass
#1000e csrss.exe:600 Message
.#10010 csrss.exe:600 -
.#10012 csrss.exe:600 -
Saves a pseudo screenshot based on GDI windows
Takes screenshot of each window from tagWND and draws them with Python Imaging Library.
Requires PIL
[root&windows]#pip install --no-index -f http://dist.plone.org/thirdparty/ -U PIL
[root&windows]#volatility -f Win7.bin --profile=Win7SP0x86 screenshot --dump-dir screenShots/
Volatility Foundation Volatility Framework 2.4
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_1.WinSta0.Default.png
Wrote screenShots/session_1.WinSta0.Disconnect.png
Wrote screenShots/session_1.WinSta0.Winlogon.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
A lot of images will be blank because not all desktops have windows..
WinSta0 is the only interactive desktop per user
Can see screen position, user names, time...
Possibly use to correlate events and build a time line!
There was a POC written to find usb monitoring applications in memory.
Not included with Volatility
Download the quick fix I commented :)
Place in volatility/plugins
[root&windows]#volatility -f stuxnet.vmem --profile=WinXPSP3x86 usbwindows
Volatility Foundation Volatility Framework 2.4
Context Process Window Procedure
------------------------------ -------------------- -------------------- ----------
0\Service-0x0-3e7$\Default services.exe AFX64c313 0x013fe695
0\Service-0x0-3e5$\Default services.exe AFX64c313 0x013fe695
0\SAWinSta\SADesktop services.exe AFX64c313 0x013fe695
0\Service-0x0-3e4$\Default services.exe AFX64c313 0x013fe695
>>> cc(pid = 668)
Current context: services.exe @ 0x82073020, pid=668, ppid=624 DTB=0xa940080
>>> dis(0x013fe695)
0x13fe695 55 PUSH EBP
0x13fe696 8bec MOV EBP, ESP
0x13fe698 817d0c19020000 CMP DWORD [EBP+0xc], 0x219
0x13fe69f 7514 JNZ 0x13fe6b5
0x13fe6a1 ff7514 PUSH DWORD [EBP+0x14]
0x13fe6a4 ff7510 PUSH DWORD [EBP+0x10]
0x13fe6a7 e810000000 CALL 0x13fe6bc
Of course, IDA would make this easier.
Table of Contents | t |
---|---|
Exposé | ESC |
Full screen slides | e |
Presenter View | p |
Source Files | s |
Slide Numbers | n |
Toggle screen blanking | b |
Show/hide slide context | c |
Notes | 2 |
Help | h |