| 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 |
| Plugin | Description |
|--------------|----------------------------------------------------|
| messagehooks | Lists desktop and thread window message hooks |
| eventhooks | Prints details on windows event hooks |
| gahti | Dumps the USER handle type information |
| userhandles | Dumps the USER handle table objects |
| gditimers | Examines the use of GDI timers |
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.
Container for processes, objects, stations and desktops.
tagWINDOWSTATION
Only one station can interact with the user at the console (Winsta0)
Applications requiring input
Each has its own
User interface objects
Malware likes to create
Atoms are strings that can be shared between processes in the same session.
Atoms Tables are hash buckets
Atoms allow us to
Applications hook the GUI to
Malware
Interactive
Applications requiring input
Each has its own
Windows can be invisible or visible, have screen coordinates and procedures for messaging
WM_KEYDOWN = event to target window's queue.
Owning window wakes up and processes message
Message hooks can be intercepted before they reach the target window
Receive notifications on WM_KEYDOWN
HHOOK WINAPI SetWindowsHookEx(
_In_ int idHook, #WH_* (WM_KEYDOWN, WH_MOUSE_
_In_ HOOKPROC lpfn, #address of the hook procedure. Can pass down chain with CallNextHookEx.
_In_ HINSTANCE hMod, #DLL that contains hook procedure
_In_ DWORD dwThreadId #thread for the hook (specific or 0 for all threads in desktop)
);
Hooks registered with dwTheadId of 0 are global hooks
>>> dt("tagHOOK")
'tagHOOK' (96 bytes)
0x0 : head ['_THRDESKHEAD']
0x28 : phkNext ['pointer64', ['tagHOOK']]
0x30 : iHook ['long']
0x38 : offPfn ['unsigned long long']
0x40 : flags ['Flags', {'bitmap': {'HF_INCHECKWHF': 8,'HF_HOOKFAULTED': 4, 'HF_WX86KNOWNDLL': 6, 'HF_HUNG': 3, 'HF_FREED': 9,'HF_ANSI', 1, HF_GLOBAL': 0, 'HF_DESTROYED': 7}}]
0x44 : ihmod ['long']
0x48 : ptiHooked ['pointer64', ['tagTHREADINFO']]
0x50 : rpdesk ['pointer64', ['tagDESKTOP']]
0x58 : fLastHookHung ['BitField', {'end_bit': 8,'start_bit': 7, 'native_type': 'long'}]
0x58 : nTimeout ['BitField', {'end_bit': 7,'start_bit': 0, 'native_type': 'unsigned long'}]
HEAD = common header for USER objects
phkNext = next hook in the chain (CallNextHookEx)
offPfn = RVA of hook. Local = -1... global = index into atoms array
ptiHooked = hooked thread
rpdesk = desktop for hook
Enumerate global hooks (threadId 0 in SetWindowsHookEx) by finding all desktops
tagDESKTOP.pDeskInfo.aphkStart
tagDESKTOP.pDeskInfo.fsHooks
WM_GETMESSAGE is hooked below with SetWindowsHookEx
lpfnWndProc passes control with CallNextHookEx
dwThreadId is 0 (global/HF_GLOBAL)
python vol.py -f laqma.vmem --profile=WinXPSP3x86 messagehooks --output=block
Volatility Foundation Volatility Framework 2.4
Offset(V) : 0xbc693988
Session : 0
Desktop : WinSta0\Default
Thread : <any>
Filter : WH_GETMESSAGE
Flags : HF_ANSI, HF_GLOBAL
Procedure : 0x1fd9
ihmod : 1
Module : C:\WINDOWS\system32\Dll.dll
Offset(V) : 0xbc693988
Session : 0
Desktop : WinSta0\Default
Thread : 1584 (explorer.exe 1624)
Filter : WH_GETMESSAGE
Flags : HF_ANSI, HF_GLOBAL
Procedure : 0x1fd9
ihmod : 1
Module : C:\WINDOWS\system32\Dll.dll
Offset(V) : 0xbc693988
Session : 0
Desktop : WinSta0\Default
Thread : 252 (VMwareUser.exe 1768)
Filter : WH_GETMESSAGE
Flags : HF_ANSI, HF_GLOBAL
Procedure : 0x1fd9
ihmod : 1
Module : C:\WINDOWS\system32\Dll.dll
Thread
Remember Desktop naming conventions
Thread : <any>
[snip]
Desktop : WinSta0\Default
Disassemble Procedure RVA from module base address (use dlllist)
Procedure : 0x1fd9
Module : C:\WINDOWS\system32\Dll.dll #dllList shows offset of 0x00ac0000
>>> dis(0x00ac0000 + 0x00001fd9) #DLL Base + Procedure offset
0xac1fd9 ff74240c PUSH DWORD [ESP+0xc]
0xac1fdd ff74240c PUSH DWORD [ESP+0xc]
0xac1fe1 ff74240c PUSH DWORD [ESP+0xc]
0xac1fe5 ff350060ac00 PUSH DWORD [0xac6000]
0xac1feb ff157c40ac00 CALL DWORD [0xac407c] ; CallNextHookEx
With DLL injection and message hooks, the full path on disk of DLL is in atom table.
atom or atomscan would reveal an injected DLL in atom table for message hooking
python vol.py –f laqma.vmem --profile=WinXPSP3x86 atoms
0xe1f8bc30 0xc1c3 1 0 C:\WINDOWS\system32\psbase.dll
0xe28ed818 0xc1c7 1 0 BCGP_TEXT
0xe2950c98 0xc19f 1 0 ControlOfs01420000000000FC
0xe11d6290 0xc1a0 1 0 C:\WINDOWS\system32\Dll.dll
table of object references
CreateWindow -> HWND (tagWND) to GUI subsystem
20+ user objects in Windows
Can hide with DKOM...
One USER handle table per session and all processes share it.
Array of tagHANDLETYPEINFO structures
Similar to nt!_OBJECT_TYPE from executive layer
Contains
>>> dt("tagHANDLETYPEINFO")
'tagHANDLETYPEINFO' (16 bytes)
0x0 : fnDestroy ['pointer', ['void']] # deallocation/cleanup function for the object type
0x8 : dwAllocTag ['String', {'length': 4}] #32-bit pool tag
0xc : bObjectCreateFlags ['Flags', {'target': 'unsigned char', 'bitmap': {'OCF_VARIABLESIZE': 7, 'OCF_DESKTOPHEAP': 4, 'OCF_THREADOWNED': 0, 'OCF_SHAREDHEAP': 6, 'OCF_USEPOOLIFNODESKTOP': 5, 'OCF_USEPOOLQUOTA': 3, 'OCF_MARKPROCESS': 2, 'OCF_PROCESSOWNED': 1}}]
First struct is TYPE_FREE with a tag of Uswd
GDI Timers (TYPE_TIMER) are process owned
TYPE_CLIPDATA (not owned by processes or threads)
TYPE_FREE is used as "deletion" flag
TYPE_WINDOW
[root&windows]#volatility -f Win7.bin --profile=Win7SP0x86 gahti
Volatility Foundation Volatility Framework 2.4
Session Type Tag fnDestroy Flags
-------- -------------------- -------- ---------- -----
0 TYPE_FREE 0x00000000
0 TYPE_WINDOW Uswd 0x913b7a66 OCF_DESKTOPHEAP, OCF_THREADOWNED, OCF_USEPOOLIFNODESKTOP, OCF_USEPOOLQUOTA
0 TYPE_MENU 0x913c2bdf OCF_DESKTOPHEAP, OCF_PROCESSOWNED
0 TYPE_CURSOR Uscu 0x913aaee9 OCF_MARKPROCESS, OCF_PROCESSOWNED, OCF_USEPOOLQUOTA
0 TYPE_SETWINDOWPOS Ussw 0x913bb801 OCF_THREADOWNED, OCF_USEPOOLQUOTA
0 TYPE_HOOK 0x913aae91 OCF_DESKTOPHEAP, OCF_THREADOWNED
0 TYPE_CLIPDATA Uscb 0x91496dc0
0 TYPE_CALLPROC 0x9137b3f3 OCF_DESKTOPHEAP, OCF_PROCESSOWNED
0 TYPE_ACCELTABLE Usac 0x9137b3f3 OCF_PROCESSOWNED, OCF_USEPOOLQUOTA
0 TYPE_DDEACCESS Usd9 0x91496dc0 OCF_THREADOWNED, OCF_USEPOOLQUOTA
0 TYPE_DDECONV UsdA 0x91433eac OCF_THREADOWNED, OCF_USEPOOLQUOTA
0 TYPE_DDEXACT UsdB 0x91433b75 OCF_THREADOWNED, OCF_USEPOOLQUOTA
0 TYPE_MONITOR Usdi 0x91412c5c OCF_SHAREDHEAP
0 TYPE_KBDLAYOUT Uskb 0x914140d6
0 TYPE_KBDFILE Uskf 0x91414177
0 TYPE_WINEVENTHOOK Uswe 0x913db7f9 OCF_THREADOWNED
0 TYPE_TIMER Ustm 0x913ede8c OCF_PROCESSOWNED
dwAllocTag can be used to locate USER objects
win32k!_gSharedInfo symbol points to a tagSHAREDINFO
tagSHAREDINFO
_gSharedInfo
Volatility discovered symbol in win32k.sys
>>> dt("tagSHAREDINFO")
'tagSHAREDINFO' (568 bytes)
0x0 : psi ['pointer64', ['tagSERVERINFO']] #tagSERVERINFO
0x8 : aheList ['pointer64', ['_HANDLEENTRY']] #array of _HANDLEENTRY (one for each in the table) (tagSHAREDINFO.psi.cHandleEntries)
0x10 : HeEntrySize ['unsigned long'] #size of HANDLEENTRY
0x18 : pDispInfo ['pointer64', ['tagDISPLAYINFO']]
0x20 : ulSharedDelta ['unsigned long long'] #delta to USER objects
0x28 : awmControl ['array', 31, ['_WNDMSG']]
0x218 : DefWindowMsgs ['_WNDMSG']
0x228 : DefWindowSpecMsgs ['_WNDMSG']
def Win32KBase(self):
for mod in modules.lsmod(self.obj_vm):
if str(mod.BaseDllName or '').lower() == "win32k.sys":
return mod.DllBase
def _section_chunks(self, sec_name):
dos_header = obj.Object("_IMAGE_DOS_HEADER", \
offset = self.Win32KBase, vm = self.obj_vm)
if dos_header:
try:
nt_header = dos_header.get_nt_header()
sections = [
sec for sec in nt_header.get_sections()
if str(sec.Name) == sec_name
]
Source code on GitHub
>>> dt("_HANDLEENTRY")
'_HANDLEENTRY' (24 bytes)
0x0 : phead ['pointer64', ['_HEAD']]
0x8 : pOwner ['pointer64', ['void']]
0x10 : bType ['Enumeration', {'target':
'unsigned char', 'choices': {0: 'TYPE_FREE', 1: 'TYPE_WINDOW',
2: 'TYPE_MENU', 3: 'TYPE_CURSOR', 4: 'TYPE_SETWINDOWPOS', 5: [snip]
0x11 : bFlags ['unsigned char']
0x12 : wUniq ['unsigned short']
_HANDLEENTRY.phead is common USER object herader
bType = type of object
THRDESKHEAD, = thread
PROCDESKHEAD = Proc
>>> dt("_HEAD")
'_HEAD' (16 bytes)
0x0 : h ['pointer64', ['void']]
0x8 : cLockObj ['unsigned long']
>>> dt("_THRDESKHEAD")
'_THRDESKHEAD' (40 bytes)
0x0 : h ['pointer64', ['void']]
0x8 : cLockObj ['unsigned long']
0x10 : pti ['pointer64', ['tagTHREADINFO']]
0x18 : rpdesk ['pointer64', ['tagDESKTOP']]
0x20 : pSelf ['pointer64', ['unsigned char']]
>>> dt("_PROCDESKHEAD")
'_PROCDESKHEAD' (40 bytes)
0x0 : h ['pointer64', ['void']]
0x8 : cLockObj ['unsigned long']
0x10 : hTaskWow ['unsigned long']
0x18 : rpdesk ['pointer64', ['tagDESKTOP']]
0x20 : pSelf ['pointer64', ['unsigned char']]
Dumps the USER handle table objects
Locates shared information for each session and prints of contents of handle table
Can filter by PID and type
[root&windows]#volatility -f Win7.bin --profile=Win7SP0x86 userhandles
Volatility Foundation Volatility Framework 2.4
**************************************************
SharedInfo: 0x91552440, SessionId: 0 Shared delta: 0
aheList: 0xff910000, Table size: 0x1000, Entry size: 0xc
Object(V) Handle bType Flags Thread Process
---------- ---------- -------------------- -------- -------- -------
0xff9d1d28 0x10001 TYPE_MONITOR 0 -------- -
0xffbbd148 0x10002 TYPE_WINDOW 64 444 348
0xffb7b908 0x10003 TYPE_CURSOR 0 -------- 348
0xff650618 0x10004 TYPE_WINDOW 0 444 348
0xffb7aa88 0x10005 TYPE_CURSOR 0 -------- 348
0xff6507c8 0x10006 TYPE_WINDOW 0 444 348
0xffb7a9c8 0x10007 TYPE_CURSOR 0 -------- 348
0xff650900 0x10008 TYPE_WINDOW 0 444 348
0xffb7a908 0x10009 TYPE_CURSOR 0 -------- 348
0xff670618 0x1000a TYPE_WINDOW 0 444 348
0xffb79a88 0x1000b TYPE_CURSOR 0 -------- 348
0xff670748 0x1000c TYPE_WINDOW 0 444 348
0xffb799c8 0x1000d TYPE_CURSOR 0 -------- 348
0xff670880 0x1000e TYPE_WINDOW 0 444 348
0xffb79908 0x1000f TYPE_CURSOR 0 -------- 348
0xfea00618 0x10010 TYPE_WINDOW 0 444 348
0xffb78828 0x10011 TYPE_CURSOR 0 -------- 348
Thread owned = _TREDDESKHEAD.pti -> tagTHREADINFO -> tagTHREADINFO.pTHread -> _ETHREAD -> _KTHREAD -> _KPROCESS
Like hooking the GUI, GUI Events can also be hooked.
Those annoying windows sounds? Events
Smaller icons / icons appear for actions on the taskbar
Uses a loaded DLL to hook events
All undocumented structs...
tagEVENTHOOK in memory.
>>> dt("tagEVENTHOOK")
'tagEVENTHOOK' (48 bytes)
0xc : phkNext ['pointer', ['tagEVENTHOOK']] #linked list of hooks
0x10 : eventMin ['Enumeration', {'target': }] #lowest system event
0x14 : eventMax ['Enumeration', {'target': }] #highest sysem event
0x18 : dwFlags ['unsigned long'] #if DLL is in address space and if thread that installed the hook is exempt from the hook
0x1c : idProcess ['unsigned long'] #PID (0 if global)
0x20 : idThread ['unsigned long'] #TID (0 if global)
0x24 : offPfn ['unsigned long'] #RVA to procedure
0x28 : ihmod ['long'] #win32k!_aatomSysLoaded (full DLL path)
Events?
['Enumeration', {'target': 'unsigned long', 'choices': {19968:
'EVENT_UIA_EVENTID_START', 1: 'EVENT_MIN',
2: 'EVENT_SYSTEM_ALERT',
3: 'EVENT_SYSTEM_FOREGROUND',
4: 'EVENT_SYSTEM_MENUSTART',
5: 'EVENT_SYSTEM_MENUEND',
6: 'EVENT_SYSTEM_MENUPOPUPSTART',
7: 'EVENT_SYSTEM_MENUPOPUPEND',
8: 'EVENT_SYSTEM_CAPTURESTART',
[snip]
HWINEVENTHOOK WINAPI SetWinEventHook(
_In_ UINT eventMin,
_In_ UINT eventMax,
_In_ HMODULE hmodWinEventProc,
_In_ WINEVENTPROC lpfnWinEventProc,
_In_ DWORD idProcess,
_In_ DWORD idThread,
_In_ UINT dwflags
);
To hook all events give EVENT_MIN and EVENT_MAX as the eventMin and eventMax params.
Prints details on windows event hooks
Shows
PID and TID
Event range
offset
ihmod (-1 is within process)
Session
[root&windows]#volatility -f Win7.bin --profile=Win7SP0x86 eventhooks
Volatility Foundation Volatility Framework 2.4
Handle: 0x20071, Object: 0xfe9e3898, Session: 1
Type: TYPE_WINEVENTHOOK, Flags: 0, Thread: 1400, Process: 352
eventMin: 0x4 EVENT_SYSTEM_MENUSTART
eventMax: 0x7 EVENT_SYSTEM_MENUPOPUPEND
Flags: , offPfn: 0x9c6264, idProcess: 0, idThread: 0
ihmod: -1
Handle: 0x20567, Object: 0xffa6f4d8, Session: 1
Type: TYPE_WINEVENTHOOK, Flags: 0, Thread: 3680, Process: 3676
eventMin: 0x8001 EVENT_OBJECT_DESTROY
eventMax: 0x8001 EVENT_OBJECT_DESTROY
Flags: WINEVENT_INCONTEXT, offPfn: 0x3309, idProcess: 3676, idThread: 0
ihmod: 1
Data stored in RAM and can be extracted
File artifacts from Windows Explorer
Clipboard really lives in user32.dll
Allows data to be shared between applications
tagCLIP and tagCLIPDATA
tagWINDOWSTATION.pClipBase -> array of tagCLIP -> tagClip points to tagCLIPDATA
Walk handle table and look for TYPE_CLIPDATA
>>> dt("tagCLIP")
'tagCLIP' (24 bytes)
0x0 : fmt #clipboard format.
['Enumeration', {'target': 'unsigned
long', 'choices': {128: 'CF_OWNERDISPLAY', 1: 'CF_TEXT', 2: 'CF_BITMAP', 3:
'CF_METAFILEPICT', 4: 'CF_SYLK', 5: 'CF_DIF', 6: 'CF_TIFF', 7: 'CF_OEMTEXT', 8:
'CF_DIB', 9: 'CF_PALETTE', 10: 'CF_PENDATA', 11: 'CF_RIFF', 12: 'CF_WAVE', 13:
'CF_UNICODETEXT', 14: 'CF_ENHMETAFILE', 15: 'CF_HDROP', 16: 'CF_LOCALE', 17: 'CF_
DIBV5', 131: 'CF_DSPMETAFILEPICT', 129: 'CF_DSPTEXT', 130: 'CF_DSPBITMAP', 142:
'CF_DSPENHMETAFILE'}}]
0x8 : hData ['pointer64', ['void']] #handle to tagCLIPDATA
0x10 : fGlobalHandle ['long']
>>> dt("tagCLIPDATA")
'tagCLIPDATA' (None bytes)
0x10 : cbData ['unsigned int']
0x14 : abData ['array', <function <lambda> at 0x1048e5500>, ['unsigned char']]
#actual clipboard data!
James Okolica and Gilbert L. Peterson - Compiled Memory Analysis Tool (CMAT)
user32!gphn and win32k!gSharedInfo
Extract the contents of the windows clipboard
[root&windows]#volatility -f Win7.bin --profile=Win7SP0x86 clipboard
Volatility Foundation Volatility Framework 2.4
Session WindowStation Format Handle Object Data
---------- ------------- ------------------ ---------- ---------- --------------------------------------------------
1 WinSta0 0xc009L 0x70327 0xfdf27168
1 WinSta0 CF_TEXT 0xd ----------
1 WinSta0 0x2000L 0x0 ----------
1 WinSta0 CF_TEXT 0x2000 ----------
1 WinSta0 0x1032bL 0x0 ----------
1 WinSta0 CF_TEXT 0x1 ----------
1 ------------- ------------------ 0x10329 0xfce63b70
1 ------------- ------------------ 0x1032b 0xffac40c8
-v for verbose
Like _KTIMER
User-mode GUI threads
Callback function when runs timer expires
[root&windows]#volatility -f Win7.bin --profile=Win7SP0x86 gditimers
Volatility Foundation Volatility Framework 2.4
Sess Handle Object Thread Process nID Rate(ms) Countdown(ms) Func
------ ---------- ---------- -------- -------------------- ---------- ---------- ------------- ----------
0 0x10083 0xffaafb70 436 csrss.exe:348 0x7ffe 35000 54203 0x913a636b
0 0x10088 0xfe9c24f8 3796 svchost.exe:948 0x0 300000 265516 0x75c219a5
0 0x100f1 0xffa1bd10 1836 dllhost.exe:1804 0x0 300000 218047 0x75c219a5
0 0x10101 0xfe9e4bc8 1924 dllhost.exe:1868 0x0 300000 218094 0x75c219a5
0 0x10117 0xfe9d0270 364 dllhost.exe:1804 0x7ffd 300000 218875 0x7068e453
0 0x1011b 0xfe9cd1e8 344 dllhost.exe:1804 0x7ffc 300000 218875 0x7068e453
0 0x1011f 0xfe9ca928 340 dllhost.exe:1804 0x7ffb 300000 218875 0x7068e453
0 0x10123 0xfe9cc288 416 dllhost.exe:1804 0x7ffa 300000 218891 0x7068e453
0 0x10127 0xfe9cc238 396 dllhost.exe:1804 0x7ff9 300000 218906 0x7068e453
0 0x1012b 0xffa17a18 392 dllhost.exe:1804 0x7ff8 300000 218937 0x7068e453
0 0x1012f 0xffa179c8 296 dllhost.exe:1804 0x7ff7 300000 218937 0x7068e453
0 0x10133 0xffa15ea0 492 dllhost.exe:1804 0x7ff6 300000 218937 0x7068e453
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 |