Hello Readers!

This week is a continuation of sorts from my code from last week.  As you recall I created a script to parse the volume boot record of a FAT32 volume.  This week my script is designed to parse a volume boot record from a FAT12/16 file system.

The overall goal will be a single script that will determine which volume boot record it’s dealing with, and pull out the appropriate information.  From there it will be incorporated to a larger script that you can point at a disk image, and it will parse out all the partition information for you in one shot.

Now again there are a lot of different tools already that can parse this information, but it gives me a great change to practice my Python coding.  And doing it in this structured way allows me to have a “baseline” to test from as the overall script takes form.

Next week I’ll have a script to parse out an NTFS VBR, and from there I’ll be putting all the components together.

Until next week!


Hello Reader!

I teach part time at a college.  It’s a great experience being able to pass on things you’ve learned in the field you work in.  And for me it helps reinforce a lot of the “fundamentals” that one takes for granted as the years go on.  I definitely recommend anyone who gets the opportunity to teach a class to take advantage of it.

Some of the assignments I give out to my students require them to parse data with a hex editor.  I like making scripts to parse out my lab and homework assignments because it saves me from having to use a hex editor. :)  And I also get to go through all the images I have really quickly to figure out which ones to use for assignments.

So this week I wrote a script to parse FAT32 Volume Boot Records.  My overall goal is to write a large script that can parse either FAT12/16/32 VBR’s, but it’s not there yet.  It will slowly appear over the course of this Python adventure I’m on.

Until next week!


Hello readers!

This week I needed to create a script to scan some servers in my environment to confirm that an agent we deployed was installed.  I could use the “native” client that comes with the agent to do my check, but this gave me an opportunity to write some code.  Plus it would be faster because I just needed to see if I could connect to the port.  That would tell me if the agent is running.

So this “introduced” me to the socket module with Python.  And after a bit of trial and error I got the program to do what I wanted to do.  But I wanted to add some additional aspects that would give me a bit of flexibility with the script.  Mainly that I could just feed it a list of IP’s, pick whatever port I wanted to use, and then output it to a file so I could review the results.

Argparse is the module to use (from what I’ve seen) if you want to pass command line arguments to your program.  The bonus is that it’s already part of any newer python install.  Adding options for the input file, output file, and port means I can basically use the script for this one project, but easily use it for anything else to check in the future.

Until next week!


Hello Reader!

This week, I wanted to get back to my code from Week Two, where I created a program to download the md5 hash files from the VXShare website.  What I wanted to do was create a configuration file to track the last file that I downloaded, as well as create a new file if it was the first time I was running the program.

So I decided to use the ConfigObj python module for the configuration piece.  No real reason to be honest, except it was the first one on the ConfigParserShootout page of the Python Wiki, and it did what I needed it to do.  Which was basically to act like an INI file.

The code looks like this:

if os.path.exists(config_file):
    print "File exists"
    config = ConfigObj(config_file)
    vxshare_no = int(config['last_vxshare_num'])
    print "File doesn't exist"
    config = ConfigObj()
    config.filename = config_file
    config['last_vxshare_num'] = 0
    vxshare_no = int(config['last_vxshare_num'])

For the first part of the code, I’m checking to see if the configuration file already exists.  If it does, I use that as my configuration file, and I pull out the “last_vxshare_num” value, which represents the next file to check the site for.  You have to pass it into the “vxshare_no” variable as an integer, because we’re going to increment this number (if there is an updated file), and by default the configuration value is a string.

If the configuration file doesn’t exist, we’re going to make the assumption that it’s the first time we’re running this program, and we need to create the configuration file.  The ConfigObj module makes it really easy to do that, by just opening up an empty ConfigObj class (I believe it’s a class, I’m still getting all the Python terminology down), and then you create the file with the filename method.  Since it’s a new file we initialize the “last_vxshare_num” variable to zero, and then pass it to the “vxshare_no” variable.  Again it needs to be passed as a string.  In both instances I added a print statement just as a check if the code sees the file or not.  In the overall code I’ve removed that.

My next step with this, is to configure the hash files after they are downloaded for import into X-Ways Forensic.  What needs to be done is remove the first six lines of the file, and then add “MD5″ as the first line.  That’s what I’m looking to do next week…

Until then!


Hello Reader!

So here we are at part 2 from last weeks post. On the Github site, the Week 5 code contains both parts in it.  I figured it would be easier to have the entire piece of code then trying to separate out the second part of the code.

So at this part of the code we’re dealing with the Cache Directory Table.  The cache directories hold the temporary files for Internet Explorer, and are grouped in quantities of four.  Normally there are only four of these directories, but there can be more.  The names of these directories are randomly generated.

So first at offset 72 of the index.dat file, we have the number of cache directories.  So the first thing I did with my code was pull that 4 byte value, and use that as a key for the number of directories I’ll need to parse out.

num_cache_dir_entries = ie_ind_four_byte(ie_index_header[72:76])
num_cache_dir_parse = num_cache_dir_entries
start = 76
end = 88

Each cache directory is 12 bytes long, so I initialize a start point of 76 and an end point of 88.  This should handle the first directory entry.  Then all I need to do is move the end value to the start value, and then create a new end value by adding 12 to the new start value.  Then just repeat until the number of cache directories I have to parse is zero.

dict_cache_dir_entry = {} # initialize a dictionary to put the cached directory name and no of cached files
while num_cache_dir_parse > 0:
    cache_dir_entry = ie_ind_cache_dir_entry(ie_index_header[start:end])
    dict_cache_dir_entry[cache_dir_entry[1]] = cache_dir_entry[0]
    # increment our variables
    start = end # Pass the previous ending point to the start
    end = end + 12 # Now add 12 to the previous ending point to get the new one
    num_cache_dir_parse -= 1

Now I also create a dictionary called dict_cache_dir_entry that I’ll use to store the cache directory name and the number of cached files in that directory.  I’ll end up using the directory name as the key, and the number of cached files as the value.  However the trick in the code is that in the index.dat file, the number of cached files is first, and the directory name is second, so I have to swap out the code.

Finally I print out the data along with the other information.

That’s all for this week!


Hello Reader!

So we’ve made it to one month, and this week we have a two part code snippet.  Both parts of code for this week and next are designed to parse the header of an index.dat file.  I’m using the following paper from Joachim Metz to parse the code:

https://github.com/libyal/libmsiecf/wiki (click on the Documentation link)

The code parses the first 72 bytes of the file header.  What I decided to do when I was writing this is create two functions.  One to parse out a 4 byte value, and the other to parse out an 8 byte value.  That way I’m able to reuse the same functions multiple times.  The same two functions will also be used in part 2 of this script when I post it next week.

def ie_ind_four_byte(decoder):
    ind_four_byte = struct.unpack("<L", decoder[0:4])
    return ind_four_byte[0]
def ie_ind_eight_byte(decoder):
     ind_eight_byte = struct.unpack("<Q", decoder[0:8])
     return ind_eight_byte[0]

Once the data is all parsed out, it prints the output for the user.  Part 2 next week will be the code I wrote to parse the cache directory table.

Until then!


Hello Reader!
Well this week I’m sort of taking a shortcut, but what I enjoyed about this script is it was rather easy for me to write. I’m happy about that because it at least gives me some hope that this resolution will accomplish what I want it to.

I teach Computer Forensics part time for a University here where I live. The class started up last week, and I was putting some finalizing touches on my week one lecture. Part of this lecture just goes over the fundamentals of converting decimal numbers to both their binary values and their hexadecimal values. For the students homework assignment, they have to take a binary number and write down the decimal and hex values, and then take a hexadecimal number and write down the binary and decimal numbers.

What I wanted to do is update that part of my presentation every year, but not really have to think about what numbers to put in with the homework assignment. So why not have Python generate everything for me!

Overall this is a really simple script, it starts out with a function that does all the heavy lifting:

def random_number_generator():
    ran_decimal = random.randint(1, 255)
    return (ran_decimal, bin(ran_decimal), hex(ran_decimal))

essentially this function generates a random decimal number from 1-255, and then returns the decimal value, along with the equivalent binary and hexidecimal values.

The second part of the script just takes the data from the function and writes it to a file. I wanted to write to a file instead of presenting the output to the screen, because it would be easier to copy and paste the values into my homework assignment.

The numbers_start and numbers_end values are optional for anyone else, I have them in there because the homework assignment is 40 problems.

Until next week!



Get every new post delivered to your Inbox.