EnScript v6 Tutorial IV

Thursday, January 31, 2008

I have posted some answers to the first forensic practical here. Based on the lack of answers/feedback on the first one it was either too difficult or nobody was really interested, so I will post an easier second problem and see how this one goes.

Scenario:
An employee named Castor Troy has just abruptly left a software company that he has worked at for the past 5 years. His departure was sudden and somewhat suspicious. Co workers said he came in very early the day he quit and seemed "panicked".

Due to his tenure, he had access to some critical intellectual property. When he left, the IT department assumed control of his computer and briefly examined it pursuant to an HR request. They found several zip files in the user's home folder containing some critical information. HR has referred this to legal counsel and you have been retained to provide whatever information you can about what happened and what, if anything may have left the company when the employee quit. The information found in the user's folder is critical IP information, but the employee had access to even more sensitive information deemed very secret.

Inside Counsel would like to know if any of that information was accessed or copied. Your mission, if you choose to accept, is to conduct a forensic examination and provide whatever factual information you can to counsel so they can decide if further legal action is necessary.

Good luck, have fun, and as always, if you are caught I will deny any knowledge of your existence.

A few weeks ago I posted a forensic practical along with a basic scenario. You can review it here. A few readers posted some comments, some of them on target, but not nearly in-depth enough. Here is a summary of key points that should have been observed.

1. WINDOWS/system32/inetsrv/rpcall.exe is malware and would be identified by an AV scan. The behavior of this malware is to scan for additional vulnerable machines, which is what caused the network traffic. This executable is set to run at boot through the HKLM\Run key.

2. Looking at the creation date of rpcall.exe should reveal some interesting things, most notably is that every file in the parent folder (\windows\system32) has the same created date/time. This is not normal and is indicative of some sort of timestamp manipulation tool.

3. Sorting by filenames would have revealed a prefetch file was created 06/18/04. Sorting on creation time on that file would show several other files of interest were started near that same time:

ping.exe
cacls.exe
cmd.exe
sms.exe

4. Looking for sms.exe would result in finding no executable named that, but there must have been one at some point if there was a prefetch file, right?

5. An exam of the User assist keys shows several programs run by the user account of "vmware". One of which is "UEME_RUNPATH:C:\System Volume Information\_restore{00D8A395-89D5-46B8-A850-E02B0F637CE5}\RP2\snapshot\Repository\FS\sms.exe" What the heck is a user doing executing something out of a system restore point folder?

6. Searching in unallocated for "sms.exe" in Unicode would reveal some interesting results

7. Searching the $Logfile would also reveal some interesting results for the keyword of sms.exe, including a complete MFT record for that file and the MAC timestamps. In addition there is an interesting fragment of text from what appears to be a batch file named del10.bat.

8. A search of del10.bat would reveal several hits, including a complete MFT record in the $logfile with timestamps and the appearance in two prefetch files, sms.exe & cmd.exe.

Monday, January 28, 2008

The NTFS file system is pretty verbose and redundant. With the introduction of Windows Vista, there is even more file system redundancy with the Volume Shadow Service (VSS). Windows uses a 64 bit timestamp to track most file system events (created, accessed, written, modified). This 8 byte value represents the number of 100-nanosecond intervals that have passed since midnight UTC, January 1, 1601.

There have been many times where I have found myself searching for these Windows timestamps in the various internal files. EnCase and most of the other forensic tools show you the contents of the master file table (MFT), but what if the reference to the file and folder is no longer there?

On several occasions I have found references to files/folders in the $LogFile and unallocated space that were of interest. Most times I found them because I was searching for a specific filename and I uncovered the record or I stumbled across it. In those cases, I found myself trying to craft a GREP expression to then lock onto any other Windows TIMESTAMPS that were for the time frame. As an example, the screenshot below is of an MFT record that is in the $LogFile:

This EnScript basically takes a starting date/time combination and then an ending date/time combination and generates an appropriate GREP search expression for that date range. It then searches any selected (checked) files for that date range and then bookmarks the findings. Because Windows timestamps are very granular and accurate down to a 100 nanosecond interval, exact date/time matching is impossible, but its very close depending on the size of your date range. Smaller date ranges (a couple of days) will be much more accurate than large date ranges (several months).

The option at the bottom allows you to look for consecutive timestamps, i.e. a timestamp matching your date range, followed by another timestamp, not necessarily in your date range. This is if you want to specifically look for orphaned MFT records in unallocated or the $Logfile, since an MFT record has eight timestamps, a group of four consecutive timestamps and then another group of four, then setting this option would only find those types of records.

This EnScript bookmarks any found timestamps and then reads the timestamp and places it in the comment field for sorting purposes. The timestamp in the comment field is GMT and your case settings have no effect on it. If you choose to sweep the timestamp and view it through the bookmark styles, then your case timezone setting applies.

Friday, January 25, 2008

**UPDATED Version 1.1 - fixes a problem with boomarks in multiple files

The Yahoo Messenger client has the option to save chat conversations to a text file. The default is to save all conversations until the Yahoo Messenger application is closed and then the logs are purged, thus leaving them in unallocated space.

Yahoo Messenger does not store the chat conversations in plain text, but instead uses the low-level XOR encryption technique to obfuscate them. This thwarts the technique of doing a keyword search for something that may have appeared in the chat conversation to find a conversation or fragment of the log in unallocated.

Yahoo Messenger uses the screen name of the person logged in using the Yahoo client as the XOR key. That key is then applied to all chat text and the resulting ciphertext is stored in the logs. If you use the built-in Yahoo archive viewer, the text is decrypted and displayed, but as it sits on disk, it is encrypted.

I have written an EnScript that asks for two primary things, the screen name of the person using the local Yahoo client and then the keyword or phrase you wish to search for. The following is an example of how the chat conversation is encrypted by the Yahoo Messenger client.

For example, lets assume the local user has a screen name of "localuser" and the remote user has the screen name of "remoteuser". The localuser sends the following message to the remoteuser:

"lets meet tomorrow and talk about how we are going to murder her"

If you think about the XOR process similar to doing addition, the localuser screen name is applied to the above text in the following way:

lets meet tomorrow and talk about how we are going to murder her
localuserlocaluserlocaluserlocaluserlocaluserlocaluserlocaluserloca
------------------------------------------------------------------
resulting ciphertext resulting ciphertext resulting ciphertext

The resulting XOR ciphertext would be the result of XORing the top "l" with the bottom "l", then "e" with "o", "t" with "c", and so forth. So from this example you can see that if you were searching for the keyword of "murder" you would have to XOR it with "aluser" in order to search for the correct cipher text (it may not be aligned properly in the above display).

This EnScript basically takes the keyword or phrase you enter and then XOR's it every possible way depending on how long the screen name is. Using the example above, searching for the keyword of "murder", there would be nine possibilities (because the screen name of "localuser" is nine characters long). So this EnScript creates all the possible ciphertext keywords and then searches the selected (blue checked) file for the ciphertext and bookmarks any findings.

Currently, I consider this EnScript in BETA form. It seems to work and find the keywords I have search for, but I have not thoroughly tested it yet. In addition, it simply bookmarks the found ciphertext, but leaves further decoding to you. I may add that in future releases and will most likely add additional information to the bookmark in the near future. I welcome any feedback, comments or feature enhancements.

Wednesday, January 23, 2008

This post is just a refresher for those of you who may encounter a running Vista machine that has BitLocker enabled. The following command will display the recovery password in a command prompt so it can be recorded (a photo) for later use by the examiner.

When initially looking at a running Vista machine, one easy indication that bitlocker is installed is the presence of two volumes. The main volume labeled "C:", and a second volume labeled "S:" (Of course this labeling is by default and could be changed).

The second volume labeled "S:" is a small boot partition that is created when BitLocker is enabled and is typically 1.46GB in size. The contents of this volume is minimal and will at a minimum contain the following files & folders:

If you suspect BitLocker is installed, and even if you recover a removable flash drive that you suspect contains the startup key, the following command is recommended. Start a command prompt with escalated privileges by right-clicking on the command prompt option from the Start menu and choosing "Run as Administrator". Once the command prompt starts, it should say "Administrator: Command Prompt":

Once you have this prompt, the best practice would be to insert your Incident Response toolkit CD-ROM that you previously built (you did previously build it, right?) that contains two WMI scripts that can be found on a default installation of Vista with Bitlocker enabled. These two files can be found in the system32 folder of a BitLocker enabled Vista installation and are named:

manage-bde.wsf
manage-bde.ini.en

You should copy these two files along with the cscript.exe interpreter to your incident response CDROM, you know, the one that's in your incident response toolkit and ready to go....:(

These files are installed by default when the BitLocker feature is enabled, but you shouldn't use the ones on your suspect's installation of Vista. Yes, you are already using the suspect's untrusted operating system, but this is about minimizing risk.

The command to obtain the BitLocker recovery password is:

"cscript manage-bde.wsf -protectors -get c:"

The best method is to take a photo, but verify the photo is not blurry or washed out by the flash before you proceed. Alternatively, you could pipe this information to a text file on a floppy or an inserted flash drive (remember you are going to create registry keys, so document).

You can then shutdown the system and remove the drive to be later imaged in the lab. Once connected to a write-blocker, EnCase (with the EDS module) will recognize the volume as a BitLocked volume and ask for the recovery password. You can then enter the recovery password as it was displayed and make a complete decrypted copy of the data at the logical level (if you look at from the physical level, it will still be encrypted because the data is still encrypted as it sits on the disk).

Alternatively, you can connect the drive to a write blocker (better yet, make a bit level copy and use that) and then connect it to a forensic machine that has Vista installed with BitLocker enabled. Vista will see the volume as a foreign encrypted volume and ask for the recovery password. Once entered, Vista will then mount the volume and assign a drive letter. You can then fire up your favorite trusty imaging application and image the logical volume in a decrypted state.

Both methods will make a decrypted copy of the data so from that point forward, BitLocker is removed from the equation.

*NOTE: There are two primary methods of implementing BitLocker. The first is with the use of an onboard TPM chip. The second is currently the more common implementation and only involves a removable flash drive (a third method exists that involves using both a TPM chip and removable flash disk, which is considered the more secure implementation). The above described commands will succeed for all the different BitLocker methods, but if a TPM chip is installed and used, the decryption process when attempting to image the volume will not work because it relies on the TPM hardware component as part of the decryption process. In theory the only solution in that scenario would be to connect a bit-level copy of the original hard drive to the original suspect's computer and then provide the recovery password at boot and then image the visible volume off to a external drive. I have not yet had the opportunity to test this because I do not yet have a TPM enabled computer. If someone has used or tested this method, please advise.

Monday, January 21, 2008

An EnCase user contacted me about a problem he was having searching for a fairly common keyword and how he could exclude certain preceding or proceeding words that were adjacent to the core keyword.

Regular GREP expressions allow you to do this, but the EnCase version of GREP currently does not support using the NOT operator ("^") against multiple characters. So for example if you wanted to search for the keyword of "install". When the search was done, you may have thousands of hits, but see that the majority of them are a word like "clientinstall", and/or 10 other combinations of the keyword of "install" like windowsinstall, installapp, applicationinstall etc.. The EnCase version of GREP DOES allow the NOT character to be used such as this example:

[^t]install

This would find the keyword "install" as long as there was no preceding "t" character before it. This example would eliminate the term clientinstall" as I indicated above, but it would also eliminate all other possible keyword hits that may have the letter "t" preceding the keyword of "install", such as "statinstall", which I may want.

So to get around this scenario, I wrote an EnScript that asks for a keyword. It then also asks for a list of exclusion words (it can be pasted into the window). The EnScript then search ALL SELECTED items for ANSI and UNICODE occurrences of the keyword. It then reads the characters before and after the keyword hit to see if the hit is one of the exclusions you provided, if so, it skips the hit and moves on to the next hit. If the characters before and after do not match what you provided in the exclusion list, then it will bookmark it.

Using the example above, I ran the EnScript and entered "install" as my keyword. I then entered a list of exclusion words, such as:

productinstall
uninstall
appinstall
installapplication

Here is a screenshot of the three fields that require input:

The results exclude any keyword hits that are part of the exclusion list:

This is a beta version and it has not been tested completely. Please feel free to download and try and post any comments, bugs, suggestions.

Friday, January 18, 2008

I was recently contacted by Hans Heins in the Netherlands, who had some EnScripts that were written in v4 by a student trainee. The EnScripts parse out basic information from the System Volume Information, Restore Point files. He posted these EnScripts to his website listed here.

I have ported these over to EnCase v6 EnPack format.

The first one parses the rp.log for basic information on when the restore point was made. To use, select (blue check) one or several rp.log files and then run the script. A small text file with the information is created in your default export folder. You can download the v6 version here.

The second one parses the change.log and lists the files that are in the restore point. To use, select (blue check) one or several change.log files and then run the EnScript. A small text file with the information is created in your default export folder. You can download the v6 version here.

I run several honeypots and I decided to take some of the malware found on the honeypots and install it on clean computer systems and watch its behavior. To take it a step further for those of you who like to hone your forensic skills, I have decided to post an evidence file of the machine with the malware, and describe a simple scenario that a first responder or examiner would likely face in examining this evidence.

SCENARIO:

A user in a company is using WinXP Home (just go with me on this ;) and he notices his computer is acting funny. He calls the IT staff over and after some digging around they determine something is definitely wrong. When they do a netstat they see hundreds of connection attempts. They pull the machine offline and image it. They did happen to speak to their netsec people before they pulled it offline, who captured a small amount of network traffic regarding the WinXP system.

This is not rocket science people, it is fairly simple exam, but it is a good training example and a very common scenario. Please feel free to download and examine the evidence file/network capture and the post any comments on what you find.

Wednesday, January 16, 2008

It has been several weeks since my last EnScript Tutorial, so I decided it was time for the next installment in the EnScript tutorial series.

In the last tutorial, we learned how to recurse through all the evidence in EnCase and select a specific object (file or folder) based on its name matching some specific text. In this tutorial, we will learn how to read data from a file, commonly referred to as File I/O.

In this tutorial, we will recurse through all the evidence to find a file named "boot.ini". Once we find this file, we will open it so we can read specific data from it. We can also bookmark a small portion of the file in the same manner as an examiner may sweep certain text in a file and bookmark only that data. We start with the following basic code:

The third line of code recurses through all the evidence loaded in EnCase in a loop. Line four compares the name of each object to see if the name matches exactly "boot.ini". If the name matches that text, then it writes the full path to the console. When this EnScript is run, we get the following output in the console:

"Case 1\C\boot.ini"

So the EnScript successfully ran, recursed through all the evidence and found one file that has the name of "boot.ini", which is located in the root of the volume named "C".

The next step is to "open" this file so we can read data from inside the file. We first need to create a variable of the proper type to hold a pointer to the file so we can then reference that specific file and perform operations. The proper class type is the EntryFileClass. We need to first create a variable of this class type. To do this we can use the following line of code:

EntryFileClass file();

This creates a variable named "file" that is of the EntryFileClass type. The open and closed parenthesis immediately after the variable name initializes the variable and prepares it to be used. Instead of using the parenthesis, you could create the variable object alternatively using the following code:

EntryFileClass file;
file = new EntryFileClass();

This code alternatively creates a variable named "file" of the EntryFileClass type, but does not initialize it. Then the next line initializes the variable and it can then be used. Either way works, the first example just uses one line of code as opposed to two.

Once we have created the proper variable type and initialized it, we can now use it and open the file we found so we can read data from it. To open the file, there is a member function of the EntryFileClass named "Open" (that's intuitive!). We can use this function to open the file so we can move a pointer around in the file and read data. The following code "opens" the file:

file.Open(entry, 0);

This function accepts two options. The first is an EntryClass object that is a pointer to the file you want to open. Line three above causes the EnScript to recurse through each object and temporarily assigns each object to the variable named "entry". Line four then compares the name property of the entry object to the text "boot.ini". The file.Open function needs to know what EntryFileClass object you wish to open. In this example, since we are using a conditional IF statement, the EnScript will open the "entry" object as long as its name property equals "boot.ini".

The second parameter specifies if you want to open the file with some options, such as include SLACK space, don't treat an erased file as consecutive clusters or if you want to write to the file. This brings up a good point that needs clarification. You cannot write to a file in the evidence file. EnCase does not allow you to alter evidence in any way. The WRITE option is used if you want to open (create) a file on your forensic machine and then write data to it.

Once you open the file, you have to tell EnCase how you want to read data from that file, for example as UNICODE, ANSI, UTF7, etc. To do this, we use the following function, which is a member of the FileClass. If you look at the EnScript Type tab in EnCase and examine the EntryFileClass type, you will notice at the very top it states "inherits:FileClass". This means that this class inherits all the functions and properties that the FileClass has. The FileClass has a member function named SetCodePage. Since EntryFileClass objects inherit functions from the FileClass, you can call this function on a EntryFileClass object. Therefore, the following code can be used to tell EnCase how we want to read the data:

file.SetCodePage(CodePageClass::ANSI);

This tells EnCase we want to read the data as simple ANSI text, one byte at a time, as opposed to UNICODE, which would read two bytes at a time.

When a file is opened for reading, a pointer is created and placed at the very beginning of the file at offset zero. As you read data the pointer moves along through the file so that if you read data again, it knows where to continue from and it won’t read the same data again, unless you explicitly instruct it to do so. Let’s assume we want to only read a specific line in the boot.ini file. If we know where that line is we could move the pointer to where we want to read the data. For example, if we knew that the data we wanted to read started at offset 100, we could use the following function to move the pointer:

file.Seek(100);

This would move the pointer to offset 100 in the file and if we then began reading data, it would start at offset 100. But what if we don't know the offset or it changes dynamically based on the computer system and how it is configured? We could read through the file and then make a decision base don what we read. In this example, we are opening the "boot.ini" file, which is used as part of the boot process on a Windows system to decide if it is capable of multi-booting different operating systems. The boot.ini file I am using in this example looks like the following:

Lets assume we want to read the line of data that specifies what the default boot location is if the user does not specify otherwise at boot time, specifically this line:

"default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS"

One way to accomplish this is to read each line and then decide if its the one we want. In this case, there is some static text in the line we want that can be used to help us identify and decide if its the data we want. We already have the file open and ready to be read. The next step is to begin reading data. We have two options here, we could read one byte at a time or we can read a string of data. In this case, we can read each line and then decide if its the line we want. The following code can be used to accomplish this:

file.ReadString(text, -1, "\x0d\x0a");

This function reads a string of data until a carriage return (0x0d in hex) and line feed (0x0a in hex) are encountered and places the text into the "text" variable. Here is the entire code with comments:

Line 8 opens the file
Line 9 sets the code page to ANSI
Line 10 creates a variable of String type to hold a line of data as we read it
Line 11 enter a DO loop to read one line at a time until the end of the file is reached or until we find the line we are looking for
Line 12 read one line of text and place the data into the "text" variable
Line 13 if the data in the "text" variable contains "default=" then this is the line we are looking for.
Line 14 print the entire line we just found
Line 15 break out of the DO loop since we just found the line we were looking for
Line 18 End of the loop, which we will exit if we have reached the end of the file

Tthe first line is the result of the first Console.WriteLine statement (line 5). The second line is the result of finding the text we want by checking if the text "default=" is in the string we just read.

The example EnScript can be downloaded here.Please feel free to post questions, comments, complaints or the upcoming winning lottery numbers.

All the EnScripts on this website are provided as-is, free of charge, created by me on my own personal free time.

If you have found any of these EnScripts useful and feel inclined to give a donation, please feel free to use the link above. You can donate whatever amount you think is appropriate and a PayPal account is not required.

Any and all dontations are greatly appreciated and are used to offset the cost of maintaining the server to store the EnScripts & resources online.