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()
            newfile.write(oldfile_clean)
    return

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'))
    return

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!

https://github.com/CdtDelta/YOP


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!

https://github.com/CdtDelta/YOP


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!

https://github.com/CdtDelta/YOP


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!

https://github.com/CdtDelta/YOP


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!

https://github.com/CdtDelta/YOP


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!

https://github.com/CdtDelta/YOP


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 &quot;File exists&quot;
    config = ConfigObj(config_file)
    vxshare_no = int(config['last_vxshare_num'])
else:
    print &quot;File doesn't exist&quot;
    config = ConfigObj()
    config.filename = config_file
    config['last_vxshare_num'] = 0
    vxshare_no = int(config['last_vxshare_num'])
    config.write()

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!

https://github.com/CdtDelta/YOP




Follow

Get every new post delivered to your Inbox.