Monday, January 12, 2015

Happy New Year and a CTF Challenge Write-Up

Happy New Year!!!

I'd like to start the first blog post of 2015 by wishing the 7 people who read this blog a Happy New Year! As a new year's resolution, I am challenging myself to write at LEAST one (1) blog post per month. We'll see how well it goes. Without further ado, here is January's.

In December, two people (@akiym and @xrekkusu) put together an Advent Calendar Capture The Flag competition (ADCTF). This was an awesome and unique CTF where every day in December, a small challenge was released. I was able to complete a couple of these challenges, but wanted to take some time to do a write up on my favorite one.

Before we get into it, a quick disclaimer: I will be posting a solution. According to the rules of the CTF this is not allowed. Therefore, I waited awhile (over two weeks after the challenge ended) to post this solution. I don't agree with the rule of NEVER releasing a write up. Therefore, as someone who personally identifies as a pirate, I scoff at rules. ARRRGGGGGHHHHHH. 

A lot of people, including myself learn the most from the trying and failing process, but eventually we all need a hand. So in the spirit of that, I will try and keep the write up linear in the sense that, if you need a hint, just keep reading until you get to the part where you are stuck, get a hint or two and then stop reading and continue trying. 

If it wasn't clear enough .... 




Okay, fair warnings aside let's get into the challenge. This was the Day 9 PPC Challenge dubed "qrgarden".

Apart from the lacking hint of "read a lot" there is a png file:

It is hard to see, since it is compressed down, but what you are looking at is 10,000 QR codes. 100 x 100. I know it is 10k QR codes for two reasons:

    1) I measured the size of 1 QR code in a graphics program
    2) I saw this tweet:

So based on the clues, the challenge consists of reading every, single, last, QR code and finding the one that starts with "ADCTF_"

If for some reason, you can get the png file from the CTF website, I've mirrored it on my GitHub here:

So, how do we read 10k QR codes? The way I thought of doing it was pretty simple. I will leverage Python, the Python Imaging Library (PIL) to slice the image into individual QR codes and then use the python qrtools library to read each one. 

Step 1: Slice and Dice

In order to read each QR code, we need to slice and dice this big png into individual QR codes. The first thing I did was to determine how big each code was.

While in my Kali Linux VM, I used the file program on the image and got 8700 x 8700 pixels as the size in pixels which means each QR code is 87x87 pixels.

The process I took was to slice the large png HORIZONTALLY into 100 new images each being 1 qr code high by 100 qr codes wide. Then for each of the horizontal strips, to dice each of those new 100 images VERTICALLY into single QR codes.

I wrote the below function called slice_and_dice() to do just that. I assume you could use this any time you needed to slice and dice something into squares. This tool will save each single qr code to a directory of your choice.

I have also posted this in GitHub:

1:  from PIL import Image  
2:  import math  
3:  import os  
5:  def slice_and_dice(img_path, output_dir, horizontal_size, vertical_size):  
6:   #set statistics  
7:   total_h_slices = 0  
8:   total_v_slices = 0  
9:   total_s_slices = 0  
11:   filename = os.path.split(img_path)[1]  
12:   img =   
14:   #get image size, and the starting points  
15:   h_width, h_height = img.size   
16:   h_upper = 0   
17:   h_left = 0  
19:   # get how many horiztonal slices to make  
20:   h_slices = int(math.ceil(h_height/horizontal_size))   
22:   #make the horizonal slice  
23:   for row_count in range(1,h_slices+1):  
24:    h_lower = int(row_count * horizontal_size)   
25:    h_bounding = (h_left, h_upper, h_width, h_lower)  
26:    horizontal_slice = img.crop(h_bounding)  
27:    # increment the upper boundry     
28:    h_upper += horizontal_size   
29:    print "Made horizontal slice #"+str(row_count)  
30:    total_h_slices += 1  
32:    # slice the horizontal slice vertically into singles  
33:    v_width, v_height = horizontal_slice.size  
34:    v_upper = 0  
35:    v_left = 0  
36:    v_lower = v_height  
37:    v_slices = int(math.ceil(v_width/vertical_size))  
39:    for column_count in range(1, v_slices+1):  
40:     v_width = int(column_count * vertical_size)     
41:     v_bounding = (v_left, v_upper, v_width, v_lower)  
42:     single_slice = horizontal_slice.crop(v_bounding)  
43:     v_left += vertical_size  
44:     print "Made vertical slice #" + str(column_count)  
45:     total_v_slices += 1  
47:     #save the single slice  
48:, filename +"_row" + str(row_count) +"_column" + str(column_count)+".png"))  
49:     print "Saved slice: " + filename +"_row" + str(row_count) +"_column" + str(column_count)+".png"+ str(column_count)  
50:     total_s_slices += 1  
52:   #print the stats  
53:   print "Total Horizontal Slices Made:", str(total_h_slices)  
54:   print "Total Vertical Slices Made:", str(total_v_slices)  
55:   print "Total Slices Saved:", str(total_s_slices)  
57:  slice_and_dice("qrgarden.png", 'output/', 87, 87)  

So this worked out very well and provided me with 10,000 individual QR codes ...

Step 2: Read all the QR codes

Suddenly, reading all the QR codes doesn't seem so daunting. To make life easier I used a python library called qrtools. The script I wrote will take a directory and a search term and decode all the QR codes in that directory while searching for the search term provided. This code is also on my GitHub at:

1:  import os  
2:  import qrtools  
4:  def read_qr_codes(directory, search_term, verbose=True):  
5:    # initalize a list for holding our hits  
6:    matches = []  
8:    # for each qr image in the directory ....  
9:    for f in os.listdir(directory):  
10:      img_path = os.path.join(directory, f)  
11:      code = qrtools.QR(filename=img_path)  
12:      # check if we can decode the image  
13:      if code.decode():  
14:        # convert the code to a string  
15:        code_value = code.data_to_string()  
16:        # if verbose is toggled, output the qr code values  
17:        if verbose: print img_path + ", " + code_value  
19:        #if we find the search term add it to the matches list  
20:        if search_term in code_value:  
21:          matches.append({img_path: str(code_value)})  
22:      else:  
23:        print "Could not decode:", img_path  
25:    #print all the matches  
26:    print len(matches), "match(es) were found:"  
27:    for finding in matches:  
28:      for key in finding:  
29:        print key + ', ' + finding[key]  
31:  read_qr_codes('/root/Desktop/day9/output','ADCTF_', False)  

After running this, I had my flag and this challenge was completed:

Step 3: PROFIT!

I blurred the answer out so at a minimum you at LEAST had to copy and paste the code to complete the challenge.

I hope you enjoyed this small write up and code. Please leave a comment if you found this helpful or were able to use it to solve a different CTF or challenge!

Saturday, December 6, 2014

Moar Steamed Phish

I got another Steam phishing message from our same friend. See my last blog post HERE for more details.

Anyhow, the first thing I noticed is account changed their name from Rainstone to [unassigned] and the message is a bit different this time:

Same well done Steam profiles as before:

And the same vector to steal credentials via the Add Friend which requires you to "Sign In":

Before we jump to the malware -- let's check out this domain ( real quick. If you remember from the last blog, this domain was in the list of domains registered with the e-mail address. I checked to see if he has added any more domains, but there is still the list of 21 domains from the last time we checked:
3. <-- This was used in the last blog post
8. <-- This is the new one

'Ol Ivan is keeping plenty busy! Now let's get back to the malware which is the reason for this new post.

The first thing I noticed was they used a new icon in the download prompt:

So they went from the really good looking logo to one that looks more like ass. Oh well.

Here are the file details:
File:     SteamGuard.exe
Size:     229376
MD5:      D18C0C6E73DB25C8D29EF7DF0EE71AB1
Compiled: Sat, Dec 6 2014, 10:10:22  - 32 Bit .NET EXE

PEiD: Microsoft Visual C# / Basic .NET
DNiD: SmartAssembly v6.X -> RedGate

Redgate's SmartAssembly is .NET obfuscate:

Lastly, lets check the compiled date:
TimeDateStamp: 0x5482D60E (Sat Dec 06 05:10:22 2014)
Pretty new!

They are still hosting this malware using their Google Docs account. You can download a copy yourself at (defanged):

If time passes and it disappears and you would like a copy, please tweet at me @JC_SoCal and I will get you a copy.

Nothing on VirusTotal for that hash as I write this (I'll upload it once I'm done).

Using Marc Ochsenmeier's tool PEStudio I check the exe file. The version info is COMPLETELY different than the previous malware they were hosting:

Since its .NET and obfuscated, I used de4dot to de-obfuscate the SmartAssembly.  Now I can read the .NET code in ilspy easily. and with that ... I am out of time. The rest of the analysis will have to continue later.

Monday, December 1, 2014

Steam Phish and Broken Malware

When I have free time, I like to try and add to this blog. I also like to play some online games. Lucky for me, I get to do both. Most of my games are on Steam, and to be honest it makes my life easier when I want to play with friends. It would appear that Steam makes malware distribution easier as well! Take for instance this phishing message I received through the Steam chat system:

To the average young player this looks fairly legit. A few things caught my eye, and I'll admit, the first of them was how they insisted I could use any browser. Who would care? Then I noticed the malformed domain: ... nice. The page actually had a well done Steam user profile:

When you tried to click Add Friend, it brought you to a login page which is pretty normal, especially for me. Most users are only logged into the Steam application and not the actual website.

So they are obviously harvesting usernames and passwords. Which should be enough for offloading expensive in game items like gun-skins for Counter Strike ... BUT WAIT! There's more!

This is a somewhat familiar message box, where Steam will actually require a code sent to your e-mail address on file in order to continue the login. However, it has been changed from requiring a code, to downloading SteamGuard.exe. How thoughtful.

Before we jump into the malware, lets take a look at the registrar information on this domain:

Domain name:
Domain idn name:
Status: clientTransferProhibited
Registry Domain ID:
Registrar WHOIS Server:
Registrar URL:
Registrar URL:
Registrar URL:
Updated Date: 2014-11-29
Creation Date: 2014-11-29T12:24:10Z
Registrar Registration Expiration Date: 2015-11-29
Registrar: Domain names registrar REG.RU LLC
Registrar IANA ID: 1606
Registrar Abuse Contact Email: 
Registrar Abuse Contact Phone: +7.4955801111
Registry Registrant ID:
Registrant Name: Ivan Ivanov
Registrant Organization: Private Person
Registrant Street: Koshil 23
Registrant City: Horts
Registrant State/Province: Tehas
Registrant Postal Code: 123170
Registrant Country: RU
Registrant Phone: +38021312312
Registrant Phone Ext:
Registrant Fax: 
Registrant Fax Ext:
Registrant Email:
Registry Admin ID:
Admin Name: Ivan Ivanov
Admin Organization: Private Person
Admin Street: Koshil 23
Admin City: Horts
Admin State/Province: Tehas
Admin Postal Code: 123170
Admin Country: RU
Admin Phone: +38021312312
Admin Phone Ext:
Admin Fax: 
Admin Fax Ext:
Admin Email:
Registry Tech ID:
Tech Name: Ivan Ivanov
Tech Organization: Private Person
Tech Street: Koshil 23
Tech City: Horts
Tech State/Province: Tehas
Tech Postal Code: 123170
Tech Country: RU
Tech Phone: +38021312312
Tech Phone Ext:
Tech Fax: 
Tech Fax Ext:
Tech Email:
Name Server: 
Name Server: 
DNSSEC: Unsigned

According to, this domain is registered to Mr. Ivan Ivanov in Russia. Ivan Ivanov is the US equivlent of John Smith, so I'll venture a guess that this is a fake name. Also according to, our friend Ivanov has a few other domains:
3. << Here's ours!

These all appear recently registered within the last month (November). This should be a pretty active campaign.

Okay, back to the malware!
File:     SteamGuard.exe
Size:     285184
MD5:      3D6FDC70E43D258FA30AC4687F4306CA
Compiled: Sun, Nov 30 2014, 13:47:44  - 32 Bit .NET EXE

Wow! Look at that compile time! That's some fresh malware.

Too bad it's busted and doesn't execute and I am out of time for messing with this. I tried to de-compile it as well and it is all in Chinese and I really don't have time for this. =(

At least they were festive when naming the resource in English.

If you want a copy, you can download it from the attackers link (defanged):


Well, that didn't take long. Rainstorm is back with another friend that needs to talk to me:

Looks like the same old same old with this cat, but wait. THERE'S MORE!!!!!! Another new domain that we didn't have in our original list ... let's check it out:

This time, they go by Maks Georgevich, with the email Feeding this back into whoismind shows that they only have one domain registered ( 

I know what your thinking -- maybe they fixed the malware? Let's check.

The website looks similar, but a new profile:

And the same shenanigans -- add a friend, log in, steal credentials and download our malware. Let's skip to the malware.

File:     SteamGuard.exe
Size:     285184
MD5:      3D6FDC70E43D258FA30AC4687F4306CA
Compiled: Sun, Nov 30 2014, 13:47:44  - 32 Bit .NET EXE

BOOOOOO! It's the same busted ass malware. Since they are harvesting credentials, if I get bored over the weekend I'll write a script to give them credentials ... =)

Saturday, April 12, 2014

Never enough time ... and an API for Fog

My goal is to blog at LEAST once a month. I missed March and I'm sorry to anyone that tries to get anything useful out of this blog. There is never enough time! I'll try harder.

Anyhow, COMPLETELY unrelated at the moment to security and on the topic of system administration, I am a huge fan of the FOG Project which is a free computer cloning solution. Think of Norton Ghost. However, I personally like this much better!

There is one issue (which is the reason for this blog post) that I have with FOG. They only have a web UI interface. This makes it a pain for automating tasks. So, I started making my first Python API for public consumption. I announced it on the FOG forum here:

and the python code is here:

Even though there is not a lot of functionality, I'm doing my best to keep this API professional and clean so that I can continue developing it and it benefits the FOG user community. This is my little way of giving back to their awesome project.

Thanks for reading,
April blog post, check in the box!

Monday, February 10, 2014

The Adobe password breach crossword ...

I thought I would mention here that I revisited the adobe password breach and wrote a blog which was posted at 6Labs. The blog discusses how you can recover the password from the adobe breach data and then if the user was employing password reuse you could access their accounts like email, facebook or possibly even corproate accoutns.  Check it out:

Revisiting the Adobe Password Breach & the Risk to Your Network

Monday, November 18, 2013

ASLR Woes for Malware Analysts using Windows 7

For those of us that have made the move from XP to 7 for their malware analysis, you may have noticed that when trying to use IDA Pro and Olly or another debugger that the virtual addresses are not matching. This is because Windows 7 ships with Address space layout randomization (ASLR) enabled.

We can use Microsoft's Enhanced Mitigation Experience Toolkit to easily toggle ASLR on and off with a reboot. This way you don't have to make any manual registry settings and you can also control DEP, SEHOP and Certificate Trust if you need to.

You can download EMET 4.1 here:

To disable ASLR:

Simply select the drop down next so ASLR and choose disable. You will need to reboot after that.

Sunday, November 3, 2013

Snazzy Windows Context Menu for Malware Analysis

One thing I like to do is save time. I am sure a lot of other people do as well. Malware Analysis is no exception to the rule. With that being said, I have found having my go-to programs in a handy context menu saves a bit of tedious clicking. Below is a screen shot of the menu I made that shows all my tools.

It was a little tricky tweaking the registry to do this, but I feel like I have it down well enough to explain it. So here goes:

Step 0: Warning

Backup your registry, take a snapshot of your VM, or do what ever it is you do in case you break your box doing this. Tweaking the Registry is always dangerous. Also, some words need to be exact. Windows uses conventions over configurations to know what's what in the registry. So don't be lazy or it won't work.

Step 0.5:

Open up the windows registry editor: regedit.exe

Step 1:

To create the cascading Malware Analysis menu navigate to the following key:

Right click on shell and select:
New > Key

For this tutorial we will name it DemoMenu

Right click and select:
New > String Value

Name the new value MUIVerb (this must be exact) and set the value to whatever you want the cascade menu to say, this will be:
Cascade Menu

Warning: Do not edit or modify the one titled (Default)

Right click on DemoMenu and make another String Value. Name this one SubCommands (this must be exact). This is not where we name them, but it is how the menu calls them. Keep the names short and descriptive with no spaces. Use a semicolon to delimit the items. If you would like a divider line put a | (pipe) character in there. Here is a sample for the demo:

If you did it correctly -- yours should look like this:

Step 2:

Step 2 will need to be repeated for each item you put in SubCommands.

Browse to the following key:

This is where we will create the command for each item.

Right click on shell and select:
New > Key

Name the key the exact same as the first item in our SubCommands data. For this example it is DemoNotepad

Edit the data in the (Default) value. Put whatever you want this command to be called in your menu. For this tutorial we'll just call it Notepad

Right click on the key we made (DemoNotepad) and select:
New > Key

Name this key:
command (this needs to be exact)

Double click on the (Default) value in the command key.

Enter the path of the program we want. For the notepad example we use: "C:\windows\system32\notepad.exe" "%1"
(Mind the quotes and spaces)

We also added a %1 at the end of the command. This is essentially argument 1 but what this will do is reference the file path we are right clicking on so the program knows we want to open that file.

Pro-Tip: If the path to your program contains spaces such as C:\Program Files\blahblah make sure to put the path in double quotes "  ". Since we don't have any clue what we may right click on and if that path has spaces, we put %1 in quotes.

If you did it correctly -- yours should look like this:

Showing the data for DemoNotepad

Showing the data for command

Step 3:

Repeat Step 2 for each item in SubCommands.

I added another for DemoWordpad. Here is a screen shot below:

Step 4: Profit

Now you have an awesome context menu you can save time with:

To save myself time, I turned my context menu registry tweaks into a .reg script. Here is the link to it on github:

Please feel free to send me questions/comments/concerns or suggestions on here or on twitter @JC_SoCal