Tuesday, January 21, 2014

Malware Superlatives: Most Likely to Cry s/Wolf/Crocodile/

As a young boy once learned, its bad to cry wolf. Its not necessarily bad to cry crocodile, but the authors of Blazgel decided to do it anyway. Blazgel is a kernel rootkit that hooks various SSDT entries and has some backdoor capabilities. When I first saw it hooking NtWriteVirtualMemory, it piqued my interest, because this is the native API called by WriteProcessMemory - a function commonly used for code injection. Presumably, by hooking this function, the rootkit could also prevent antivirus from disinfecting some of its components from memory. As I went to explore the real reason this malware hooked NtWriteVirtualMemory, I was a little surprised to see this:
Blazgel's NtWriteVirtualMemory API Hook Cries Crocodile
You may need to click the image to view a larger disassembly, but essentially what you're seeing is code like the following:

NTSTATUS Hook_NtWriteVirtualMemory(ProcessHandle,

    if (True_NtWriteVirtualMemory != NULL) 
        return True_NtWriteVirtualMemory(ProcessHandle, 

The function  named Hook_NtWriteVirtualMemory is the malicious handler that executes when NtWriteVirtualMemory is called. True_NtWriteVirtualMemory is the saved pointer to the real API function. Upon hooking the function, the malware saves the real API so that it can still be referenced when needed. Strangely, this rootkit must have been deployed while still under development, because all the hook does is print crocodile to the kernel debug message facility and then pass the call through to the valid API function.

This post is an excerpt from Malware Superlatives, a sequel to the Making Fun of Your Malware presentation.

- Michael Ligh (@iMHLv2)

Thursday, January 16, 2014

Comparing the Dexter and BlackPOS (Target) RAM Scraping Techniques

Up until yesterday when Brian Krebs wrote A First Look at the Target Intrusion, Malware, there weren't many details about the involved code. Now that its out there, I thought it might be interesting to see how the "RAM scraping" feature worked in comparison to the Dexter malware. As it turns out, the two are quite similar, and neither are really exciting. This just goes to show that you don't need advanced (fine tuned, maybe) tools to be successful at cyber crime.

The BlackPOS malware (see Krebs' article) A.K.A Trojan.POSRAM uses EnumProcesses to get the list of active PIDs on the system. It then cycles through the list, skipping its own PID (Dexter also skipped its parent PID). For all other processes, it calls GetModuleFileNameEx to get the full path to the executable, then strips off the file name (i.e. explorer.exe) portion, converts it to lowercase, and compares it against "pos.exe" with strcmp. Had Target known that this specific sample only looks in the memory of processes named pos.exe, it could have renamed its Point-of-Sale application and avoided the news (for a few minutes anyway... other samples are known to exist that looked for other process names).

The "pos.exe" string isn't exactly in plain text, but the malware isn't packed either. It uses a very simple obfuscation technique where the string is split and the characters are shifted around a bit. You can see it in the read-only section of the PE file:

Once it finds a pos.exe process, it opens a handle with OpenProcess and uses VirtualQueryEx to begin iterating through the process's available memory blocks. This is exactly what Dexter did -- the only difference being that Dexter also checked memory protection constants and skipped ranges that were marked PAGE_NOACCESS or PAGE_GUARD. As a result, the BlackPOS malware could easily lead to an access violation (e.g. STATUS_PAGE_GUARD_VIOLATION) capable of crashing the malware. I can only imagine the look on the attackers' faces once they realized that they came up with 0 credit cards because they didn't check page permissions before reading a memory address. Unfortunately for Target, the pos.exe processes must not have had any no-access or guard pages set.

Here's a snippet of code reverse engineered from the malware that shows how it determines which ranges to scan:

VOID ScanMemory(HANDLE hProcess)
    int lpAddress = 0;
    int lpMaxAddress = 0x6FFFFFFF;
    int endAddress = 0;
    SIZE_T cbReturned;

    do { 
        cbReturned = VirtualQueryEx(hProcess, 

        if (cbReturned && anMBI.RegionSize)
            endAddress = (int)((char *)anMBI.BaseAddress + anMBI.RegionSize);
        lpAddress = (int)(char *)lpAddress + anMBI.RegionSize;
    } while (lpAddress < lpMaxAddress);

Notice the malware stops at 0x6FFFFFFF, to avoid scanning inside system DLLs which normally exist in high regions of process memory space. The ScanRange function (not shown) breaks the ranges identified by VirtualQueryEx into (roughly) 10 MB chunks and uses ReadProcessMemory to read the data into a buffer, which it then checks for patterns and substrings related to the credit card information that it wants to steal. Dexter did something similar, but read data in roughly 400 KB chunks instead.

In conclusion, Dexter and Trojan.POSRAM are really quite similar in terms of how they scan memory for the sensitive data.

-Michael Ligh (@iMHLv2)

Tuesday, January 14, 2014

TrueCrypt Master Key Extraction And Volume Identification

One of the disclosed pitfalls of TrueCrypt disk encryption is that the master keys must remain in RAM in order to provide fully transparent encryption. In other words, if master keys were allowed to be flushed to disk, the design would suffer in terms of security (writing plain-text keys to more permanent storage) and performance. This is a risk that suspects have to live with, and one that law enforcement and government investigators can capitalize on.

The default encryption scheme is AES in XTS mode. In XTS mode, primary and secondary 256-bit keys are concatenated together to form one 512-bit (64 bytes) master key. An advantage you gain right off the bat is that patterns in AES keys can be distinguished from other seemingly random blocks of data. This is how tools like aeskeyfind and bulk_extractor locate the keys in memory dumps, packet captures, etc. In most cases, extracting the keys from RAM is as easy as this:

$ ./aeskeyfind Win8SP0x86.raw
Keyfind progress: 100%

Several keys were identified, but only the two final ones in red are 256-bits (the others are 128-bit keys). Thus, you can bet by combining the two 256-bit keys, you'll have your 512-bit master AES key. That's all pretty straightforward and has been documented in quite a few places - one of my favorites being Michael Weissbacher's blog

The problem is - what if suspects change the default AES encryption scheme? TrueCrypt also supports Twofish, Serpent, and combinations thereof (AES-Twofish, AES-Twofish-Serpent). Furthermore, it supports modes other than XTS, such as LWR, CBC, outer CBC, and Inner CBC (though many of the CBCs are either deprecated or not recommended).

What do you do if a suspect uses non-default encryption schemes or modes? You can't find Twofish or Serpent keys with tools designed to scan for AES keys -- that just doesn't work. As pointed out by one of our Twitter followers (@brnocrist), a tool by Carsten Maartmann-Moe named Interrogate could be of use here (as could several commercial implementations from Elcomsoft or Passware). 

Another challenge that investigators face, in the case of file-based containers, is figuring out which file on the suspect's hard disk serves as the container. If you don't know that, then having the master keys is only as useful as finding the key to a house but having no idea where the house is. 

To address these issues, I wrote several new Volatility plugins. The truecryptsummary plugin gives you a detailed description of all TrueCrypt related artifacts in a given memory dump. Here's how it appears on a test system running 64-bit Windows 2012

$ python vol.py -f WIN-QBTA4959AO9.raw --profile=Win2012SP0x64 truecryptsummary
Volatility Foundation Volatility Framework 2.3.1 (T)

Process              TrueCrypt.exe at 0xfffffa801af43980 pid 2096
Kernel Module        truecrypt.sys at 0xfffff88009200000 - 0xfffff88009241000
Symbolic Link        Volume{52b24c47-eb79-11e2-93eb-000c29e29398} -> \Device\TrueCryptVolumeZ mounted 2013-10-11 03:51:08 UTC+0000
Symbolic Link        Volume{52b24c50-eb79-11e2-93eb-000c29e29398} -> \Device\TrueCryptVolumeR mounted 2013-10-11 03:55:13 UTC+0000
File Object          \Device\TrueCryptVolumeR\$Directory at 0x7c2f7070
File Object          \Device\TrueCryptVolumeR\$LogFile at 0x7c39d750
File Object          \Device\TrueCryptVolumeR\$MftMirr at 0x7c67cd40
File Object          \Device\TrueCryptVolumeR\$Mft at 0x7cf05230
File Object          \Device\TrueCryptVolumeR\$Directory at 0x7cf50330
File Object          \Device\TrueCryptVolumeR\$BitMap at 0x7cfa7a00
File Object          \Device\TrueCryptVolumeR\Chats\Logs\bertha.xml at 0x7cdf4a00
Driver               \Driver\truecrypt at 0x7c9c0530 range 0xfffff88009200000 - 0xfffff88009241000
Device               TrueCryptVolumeR at 0xfffffa801b4be080 type FILE_DEVICE_DISK
Container            Path: \Device\Harddisk1\Partition1
Device               TrueCrypt at 0xfffffa801ae3f500 type FILE_DEVICE_UNKNOWN

Among other things, you can see that the TrueCrypt volume was mounted on the suspect system on October 11th 2013. Furthermore, the path to the container is \Device\Harddisk1\Partition1, because in this case, the container was an entire partition (a USB thumb drive). If we were dealing with a file-based container as previously mentioned, the output would show the full path on disk to the file.

Perhaps even more exciting than all that is the fact that, despite the partition being fully encrypted, once its mounted, any files accessed on the volume become cached by the Windows Cache Manager per normal -- which means the dumpfiles plugin can help you recover them in plain text. Yes, this includes the $Mft, $MftMirr, $Directory, and other NTFS meta-data files, which are decrypted immediately when mounting the volume. In fact, even if values that lead us to the master keys are swapped to disk, or if TrueCrypt (or other disk encryption suites like PGP or BitLocker) begin using algorithms without predictable/detectable keys, you can still recover all or part of any files accessed while the volume was mounted based on the fact that the Windows OS itself will cache the file contents (remember, the encryption is transparent to the OS, so it caches files from encrypted volumes in the same way as it always does). 

After running a plugin such as truecryptsummary, you should have no doubts as to whether TrueCrypt was installed and in use, and which files or partitions are your targets. You can then run the truecryptmaster plugin which performs nothing short of magic. 

$ python vol.py -f WIN-QBTA4.raw --profile=Win2012SP0x64 truecryptmaster -D . 
Volatility Foundation Volatility Framework 2.3.1 (T)

Container: \Device\Harddisk1\Partition1
Hidden Volume: No
Read Only: No
Disk Length: 7743733760 (bytes)
Host Length: 7743995904 (bytes)
Encryption Algorithm: SERPENT
Mode: XTS
Master Key
0xfffffa8018eb71a8 bbe1dc7a8e87e9f1f7eef37e6bb30a25   ...z.......~k..%
0xfffffa8018eb71b8 90b8948fefee425e5105054e3258b1a7   ......B^Q..N2X..
0xfffffa8018eb71c8 a76c5e96d67892335008a8c60d09fb69   .l^..x.3P......i
0xfffffa8018eb71d8 efb0b5fc759d44ec8c057fbc94ec3cc9   ....u.D.......<.
Dumped 64 bytes to ./0xfffffa8018eb71a8_master.key

You now have a 512-byte Serpent master key, which you can use to decrypt the roughly 8 GB USB drive. It tells you the encryption mode that the suspect used, the full path to the file or container, and some additional properties such as whether the volume is read-only or hidden. As you may suspect, the plugin works regardless of the encryption algorithm, mode, key length, and various other factors which may complicate the procedure of finding keys. This is because it doesn't rely on the key or key schedule patterns -- it finds them in the exact same way the TrueCrypt driver itself finds the keys in RAM before it needs to encrypt or decrypt a block of data. 

The truecryptsummary plugin supports all versions of TrueCrypt since 3.1a (released 2005) and truecryptmaster supports 6.3a (2009) and later. In one of the more exciting hands-on labs in our memory forensics training class, students experiment with these plugins and learn how to make suspects wish there was no such thing as Volatility. 

UPDATE 1/15/2014: In our opinion, what's described here is not a vulnerability in TrueCrypt (that was the reason we linked to their FAQ in the first sentence). We don't intend to cause mass paranoia or discourage readers from using the TrueCrypt software. Our best advice to people seeking to keep data secure and private is to read the TrueCrypt documentation carefully, so you're aware of the risks. As stated in the comments to this post, powering your computer off is probably the best way to clear the master keys from RAM. However, you don't always get that opportunity (the FBI doesn't call in advance before kicking in doors) and there's also the possibility of cold boot attacks even if you do shut down.

-Michael Ligh (@iMHLv2)

Monday, January 13, 2014

The Secret to 64-bit Windows 8 and 2012 Raw Memory Dump Forensics

Those of you who attended OMFW 2013 received a talk on Windows 8 and Server 2012 memory forensics with Volatility. One of the interesting aspects of this new operating system, which includes 8.1 and 2012 R2, is that the kernel debugger data block (_KDDEBUGGER_DATA64) is encoded by default on the 64-bit versions. As noted in Takahiro Haruyama's blog, this capability has been present since Vista, but only enabled in certain situations. Whether you're dealing with one of those special circumstances from a Vista/2008/7 system, or if you're analyzing memory from a more recent Windows 8 or 2012 system, the question remains -- what can you do about it?

An encoded KDBG can have a hugely negative effect on your ability to perform memory forensics. This structure contains a lot of critical details about the system, including the pointers to the start of the lists of active processes and loaded kernel modules, the address of the PspCid handle table, the ranges for the paged and non-paged pools, etc. If all of these fields are encoded, your day becomes that much more difficult.

>>> dt("_KDDEBUGGER_DATA64")
'_KDDEBUGGER_DATA64' (832 bytes)
0x0   : Header                      ['_DBGKD_DEBUG_DATA_HEADER64']
0x18  : KernBase                    ['unsigned long long']
0x20  : BreakpointWithStatus        ['unsigned long long']
0x28  : SavedContext                ['unsigned long long']
0x30  : ThCallbackStack             ['unsigned short']
0x32  : NextCallback                ['unsigned short']
0x34  : FramePointer                ['unsigned short'] 
0x38  : KiCallUserMode              ['unsigned long long']
0x40  : KeUserCallbackDispatcher    ['unsigned long long']
0x48  : PsLoadedModuleList          ['pointer', ['_LIST_ENTRY']]
0x50  : PsActiveProcessHead         ['pointer', ['_LIST_ENTRY']]
0x58  : PspCidTable                 ['pointer', ['pointer', ['_PSP_CID_TABLE']]]

As Takahiro points out, acquiring memory in crash dump format may help you evade this problem altogether, because some APIs used to create crash dumps will automatically decode the data before writing it to the crash dump file. They do this so Microsoft's debugger (Windbg) can find and read the structure when necessary. In fact, by simply attaching a kernel debugger to a target system, the KDBG structure will be decoded. However, tools that acquire memory in raw format (with no headers, no meta-data, etc.) will not preemptively decode the data, and raw memory dumps, including virtual machine snapshot memory files, are by far the most common format -- since practically all analysis tools accept them as input.

The answer to the problem lies within the NT kernel module, specifically in a function named KdCopyDataBlock. Here you will find a few variables, such as KiWaitNever and KiWaitAlways which are set based on the value of the timestamp counter (RDTSC) when the system boots (these values are also involved in pointer obfuscation for Patchguard2). Using those values in combination with a small formula, which we tweeted back in July 2013, you can fully decode the KDBG structure in raw memory dumps and access its members per the usual.

When you execute Volatility against a raw memory dump (or any memory dump format for that matter) that contains an encoded KDBG structure, it will first find the KiWaitNever, KiWaitAlways, and few other required sources of entropy. Then it will find the KDBG structure, despite the fact that its encoded, and use the previously found values to decode it. The plain-text data is stored in the memory of the Volatility process, not written back to your memory dump file. As a result, from the end-user's perspective, nothing has really changed. You go about your analysis in the same way you always do:

The build of Volatility that supports 32- and 64-bit Windows 8, 8.1, 2012, and 2012 R2 is currently being beta-tested by students who participate in our training classes, as well as by a few select members of the community. We hope you're as excited about this new capability as we are!

Tuesday, January 7, 2014

The Art of Memory Forensics

By now, some of you may have realized that The Art of Memory Forensics is available for pre-order on Amazon.

The Art of Memory Forensics: Detecting Malware and Threats in Windows, Linux, and Mac Memory

This book is written by 4 of the core Volatility developers - Michael Ligh (@iMHLv2), Andrew Case (@attrc), Jamie Levy (@gleeda) and AAron Walters (@4tphi). We've been collaborating for well over 6 years to design the most advanced memory analysis framework and we're excited to be collaborating on a book.

The content for the book is based on our Windows Malware and Memory Forensics Training class, which has been executed in front of hundreds of students across the US and Europe. As an added bonus, the book will also cover Linux and Mac memory forensics.

Unlike some other books, which will run you $50 for 250 pages (we call those expensive brochures), The Art of Memory Forensics will be over 700 pages. In fact, its still possible that we may grossly exceed that and have to split it into two editions, which will royally piss off our publisher.

An electronic book will be available for Kindle initially and at some point, also on Safari Bookstore.