Month of Volatility Plugins
Determining what’s in a computer’s clipboard can be a valuable resource. If you remember from MoVP 1.1 Logon Sessions, Processes, and Images, we traced an RDP user’s actions by dumping his command history and making note of the FTP transaction. You could see the FTP server address, the user’s login name, but not the password. That’s because the attacker copied the password from his remote machine over RDP to the clipboard of the target system. Using both the command history and clipboard plugins, we were able to recover all credentials needed to log into the attacker’s own FTP server if we wanted.
Data Structures
The two critical structures for understanding clipboard objects are tagCLIP (supplied in Windows 7 PDB files) and tagCLIPDATA (not documented). In MoVP 1.2 Window Stations and Clipboard Malware, we learned the tagWINDOWSTATION.pClipBase points to an array of type tagCLIP. The tagCLIP specifies the clipboard format and contains a handle to an associated tagCLIPDATA. The actual address of the tagCLIPDATA object can be derived using the handle value, as described by Okolica and Peterson or you can walk the USER handle table and filter for TYPE_CLIPDATA objects. Our method walks the USER handle table, since the framework and API is already in place for that – based on the userhandles plugin described yesterday.
Here is how the structures appear on Windows 7 x64:
>>> dt(“tagCLIP”)
‘tagCLIP’ (24 bytes)
0x0 : fmt [‘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’]]
0x10 : fGlobalHandle [‘long’]
>>> dt(“tagCLIPDATA”)
‘tagCLIPDATA’ (None bytes)
0x10 : cbData [‘unsigned int’]
0x14 : abData [‘array’, <function <lambda> at 0x1048e5500>, [‘unsigned char’]]
- fmt specifies the clipboard format. The enumeration only includes standard formats, however applications can create their own with RegisterClipboardFormat. Only the formats with “TEXT” in the name can be expected to contain human readable (i.e. non-binary) data.
- hData is a handle value for the associated tagCLIPDATA object. This value can also be 1 for DUMMY_TEXT_HANDLE, 2 for DUMMY_DIB_HANDLE, or it can be 0 for certain deferred operations, as described in How the Clipboard Works. These handles are similar to executive object handles (such as the HANDLE type returned by CreateFile).
- abData is an array of bytes (length cbData) that contains the actual clipboard data. It may be text or binary, depending on the format.
- Enumerate all unique _MM_SESSION_SPACE objects
- Find the tagSHAREDINFO (without PDBs) as described in MoVP 3.3 Analyzing USER Handles and the Win32k Gahti, walk the USER handle table, and collect all TYPE_CLIPDATA objects.
- Scan physical memory for window station objects and enumerate the tagCLIP structures from tagWINDOWSTATION.pClipBase.
- Associate the tagCLIP.hData handle values with their corresponding tagCLIPDATA
- At the end, cycle through any remaining tagCLIPDATA objects found via the USER handle table that were not “claimed” by a tagCLIP. This allows us to still report clipboard data even if the window station object isn’t found or has been subject to DKOM of some sort.
$ python vol.py -f dfrws2008-rodeo-memory.img clipboard
Volatile Systems Volatility Framework 2.1_alpha
Session WindowStation Format Handle Object Data
——– ————- —————- ———- ———- ————
0 WinSta0 CF_UNICODETEXT 0x4900c3 0xe12a7c98 pp -B -p -o out.pl file
0 WinSta0 CF_LOCALE 0x80043 0xe12362d0
0 WinSta0 CF_TEXT 0x1 ———-
0 WinSta0 CF_OEMTEXT 0x1 ———-
As you can see, a user in session 0WinSta0 has placed a Unicode string “pp –B –p –o out.pl file” into the clipboard. The CF_LOCALE data is not shown since its binary, but you can view a hex dump by passing –v/–verbose to the plugin. There is also no data shown for CF_TEXT or CF_OEMTEXT, because the handle value is 1 (DUMMY_TEXT_HANDLE).
$ python vol.py -f image_clip.vmem –profile=Win7SP1x86 clipboard
Volatile Systems Volatility Framework 2.1_alpha
Session WindowStation Format Handle Object
——– ————- —————— ———- ———-
1 WinSta0 0xc009 0x3a2043b 0xfd91a160
1 WinSta0 0xc00b 0x0 ———-
1 WinSta0 0xc004 0x0 ———-
1 WinSta0 0xc003 0x0 ———-
1 WinSta0 0xc00e 0x0 ———-
1 WinSta0 CF_METAFILEPICT 0x0 ———-
1 WinSta0 CF_DIB 0x20d04cf 0xfe1a0000
1 WinSta0 0xc013 0xb202c7 0xfe4d9650
1 WinSta0 CF_ENHMETAFILE 0x3 ———-
1 WinSta0 CF_BITMAP 0xc3050d23 ———-
1 WinSta0 CF_DIBV5 0x2 ———-
In the next example, a user selected a file on the desktop and clicked CTRL+C to copy it to another directory. As you might suspect, the entire file contents isn’t copied to the clipboard in this case. Instead, an object of the CF_HDROP format is created with a full path to the file to be copied:
from all sessions and all window stations. That means if there are multiple
users logged on (one at the console, one via RDP, etc.), then we’ll be able to
extract everyone’s clipboard data.
Conclusion
More information on the clipboard plugin and its usages in forensic investigations will be presented at Open Memory Forensics Workshop (OMFW) 2012.