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']]
Key Points
- 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.
The Clipboard Plugin
At DFRWS 2011, Okolica and Peterson were first to present a technique for extracting clipboard contents from memory using a proprietary cool called CMAT (see link above). They discussed methods to find the data from user- and kernel-mode by using PDB files from Microsoft’s symbol server to resolve user32!gphn and win32k!gSharedInfo, respectively. The way Volatility’s plugin works is similar, but quite different at the same time. Here is a brief description of the steps:
- 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.
One of the publicly accessible memory images known to have data in the clipboard at the time of the acquisition is dfrws2008-rodeo-memory.img. Below you can see the output of the plugin on this image:
$ 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 0\WinSta0 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 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 0\WinSta0 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).
In the following example, Microsoft Word and Microsoft Paint were opened. A small sketch was created in Paint, copied to the clipboard, and then pasted into Word. You can see the various private OLE formats created as a result of these actions. Additionally, there are new CF_METAFILEPICT, CF_ENHMETAFILE, CF_BITMAP, and CF_DIBV5 formats to support the binary images in the clipboard. Data is not shown since it’s all binary anyway, but with a some work, the images could potentially be carved from memory and saved for viewing on an analysis system. Please note - you could carve images with foremost or scalpel, but the point here would be to identify specific images as the ones in the clipboard.
$ 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:
$ 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:
$ python vol.py -f xpsp3.vmem clipboard -v
Volatile Systems Volatility Framework 2.1_rc3
[snip]
0 WinSta0 CF_HDROP 0x10230131 0xe1fa6590
0xe1fa659c 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0xe1fa65ac 01 00 00 00 43 00 3a 00 5c 00 44 00 6f 00 63 00 ....C.:.\.D.o.c.
0xe1fa65bc 75 00 6d 00 65 00 6e 00 74 00 73 00 20 00 61 00 u.m.e.n.t.s...a.
0xe1fa65cc 6e 00 64 00 20 00 53 00 65 00 74 00 74 00 69 00 n.d...S.e.t.t.i.
0xe1fa65dc 6e 00 67 00 73 00 5c 00 41 00 64 00 6d 00 69 00 n.g.s.\.A.d.m.i.
0xe1fa65ec 6e 00 69 00 73 00 74 00 72 00 61 00 74 00 6f 00 n.i.s.t.r.a.t.o.
0xe1fa65fc 72 00 5c 00 44 00 65 00 73 00 6b 00 74 00 6f 00 r.\.D.e.s.k.t.o.
0xe1fa660c 70 00 5c 00 6e 00 6f 00 74 00 65 00 2e 00 74 00 p.\.n.o.t.e...t.
0xe1fa661c 78 00 74 00 00 00 00 00 x.t.....
Lastly, keep in mind that we’re recovering clipboard data
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.
The Windows clipboard is just another piece in the GUI subsystem that Volatility is now intimately familiar with. It can yield critical evidence in forensic investigations and is often exploited by malware and leveraged by remote attackers. In the past, we've seen some good technical documentation of extracting clipboard data from memory, but it relied on PDB symbols and more importantly - it was implemented in a closed-source proprietary tool. At Volatility Labs, we know everyone enjoys using the clipboard - now you can analyze it too!
More information on the clipboard plugin and its usages in forensic investigations will be presented at Open Memory Forensics Workshop (OMFW) 2012.
More information on the clipboard plugin and its usages in forensic investigations will be presented at Open Memory Forensics Workshop (OMFW) 2012.
No comments:
Post a Comment