Weekend Scripter: Using PowerShell to Aid in Security Forensics

Microsoft Scripting Guy, Ed Wilson, is here. I have had many interesting email threads with Will Steele, and I have even spoken at the Dallas Fort Worth PowerShell User Group via Live Meeting. Therefore, it is with great pride that I introduce Will Steele.

Will Steele live near Dallas, Texas with his wife and three kids. He works as a senior network analyst at a financial services provider and he manages a document imaging system with a heavy investment in Microsoft enterprise technologies. Last year Will started the Dallas-Fort Worth PowerShell users group, and he contributes to the Windows PowerShell community in forums and through his blog.

Here’s a hypothetical thought about how Windows PowerShell can help in forensics registry analysis. The layout: You are a systems admin for a large IT corporation. You learn that a spreadsheet containing highly sensitive information was accessed without permission by a server in your group the previous day. Your task? Verify who opened it with one condition: you can’t use any non-Microsoft tools. You start by coming up with two simple questions:

Who accessed the server within the past 24 hours?

How, when, and where was the file accessed?

Some logs indicated which machine accessed the file, but didn’t indicate the user. Only a handful of people are now possible candidates. The number of folks with full administrative rights and access to the servers is small. Conferring with your manager about who was working yesterday, you come up with a list of four possible.

Getting down to work, you launch Windows PowerShell and plan to keep an audit trail of what you do. A log will serve perfectly as documentation of your research, so, you run this command:

md C:\research

Start-Transcript –Path C:\research\analysis.log

You then decide to see if any of these people were out of the office during the time of the incident. Remoting was enabled on your domain for all of your administrators, so, their workstations would allow you to query the workstation logs. You need an event log query to develop a timeline of log on/log off events and run it against the server. Because all the workstations run Windows 7, you use this to check for logon/logoff event IDs:

To identify which people you may need to look at more closely, you remotely query each machine to build a cross reference based on logon/logoffs. To save typing, you store the hash table from your server search as a $eventhashtable variable and pass it to the Get-WinEvent cmdlet inside a loop to check the four workstations.

Moving on to the server, you learn that it hasn’t been rebooted since last night. This increases the likelihood that the registry still contains pertinent information. You now turn to the machine to get more details. First things first: getting to the machine without arousing suspicion. Thankfully, in Windows PowerShell, this is a trivial task.

New-PSSession -ComputerName server

To determine which hives to look at, you check the IDs for verification. This command will list all users on the machine by name and SID:

This loads the HKEY_USERS hive as a PSDrive and passes the SID values to the domain controller via an ADSI LDAP call, which returns the UserPrincipalName. You know that there’s a good chance the UserPrincipalName will match the name of the C:\Users\<profile> on the server. The command returns the following information.

admin01 - S-1-5-21-123456789-1234567890-1234567890-8901

admin02 - S-1-5-21-123456789-1234567890-1234567890-8902

admin03 - S-1-5-21-123456789-1234567890-1234567890-8903

admin04 - S-1-5-21-123456789-1234567890-1234567890-8904

superadminjrich - S-1-5-21-123456789-1234567890-1234567890-1472

superadminjmiller - S-1-5-21-123456789-1234567890-1234567890-1567

superadminmcruz - S-1-5-21-123456789-1234567890-1234567890-3245

To double-check these users, you run a Get-WmiObject cmdlet as a sanity check.

The four accounts in question do have local profile data on the server, so, you move into phase 2: find out when and where the file was accessed on the server. Noticing that Admin01 and Admin02 hadn’t logged on to the server recently eliminates them. Rather than work directly against the hives on the live server, you copy NTUSER.DAT files and disconnect from the server:

'admin03','admin04' |

% {

md "C:\research\$_"

copy "\\server\c$\users\$_\ntuser.dat" "C:\research\$_"

}

Exit-PSSession

To start exploring the files, you need to load them into your current session. This old reg.exe command does the trick:

reg load HKLM\admin03 C:\research\admin03\ntuser.dat

Admin03’s hive now can be accessed via your PSSession under HKLM:\admin03. This way, you can explore their profile as if it were yours. To be sure this worked as expected, you check with regedit.

Switching over to Windows PowerShell, you start by examining most recently used (MRU) lists for this user. You recall that your manager mentioned a spreadsheet, so you look at several keys without finding the file. Finally, you find a key that piques your curiosity:

HKLM:\admin03\Software\Microsoft\Office\14.0\Excel\File MRU

Exploring the contents of the key is as simple as running this command:

You notice some weird values prefixing the file paths. Apparently the bracketed values are metadata for Excel. Interestingly, [T01CD5496156B3EF0] is a non-standard 64-bit Windows date and time stamp that is stored as hexadecimal. To convert it from the registry value to a [DateTime] object you use the following:

an excellent article about a very interesting way of gathering information!

It is a bit difficult to get at the C# code but it shows again, that we can extend Powershell

with .Net classes to integrate the missing functions.

That's a good example of how to do this.

Thanks, Klaus.

Will Steele

28 Jul 2012 10:08 PM

Thanks for the kind remarks gentlemen. Klaus, I agree, the ability to take .NET languages and extend PowerShell's functionality is one of its great features. Even if you do not understand every part of a C#, VB, or, JScript signature, PowerShell allows you take working code in other languages and apply them directly with very little effort. In my mind, I like to think of PowerShell as a .NET interpreter very much the same way F# has fsi.exe. Microsoft has done a great job allowing us to take existing code in other languages and run with it. This opens up many avenues which did not exist before.