Windows GUI Artifacts

Presenter Notes

What

Windows GUI

Sessions

Stations

Desktops

Windows

Malware and the GUI

Presenter Notes

Windows GUI

Manages

  • User Input
  • Mouse Movements
  • Draw display
  • Windows, buttons, menus
  • Isolation to support concurrent users

Presenter Notes

GUI landscape

Presenter Notes

Sessions

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.

Session resources

Atom table - Group of strings shared between applications

One or more windows stations

handle table

Presenter Notes

Windows Station

Interactive

Applications requiring input

Each has its own

  • Atom Table
  • Clipboard
  • One or more desktops

Presenter Notes

Desktops

User interface objects

  • Menus
  • Buttons
  • Hooks
  • Heap for allocating object

Windows can be invisible or visible, have screen coordinates and procedures for messaging

Presenter Notes

GUI API

user32.dll

gdi32.dll

Equivalent to ntdl.dll for native APIs

Contain stubs to route through the SSDT[1] into win32k.sys.

Presenter Notes

SSDT

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

Presenter Notes

GUI Artifacts

Debugging information only appears in Windows 7

All other windows versions are undocumented

Makes GUI forensics difficult...

Presenter Notes

Volatility plugins

    | 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  |

Presenter Notes

Sessions

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...

Presenter Notes

Session Structures

_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']]
>>>

Presenter Notes

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

_IMAGE_ENTRY_IN_SESSION

>>> 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}]

Presenter Notes

RDP

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!

Presenter Notes

Detecting RDP

RDPDD.dll and rdppclip.exe are running in a session.

RDPDD is the display driver

rdpclip handles remote clipboard operations

Presenter Notes

Sessions

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

Presenter Notes

Get a user

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)

Presenter Notes

RDP Session

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

Presenter Notes

Exfiltration

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

Presenter Notes

Consoles

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']]

Presenter Notes

Consoles

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'

Presenter Notes

Windows Stations

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 .

  • It is securable (allocated, managed and freed by object manager that handles processes and threads)
  • Has a _POOL_HEADER and _OBJECT_HEADER

win32k!grpWinStaList has the linked list of stations

Only one station can interact with the user at the console (Winsta0)

Presenter Notes

In memory

>>> 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']]

Presenter Notes

Clipboard activity in a session

Stations permitted to interact with the user have three desktops

  • Winlogon, Default (user desktop) and disconnect.

Presenter Notes

Wndscan

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:

Presenter Notes

First = 9 clipboard uses, all from RDP.

Second = no clipboard

Clipboard snooping

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!

  • Requires OpenClipboard to be used and only one session an have it opened at a time... could cause race conditions.

Presenter Notes

Microsoft helped!

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

Presenter Notes

Desktops

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

  • Hidden Desktops
  • Ransomware
  • Hidden threads

Presenter Notes

In memory

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']]

Presenter Notes

Deskscan

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)

Presenter Notes

Deskscan

Shows desktops

Winlogon = login prompt for user... if successful, it puts user into Default

  • Only should contain threads in winlogon.exe

Default contains explorer.exe

Graphical Desktops

Presenter Notes

Alternate Desktops

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
);

Presenter Notes

Tigger created alternative desktops

From book on page 427

  1. Create a new desktop named system_temp_.
  2. Generate a temporary filename that will capture the redirected output of console commands.
  3. Set STARTUPINFO.lpDesktop to WinSta0\system_temp_.
  4. Set dwFlags to indicate that the STARTUPINFO structure also has preferences for window visibility, standard output, and standard error handles for the process to be created.
  5. Create the new process. The full path to the process szCmd is passed into the function as an argument (originally taken from an attacker over the network).
  6. Wait for the process to complete.
  7. Close the system_temp_ desktop.
  8. Read the process’ output (if any) from the specified output file and return it in a buffer.

Bypassed Default desktop boundaries and evaded AV.

Presenter Notes

Atoms

Atoms are strings that can be shared between processes in the same session.

Atoms Tables are hash buckets

Atoms allow us to

  • Detect windows class names
  • Detect windows message names
  • Identify injected DLLs
  • System presence marking

Presenter Notes

Atom Tables

_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

Presenter Notes

Atomscan

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

Presenter Notes

Atoms

Lots of them..

RegisterClassEx is used to register a new window class and that name is added to atom table.

  • win32k.sys creates an atom from the ClassName member in the parameters
  • Some malware will try to be sneaky and not name their windows


Offset(P) AtomOfs(V)       Atom Refs   Pinned Name
---------- ---------- ---------- ------ ------ ----
0xe17d40a0 0xc0ff               2           0

Presenter Notes

Atoms

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
);

Presenter Notes

StuxNet used Atoms

[root&windows]#volatility -f stuxnet.vmem --profile=WinXPSP3x86 atomscan | grep AFX64
Volatility Foundation Volatility Framework 2.4
 0xcc05da8 0xe20514d8     0xc118      2      0 AFX64c313

Presenter Notes

Windows

Windows are containers for

  • Buttons
  • Scroll Bars
  • Text/edit areas

They have

  • Titles
  • Coordinates
  • Visibility properties (max, min, transparent, overlapped)

Windows are commonly used for disabling AV, debugger attacks, USB insertions..

Presenter Notes

Windows

Can

  • Cross reference window names with owning process
  • Explorer.exe always has a window called SysFader!

Detect Anti-monitoring software

  • AV uses windows names...
  • FindWindow easily finds processes with registered names

Contains metadata

  • System Time
  • Logged-on users
  • Viewed web pages
  • screen positions
  • cmd.exe commands..

Presenter Notes

Memory

>>> 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'}]

Presenter Notes

Creating Windows

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

  • Drag-drop files
  • Top-level window
  • border with sunken edge
  • Help men
  • scroll bar position
  • . . . MSDN

Presenter Notes

Windows

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

Presenter Notes

Wintree

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 -

Presenter Notes

Screenshot

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

Presenter Notes

Presenter Notes

Screenshot

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!

Presenter Notes

Usb Monitoring

There was a POC written to find usb monitoring applications in memory.

Not included with Volatility

Source Here

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

Presenter Notes

Disassembling procedures may be a good idea



>>> 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.

Presenter Notes

EOF

Presenter Notes