What’s in a name? That which we call a profile
By any other name would still let us log in.
I recently ran across a case where I needed to prove which user was using which profile folder. Every once in a while, the profile folder name won’t actually be the same as the account’s username. It’s pretty easy to assume that the folder is the username, since it that is the case better than 90% of the time. But, as Admiral Akbar says, “It’s a trap!”
There are two scenarios that I’ve witnessed where this isn’t the case. If there is already a profile folder with the same username, such as if a local account was created for the user prior to them logging in with their domain credentials and both these usernames are the same, then a second profile folder will be created. Profile folders are unique by SID and even if local account and domain account are same name they will be different SIDs and thus will get their own folders. To overcome the name conflict, the system will append the domain to the username when creating the profile folder name. This is exactly what you see in the screenshot below – the \Users\benjamin.russell folder is a local account and then when Ben logged in with this domain account for the first time the system created the \Users\benjamin.russell.hitek folder. The login that associated with the former folder is benjamin.russell and the login associated with the latter is hitek\benjamin.russell. Had it happened in the opposite order, so domain credentials logged in first and then a local account was created and used, the new profile folder’s name would have hostname appended to it instead of the domain name as that is the domain context for local accounts.
Another scenario is when the user changes their name. If there is an existing profile from the user having already logged in and the user’s username changes, the system will continue to use the existing profile folder even though the name no longer matches. Changing the username doesn’t change the SID, so in the system’s mind this is not a new profile and thus it should continue with what it has. This can happen post marriage when a last name changes or can happen when a user requests their name changed for other reasons, such as in our example below where Mr. Russell said he really prefers to go by Ben. When he requested they change his login from benjamin.russell to ben.russell, the SID never changed and thus his profile is still stored in the \Users\benjamin.russell.hitek folder, as you can see in the command prompt in the screenshot below. This can very easily cause a forensic examiner to associate data from NTUSER.DAT with a non-existent username if care is not taken.
Humans are amazing, we can intuitively tell that Ben and Benjamin are the same person and that Hitek is the domain thus benjamin.russell.hitek is the profile folder of his domain account, but computers aren’t so quick. So, how do we positively tell which folder belongs to which user?
I was really hoping the NTUSER.DAT held that answer, but it doesn’t. There is no pointed reference to the username or SID anywhere in that hive. There are some consequential references, such as some MS Office, ActiveInstaller, and Media Player related keys that list usernames, but they aren’t concrete and aren’t guaranteed to be there on every system. There is a solid clue in this article. The answer is in the SYSTEM hive in the HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\ key. Within that key is a series of keys named after the SID of each user profile on the system. This includes the various system profiles and omits the \Users\Default folder that trips up a lot of automated user data processing scripts I’ve seen. If you want a script to touch every profile that actually is a profile, this is where it should go to start its search.
Inside each SID named key you will find a value named ProfileImagePath that contains the location on disk of the profile for the user that has this SID. This allows you to definitively tie this folder to this SID, but you will have to look elsewhere to tie the SID to the username (hint: PsGetSid from Sysinternals). The other values in there, according to this, are as follows, just in case you find them forensically interesting depending on your specific case needs.
Default: It’s the value whose name is null.
Flags: Enables you to control the installation and uninstallation of your registry entries. No further information available.
GUID: This is a unique ID for this user account. It is only present on domain accounts; local accounts are absent this value. Locally, it corresponds to keys in the PoliciesGUID and ProfilesGUID keys just above the ProfileList key. Inside each of those keys is a key for each GUID with a value that tells me which SID this GUID maps to. Kinda circular and not very helpful.
ProfileImagePath: The User’s profile path. This is the important one.
ProfileLoadTimeLow: These two DWORDs make up the high-order bits and low-order bits, respectively, of a double dword that is a timestamp. Combine the 4 bytes you get from each in the right order and you should get 8 bytes that become the date and time when the user logged in. I frequently find these values as zeros, though, so I’m not sure when this gets populated vs when it gets ignored.
RefCount: value of 0 means the account has no active session, anything higher means the account has an active session. The implication is that this number indicates the number of concurrent logins by that user, but I’ve seen this number be higher than current session count so I think it counts logins but doesn’t decrement when the session ends.
RunLogonScriptSync: Determines whether the system waits for the logon script to finish running before it starts Windows Explorer and creates the desktop.
0 The logon script and Windows Explorer can run simultaneously.
1 Windows Explorer does not start until the logon script has finished running.
Sid: The Security Identifier in binary
State: Indicates the state of the local profile cache. For example, a state of 256 = x100 = Admin account, and 772 = x304 = x200 + x100 + x004 = a bunch of stuff.
x0001 Profile is mandatory.
x0002 Update the locally cached profile.
x0004 New local profile.
x0008 New central profile.
x0010 Update the central profile.
x0020 Delete the cached profile.
x0040 Upgrade the profile.
x0080 Using Guest user profile.
x0100 Using Administrator profile.
x0200 Default net profile is available and ready.
x0400 Slow network link identified.
x0800 Temporary profile loaded.
I recently read an article that included the following quote:
“During Chinese President Xi Jinping’s recent state visit, the two countries agreed to a “common understanding” that neither side would engage in or support commercial espionage. The agreement did not address legitimate intelligence espionage.”
There is a fundamental misunderstanding of foreign cultures that seems to constantly come up, both in how our delegated officials interact with foreign states and how our media reports on those interactions.
To counter the point the person being quoted is trying to make in their last sentence, we would never enter into any agreement that addresses intelligence espionage because that is how we keep check on foreign states, both ally and adversary. How do you know they are doing what they told you they would do during the diplomatic talks if you don’t monitor their actions? Every country does this. As an example, it was interception of communications between two countries that were not considered our adversaries at the time that brought us into WWI. Our intelligence apparatus is older than our country, having been formed during the Revolutionary War, and we are not, nor will any other country, going to agree to anything that will cripple intelligence gathering capabilities.
The problem comes when we try to evaluate that foreign state’s words or actions based on our own ethics, cultures, and mindsets. To China, there is NO difference between commercial espionage and intelligence espionage. To China, theft of an idea is not theft because you have not stolen a thing; thus the huge and invasive knock-off market that originates from there that permeates every industry from clothes to purses to electronics. From our point of view, government and commercial are two different things. To China, the government controls the commercial environment and takes a very active stake in bettering those companies’ placement in the world market because improving China’s commercial interests are one in the same with improving China’s governmental interests.
How can we expect them to differentiate between commercial and governmental espionage and make an active stance against theft of corporate intellectual property when in their eyes there is no difference between the two types of espionage and there is no ethical problem with conducting commercial espionage to better their interests?
Named Key cells are the data structures within the Registry that hold the Keys and provide the parent/child data necessary to build the tree. Different documentation calls these Named Keys, Node Keys, or NT Keys. It is unclear which is correct, so I’m going to go with Noodle Keys.
|offset||length||type||what is it?|
|x08||8||datetime||Last Modified Date|
|x14||4||int32||Parent Key Offset|
|x18||4||int32||Number of stable sub keys|
|x1C||4||int32||Number of volatile sub keys|
|x20||4||int32||Sub key offset|
|x24||4||int32||Volatile sub key offset|
|x28||4||int32||Value List Count|
|x2C||4||int32||Value List Offset|
|x30||4||int32||Security key offset|
|x34||4||int32||Class name offset|
|x38||4||int32||Max name length|
|x3C||4||int32||Max class name size|
|x40||4||int32||Max value name size|
|x44||4||int32||Max value data size|
|x4C||2||int16||Key name size (n)|
|x4E||2||int16||Class name size|
This is what one would look like in a hex editor:
|Length||Sig||Flags||Last Modified Date|
|Unknown||Parent||# Skey subs||# Vkey sub|
|Skey offset||Vkey offset||VL count||VL offset|
|Seckey offset||Class offset||Max Name Len||Max Cls Sz|
|Max Name Sz||Max Data Sz||Unknown||KNS||CNS|
Notes and observations:
The length field at the beginning is a negative number for allocated cells. So, an 88 byte cell has a length of xA8FFFFFF and a really long cell of 264 bytes would be xF8FEFFFF. When this number is positive it describes an unallocated cell. When searching for unallocated cells, I’ve seen three scenarios: 1. the cell is empty (length makes no sense), 2. the cell is partially overwritten (size is logical, but another record is found much sooner), and 3. the cell is a whole deleted record (yea!).
Scenario 1 looks like this. Note the length set to x00 and the complete lack of usefulness. This appears to be the case when an unallocated cell’s ‘nk’ signature appears in slack space of another cell. In this example below, the x0000 at offset x00 is the null terminator to the string on the previous line and that cell consumes all the way to offset x07 with the next cell starting at offset x08.
Scenario 2 looks like this. This appears to be legit data that was partially overwritten. We have a length field of x58 or 88 bytes, yet we have another cell starting after 64 bytes.
|00||58||00||00||00||6E||6B||20||00||68||51||82||45||30||89||CB||01||X nk hQ‚E0‰Ë|
|40||A8||FF||FF||FF||6E||6B||20||00||37||7A||B2||76||18||3E||D0||01||¨ÿÿÿnk 7z²v >Ð|
The flags at offset x6 tell us some interesting things about this key. They parse out as:
|00000010||x02||Is mount point|
|00001000||x08||Cannot be deleted|
|00010000||x10||Is symbolic link|
|00100000||x20||Name is ASCII, 0 = Unicode|
|01000000||x40||Is predefined handle|
Most of these fields seem self explanatory based on the names, but I’ve seen conflicting names in different documentation.
Several of the fields will be xffffffff if they are undefined, such as Volatile Sub Key Offset and other offsets.
Parent Key Offset at offset x14 provides the location of the cell that is this cell’s parent. Offset starts from start of first bin, so add 4096 to cover regf header. Root cell has a value in this field even though it doesn’t have a parent and that value is garbage that points to a location that doesn’t make any sense. Not sure why that isn’t just zeroed out.
Sub Key Offset will point to an lf cell that lists all of the children cells and provides their locations. The best and most succinct explanation of this relationship is in appendix 22 of Norris’s documentation. More on that later.
The Value Key Offset and Count work just like the Sub Key data but for Values.