Hello Reader!

This weeks script is brought to you by MIcrosoft’s Patch Tuesday, and the MS15-034 fix that came out this month…

So we started looking at what systems we needed to patch for this vulnerability, and I started to think about some of the programs that are on the servers I use that don’t use a standard port 80 web server connection.  Some of the software I use on my systems (both forensic and from the server manufacturer) have some type of web front end, but they use odd numbered ports.  So I was thinking of a quick way that I could figure out which systems might be vulnerable, including ones that I didn’t know there was any type of web service on.

I was reading this SANS Diary post about MS15-034, which included a method of just checking for the vulnerability, and thought it would make a great YOP post for this week.

Now there is a pre-requisite for this script in order for it to run, you’ll need to install the Requests module.  I may re-write this script at a later point to use urllib, but I prefer using Requests for any web based stuff.

Basically you can feed this script a list of servers/IP addresses, and then specify an output file to write your results too.

The first thing I did in this script is define the request I wanted to send, along with a range of ports to check (in this case all of them):

headers = {'host':'ms15034', 'range': 'bytes=0-18446744073709551615'}
tcp_ports = range(1,65536)

But the following code:

with open(args.server_list, "r") as servers_to_check:
    for ms15_034_server in servers_to_check.readlines():
        for ports in tcp_ports:
                url = 'http://' + ms15_034_server.rstrip() + ':' + str(ports)
                print "Checking: {}...".format(url)
                ms15_034_check = http_check.get(url, headers = headers)
                ms15_output[str(ports)] = ms15_034_check.status_code
        for key, value in sorted(ms15_output.iteritems()):
            ms15_output_file.writelines("Server: {}\tPort: {}\tResult: {}".format(ms15_034_server, key, value))

Does most of the heavy lifting.  Here I start by cycling through the ports, informing the user which URL and port I’m checking (I’ll explain why in a bit).  When it finds an open port, it sends the headers I defined to see if it gets a response.  Then, it takes that response and puts it into a dictionary by port and then the HTTP response (if there is one).  When it’s finished cycling through all the ports, it writes the dictionary data to a file, and then moves on to the next server in the list.

Now there is a small bug in the code that I’m still trying to nail down, that’s inconsistent.  In some cases the script will hang on a port, and then only way to get it to continue is to do a Ctrl-C (which makes it move on to the next port).  I’m not quite sure why this is happening yet, because sometimes it will just hang on an open port longer than others.  So sometimes I’m just having to wait for it to move on, otherwise I need to help it along.

Until next week!


(EDIT: Thanks to Willi Ballenthin for suggesting the timeout parameter in the ms15_034_check line.  That appears to have fixed the hanging issue and I’ve updated the code on the site.)

Hello Readers!

This week I’m taking a trip back to the past a bit (for me anyway).  Originally I was planning on publishing some code that worked with IMAP and webmail accounts, however I ran out of time in getting the code in a working state.  My plan is still to publish it during this Year of Python.  I’m looking for it to do a specific task with the Spam folder, but I don’t want to say much more than that now.

However, if you want to see an excellent write up on using Python and IMAP/email, check out this post from the System Forensics Blog.

Now this particular piece of code this week I used a long time ago for a case I was working on.  At the time I was going through some Apache log files, and I needed to verify two types of log entries.  One was if a hashed password was being included in the URL string, and then the second was to decode some %xx characters in other URL entries (ex %2f).  At the time I was hoping to automate the process a bit better for my workflow, but the reality of time stepped in, so I turned it into a menu that would just prompt me for what I wanted to do.

Which is all in this piece of code:

while quit_prog:
    choice = raw_input("Choose md5 or url (type quit to exit): ")
    if choice.lower() == "md5":
        enter_md5 = raw_input("Enter the text to convert to md5: ")
        print create_md5(enter_md5)
    elif choice.lower() == "url":
        enter_url = raw_input("Enter the url text to convert: ")
        print decode_url(enter_url)
    elif choice.lower() == "quit":
        quit_prog = False

The code is rather simple.  I just set it up to prompt me if I was decoding and MD5, or a URL.  After that I would just copy/paste what I wanted to decode.  At that point the script would just run the corresponding function, and either generate the MD5 hash from the text I put in, or decode the special characters in the URL.

And that’s it!  Again this was one of these programs I designed to satisfy a need at the time, but it worked.  Moving forward I would probably look at just feeding in the Apache logs and then outputting the decoded data.  That will be version 2.0!

Until next time!


Hello Reader!

This weeks script comes out of some playing around I was doing with sqlite databases.  In the class I teach, we were talking about Mozilla Firefox artifacts, along with Google Analytics Cookies.  While I was talking about the different types of utm* cookies that are present, I thought about writing a quick script to parse some of the data in a __utmz cookie.

Now there are other people that have worked with Google Analytic Cookies, including Mari DeGrazia who wrote a very nice program to parse Cookie files, but I was looking for something that would let me play around with some different python concepts.

First was of course just connecting to a sqlite database and running a query against it.  Next was taking those results and processing the data.  Finally just playing around a bit more with python functions to convert an integer to a date/time stamp (or in this case just a time stamp).

So first we have a simple function to handle the timestamp:

def unixtime(timevalue):
    return datetime.datetime.utcfromtimestamp(int(timevalue))

Now there’s a simpler way to handle formatting with the python datetime module, but I wanted to put it in to a function just to practice utilizing them.

Next we have the section that just opens the database and connects to it:

    db_connect = sqlite3.connect(cookies_db)
    db_cursor = db_connect.cursor()
    db_cursor.execute('SELECT * FROM moz_cookies WHERE name = "__utmz"')
    db_row = db_cursor.fetchall()
except Exception, error:
    print error

Here I just wanted to set up some error checking when I open the database and do my specific select statement.  Basically if it works, great, if it doesn’t print the error saying why.

Finally we just pull out the data we want, and print it to the screen:

for rows in db_row:
    utmz = rows[5]
    utmz_segment = utmz.split(".")
    cookie_last_time = unixtime(utmz_segment[1])
    print "Domain: {}\t\t\tLast Visit: {}:{}:{}\t\tNo of sessions: {}".format(rows[1], cookie_last_time.hour, cookie_last_time.minute, cookie_last_time.second, utmz_segment[3])

And that’s it.  Just a real simple script to parse out the data quickly and look it over if necessary.

Until next week!


Hello Reader!

This weeks piece of code is actually a script I’m preparing to run at a later date.  I have some data on a system at work that I’m looking to move to our SAN.  The end goal is consolidating some files that all belong to the same category.  However because of the nature of the data, I need to make sure the contents remain unchanged from point A to point B.  Now there are some tools out there (SafeCopy is a favorite of mine) that will copy files form one place to another, and MD5 hash the source and destination file…

But this is YOP, so we must figure out how to do the same thing in Python!!!!

Now this script assumes the files have already been copied, I haven’t written the code to do that part yet.  But essentially what you do is feed it a source and destination directory, then it will traverse both locations (including subfolders), and MD5 hash all the files located in those directories.  Finally, it writes the filename and it’s corresponding hash to an output file so you have an audit log of the end result.

It was interesting working on this script.  When I started writing it earlier this week, I really just needed to look up the hashlib library code.  The rest of the code I was familiar with from other code I’ve written so far as part of this project.  So I was pleased that it seemed to be a bit easier to code then when I started this endeavor.

And then I got to testing the code to make sure it would work, and got knocked back down a few steps….first, and I think this is a common mistake for people new to the hashlib library, I realized I was not actually hashing the contents of the file in both locations, but the file name itself.  A few Google searches later (along with some Stack Overflow), and I figured out what I needed to do.

My second problem came up with traversing through the directories.  What I discovered is you need to reassemble the path to the file along with the file name.  Otherwise Python returns a file not found error.  Ironically this problem took me longer to figure out than the MD5 hashing issue.

In the end, I ended up with this piece of code:

for path, subdirs, files in os.walk(args.source_dir):
    for name in files:
        hash_filepath = os.path.join(path, name)
        with open((hash_filepath), "rb") as file_to_hash:
            md5_buff = file_to_hash.read()
            md5_returned = hashlib.md5(md5_buff).hexdigest()
        source_file_list[name] = md5_returned

Now I know I can turn this into a function, since I’m running the code twice.  That’s a plan for a later date.  I’ve also added some code that’s not included here to inform the user which files matched.  I’m still tweaking that part of the code so it wasn’t ready for this week.  But I’m hoping to add it in as an additional part of the output audit file.

Until next time!

Hello reader!

This weeks script is a rather simple one.  As you may or may not know there’s some malware floating around the Internet that uses Office documents as its initial “lure” to the reader.  I’m sure most of you could look through your spam mail of your <insert free webmail service here> account and see plenty of examples of what I’m talking about.  Subjects like “Invoice ID”, “Payment Collection”, or “Debt Collection”, all with a nice little Office Icon’d attachment included for you to open.  And if you open the attachment…well bad things my happen.

Dider Stevens has a python program called oledump that can normally parse these files.  And in doing so give you a look in to what else the files may be doing.  Lately it appears that there’s a cat and mouse game going on.  Dider updates his took to parse the latest variant of these malware attachments, and then the malware author changes tactics slightly so the script doesn’t work anymore.  And then Dider updates his oledump program to account for the change….rinse, lather, and repeat….

So normally I use his oledump program to look at these files.  Mainly to get an idea of what exe they are trying to download (there’s always another exe involved).  But there have been times where oledump hasn’t been updated yet, and I get some new version of this malware document.  Since (for me) Google is pretty quick on noticing these things as having a virus in them, I like to download them to my linux machine as soon as I can to examine them.

Now these files you can actually open up in a text editor to see the content.  And when you do you’ll see a base64 encoded string (the newer variants now have two of them).  However it’s not one long string, it broken up over many lines, and I wanted to come up with a way copy out the base64 encoded part to a file, recombine it into one line, and then decode it.

Which leads us to this weeks YOP entry…It’s basically two functions that I wrote.  The first:

def fix_file(filename):
    with open(filename, "r") as oldfile:
        with open(args.output_file, "w") as newfile:
            for oldfile_line in oldfile:
            oldfile_clean = oldfile_line.rstrip()

Just takes the base64 encoded text I copied and pasted into a new file, and turns it into one long base64 encoded string.  Then it writes that new string to a new file.  The next function:

def decode_base64(filename):
    with open(filename, "r") as file_to_decode:
        with open(args.base64_file, "w") as decoded_file:
            base64_decode = file_to_decode.read()
            decoded_file.write(base64_decode.decode('base64', 'strict'))

Takes the output file from the first function, base64 decodes it, then writes it to yet another new file.

Once that’s done, you can run strings against it, load it up into a hex editor, or whatever you want to do with it.  Now I know I could just feed everything through without writing the intermediate output file (from the first function), but I wanted to practice using file handles, and it’s a good way for me to troubleshoot any issues.

Until next week!


Hello reader!

This week I’m changing gears a bit.  This week I’ve been playing around with kicking off other programs using Python.  So I did some reading about the subprocess module.

On a few occasions I’ve had to work with drive images from OS X systems.  And a lot of them have been encrypted with File Vault (which is a good practice).  However most forensic tools can not decrypt FV images, which means we need to find an alternate method of getting the image to a “readable” state.  Enter libfvde….

libfvde (https://github.com/libyal/libfvde) is a set of “library and tools to access FileVault Drive Encryption (FVDE) encrypted volumes,” created by Joachim Metz.  The library currently doesn’t have python bindings, but it is on Joachim’s TODO list.

The critical component with using libfvde is having the File Vault Recovery Key from the system.  Unfortunately you only have the opportunity to record the Recovery Key when you kick off the encryption process.  The key is not recorded anywhere on the system.  The key is six sets of four alphanumeric characters (ex: 35AJ-AC98-TI1H-N4M3-HDUQ-UQFG).

So what happens if you don’t have the recovery key?

That’s what this weeks script is designed to do, brute force the Recovery Key to get the encrypted image mounted with fvdemount (the program that actually mounts the image on to the system).

Now the key to this program is the following code:

def fvde_key():
    chars = string.letters.upper() + string.digits
    pwdSize = 4
    key_attempt = ''.join((random.choice(chars)) for x in range(pwdSize))
    return key_attempt

This is the part of the code that generates the random 4 character string to use in the larger recovery key code.

Then, we need to assemble the entire recovery key from this function, which is done with this line of code:

decryption_key = "-".join([fvde_key(),fvde_key(),fvde_key(),fvde_key(),fvde_key(),fvde_key()])

The rest of the code goes through a loop which generates a decryption key, and then plugs in into a command line program to try and mount the file vault image.  If it is successful, it mounts the image and prints out what the correct recovery key was.  If it fails, it simply tries a new code.

Mind you this code is not optimized for any type of speed or performance….

Until next week!


Hello Reader!

Well we’ve hit week ten, and this will be the third VBR script in this “mini series”.  This time I’ve written a snippet of code that will parse an NTFS VBR.

Again the code overall follows the same basic structure as the FAT VBR’s, but NTFS has some different structure once you get 32 bytes into it…

For example, the total number of sectors in a VBR is an eight byte value, versus a four byte value.  Another difference is at sector offset 48 for eight bytes is the sector address of the $MFT, which is an important system file on an NTFS file system.

The overall idea for this larger program would be able to point it at a disk image (or even a disk if you want) and the program would parse out the master boot record, follow the partition settings to the location of the start of each partition, and then parse the VBR’s of each of those partitions.  I might even stretch it further and if it’s an NTFS file system, locate the $MFT file and parse that out as well.  However for the $MFT I’ll probably just incorporate analyzeMFT as a module and parse the file using that.

Until next week!



Get every new post delivered to your Inbox.