Hiding in White Text: Word Documents with Embedded Payloads

Published: 2016-07-06
Last Updated: 2016-07-11 17:31:25 UTC
by Johannes Ullrich (Version: 1)
1 comment(s)

This is a guest diary by Yaser Mansour. Due to the extensive use of images, please note that all the images are clickable to view them at full size. A PDF version of this diary is available here

Malicious macros in Office documents are not new, and several samples have been analyzed here at the ISC Diary website. Usually, the macro script is used to drop the second stage malware either by reaching to the internet or by extracting a binary embedded in the Office document itself. In this post, we will examine two similar malicious documents that were observed separately with each dropping a different malware sample, namely, NetWiredRC and iSpy.

There are several interesting facts about the samples we are going to analyze today:

  1. The macro embedded in the Office document does not reach to the internet. Instead, it extracts a binary embedded in the Word document itself in ASCII hex format and writes it to disk.
  2. Both malicious Word documents were observed separately. However, both use the same technique to extract the embedded binary as well as the same decoy message enticing the end user to enabled macros.
  3. During network forensics of the NetWiredRC malware, a new C&C command was observed which was not reported by [1][2]. This also resulted in a total of 9 custom Snort signatures being submitted and published in Snort Community Ruleset [3][4].
  4. The iSpy sample generated new network traffic patterns than what were observed previously. More about this in the following sections.

Brief History of NetWiredRC and iSpy Malware Samples

NetWiredRC RAT family has been extensively discussed by security researchers [1][2], and recently TALOS released Snort signatures to detect NetWiredRC over the network [3], and a new signature for the new NetWiredRC command[4].

iSpy was first observed by the author during January 2016 with the sample b33c5ba388f8a32006133cb8888a9370. This sample performed its C&C over HTTP as seen in the below screenshot and Snort signatures were released [4].

Picture 1

Other samples were observed during March and April 2016 (65ee535f0efcb30626ce5c8e7763e782 and cd3a43d3504925a396183b467b0980cb, respectively). Both of these samples also used HTTP for their C&C communication. One of the latest samples observed was extracted from the embedded payload in the Word document discussed in the remaining of this article. This recent sample performs its C&C over SMTP for initial and exfiltration communication as shown in the screenshots below.

Malicious Word Documents Analysis

Both malicious documents implement the same algorithm used to extract the embedded binary. While the focus will be on the malicious document embedding the NetWiredRC sample, we will attempt to provide side-by-side analysis of both malicious documents. Throughout the remaining of this post, comparative screenshots will have the first screenshot reflecting the analysis of the document dropping NetWiredRC while the second reflecting the iSpy sample.

Both samples documents have exactly the same decoy message enticing the unsuspicious user of disabling the protected view and enabling macros as seen in the below screenshot.

Interestingly each document consisted of a large number of “empty” pages with the only text visible as shown in the above screenshot. More accurately, the document consisted of 232. The second malicious Word document consisted of 528 pages.

The document was initially inspected for the presence of macros using oledump.py [5]. From the screenshots below, we can see that document indeed embeds a macro. The VBScript code was extracted using the oledump.py or olevba.py [6] can also be used. Both tools exist in the Remnux [7] image.


Closely inspecting the dumped and obfuscated VBScript, there were no indications that the script reaches to the internet. Going further through the code, there was an interesting function as shown in the below screenshot. Please note the highlighted variable and its data type as it plays a major role on how the embedded second stage binary is extracted from the Office document.

Continuing to inspect the script, it becomes apparent how the second stage binary is dropped to the local disk. The script leverages the Word Object Model [8] to access the Paragraph Object Members [9]. More about this later. On order to understand why the script would access paragraphs from the document itself, the document was opened while macros are disabled prevent the script from executing.

Scrolling through the document to inspect what these 232 pages contain showed only empty pages containing nothing, or did they? To verify, the document was zip extracted since it is an OOXML document. Extracting the document will also help in getting access to the internal structures of the document.  Once extracted, we end up with a set of XML files. We are interested in one file, in particular, the document.xml. This file contains the actual content of the document in XML representation.

An OOXML file contains element blocks representing the various content aspects of a document. For examples, how paragraphs in a word document are structured as XML [10]. In a nutshell, a paragraph is expressed with the XML element block . Text within a paragraph block is expressed by the XML element . Within the paragraph block, other XML elements may exist to represent things like formatting (). For more information about these elements, refer to the EMCA-376 Standard of the Office Open XML File Formats [11] and [12].

Back to our document.xml file, when viewed in a browser we notice that we have 24 paragraphs denoted by the element as we explained earlier. Inspecting and mapping the elements to the actual paragraphs in the document leads up to the fact that the last paragraph spans across the 232 pages. This paragraph not only contains text but also formats the text within the paragraph to be in white color (#FFFFFF) as a hiding technique from the viewer of the document.

So we have a VBScript that defines a variable as a paragraph and hidden paragraph that spans 232 pages. This indicates that the VBScript does in fact access the Word Object Model in order to reach to the paragraph. Inspecting the VBScript, we find evidence that the script indeed attempts to access the paragraphs objects and the text within which are included in the document. Specifically, the script has interest in paragraph number 24.

A bird’s-eye view of this segment of script suggests that the script loops through the paragraphs available within the document and the embedded text within until it reaches to paragraph 24. From its text, the script grabs 2 letters (or 1 sting hex byte, see below 2 screen shots), “un-hexifies” it o get the decimal/numerical representation using the Type Character “&H” (hS variable value) Hexadecimal Literal [13], and then hex xor it with hexadecimal key &HEE (0xEE) to produce hexadecimal bytes that serve a specific purpose. 

Let’s take the first two bytes from the below screenshot to test this logic. The first 2 string hex bytes are “A3 B4”. The below table breaks down the conversions performed by the script snippet above. Do you see anything familiar in the table? The two bytes “4D 5A” or “MZ” are the magic number of the DOS MZ executable.

Raw String Hex Byte Decimal Representation (&H) Decimal Representation (Xor 0xEE) Hex Representation
A3 163 77 0x4D
B4 180 90 0x5A

To automate this the above algorithm, the following python script was created. 

Once each byte is extracted and converted, it is written to disk byte-by-byte until there is no more text left in the paragraph. Afterward, the script calls a function passing the name of the just generated binary to execute it. The function uses the built-in function Shell() [14] to execute the second stage binary. The function is captured in the below screenshot.

To put everything together, the below screenshot represents the beautified and commented version of both functions discussed earlier.

The below screenshot represents the same “ParagraphRemove()” (beautified and commented ) from the second malicious Word, which dropped iSpy malware sample. An interesting note from both malicious Word documents is the “Startincex” misspell. 


[1] https://www.circl.lu/pub/tr-23/
[2] http://researchcenter.paloaltonetworks.com/2014/08/new-release-decrypting-netwire-c2-traffic/
[3] http://blog.snort.org/2016/03/snort-subscriber-rule-set-update-for_29.html
[4] http://blog.snort.org/2016/05/snort-subscriber-rule-set-update-for_31.html
[5] https://blog.didierstevens.com/programs/oledump-py/
[6] http://www.decalage.info/vba_tools
[7] https://remnux.org/
[8] https://msdn.microsoft.com/en-us/library/kw65a0we.aspx
[9] https://msdn.microsoft.com/en-us/library/office/ff839491.aspx
[10] http://officeopenxml.com/WPparagraph.php
[11] http://www.ecma-international.org/publications/standards/Ecma-376.htm
[12] https://msdn.microsoft.com/en-us/library/office/gg607163(v=office.14).aspx
[13] https://msdn.microsoft.com/en-us/library/s9cz43ek.aspx
[14] https://msdn.microsoft.com/en-us/library/xe736fyk(v=vs.90).aspx


1 comment(s)

Pentesters (and Attackers) Love Internet Connected Security Cameras!

Published: 2016-07-06
Last Updated: 2016-07-08 03:12:18 UTC
by Rob VandenBrink (Version: 1)
0 comment(s)

A recent story making the rounds in both the infosec and public press is the recent use of internet-connected security cameras as a base for DDOS attacks.  They don't have a lot of CPU, but they're linux platforms that are easily hackable, never get updated and usually have good bandwidth available to them.

This shouldn't come as any surprise to folks who are in the security business, or those who do any kind of a product eval before they plug new gear into their network.  I see security cameras on network assessments and penetration tests regularly.  A simple NMAP -sV scan (to show service versions) will typically light up a security camera as:

23/tcp    open  telnet      security DVR telnetd (many brands)
80/tcp    open  http        Boa HTTPd 0.94.14rc21
1025/tcp  open  NFS-or-IIS?
9000/tcp  open  tcpwrapped
56575/tcp open  unknown

The give-away is that Boa web server.  For some reason, security camera vendors seem to have standardized on this as their web service.  Or more likely, one vendor has, and they're selling the chipset to everyone else to put inside of their cases.

Let's take a look at that.  The Boa project has an active website (www.boa.org), and version 0.94.14rc21 is listed as the latest development release, complete with signatures.  Sounds great so far right?  Except when we look at the code, it was posted Feb 2005 (yikes!).  It looks like this project is no longer seeing active development (as of 11 years ago!).  So even if the vendor supplies updates and you apply them, there's no fixing the web portal that faces the network - and so often the public internet.

A quick google shows that this version of the web server is subject to a command injection vulnerability, as described in CVE-2009-4496. Exploit-db has an example curl one-liner that demonstrates this:  https://www.exploit-db.com/exploits/33504/ , vulndb has a larger write-up here: https://vuldb.com/?id.51542

Nessus has identified this remote code exec issue for years (plugin 47463).

Shodan identifies 936,736 of these servers on the public internet - because of course it's just too much trouble to VPN in to view the video footage on your ATMs or other physical assets

So a DDOS really is that simple.  Just using a curl script, you can start a "ping -t" or "ping -t -l 1000" against your victim (I picked 1000 just to prevent any packet loss due to fragmentation prevention).  With a few thousand camera devices, you have what the victim will perceive as a sophisticated DDOS attack.  Your curl string to attack a test "" ip address with default sized icmp echo requests would be:
curl -kis http://camera.public.ip.address/%1b%5d%32%3b%70%69%6e%67%20%2d%74%20%31%2e%31%2e%31%2e%31%07%0a

The first few characters are the escape sequence: %1b%5d%32%3b

The string "ping -t" is represented in hex as: 70%69%6e%67%20%2d%74%20%31%2e%31%2e%31%2e%31

The string terminates with: %07%0a

Wireshark catches the icmp echo requests (replies are filtered out) - yes, this did work first time for me:

That aside, what folks are missing in all of this is that these cameras are usually connected on the inside, trusted network, right there next to the servers.  Folks seem to find it too much trouble to make a DMZ for these things.  So the majority of these cameras make dandy pivots inbound to the customer's servers and workstations - your command string isn't restricted to "ping", you can run anything you want on the box (that the web service has rights too).  From the public internet, you could easily craft an inbound proxy or relay, giving you full access to the internal network - or at least long enough to establish a more "reliable" reverse shell or vpn solution.  Or just use teamviewer or logmein if you have that kind of access, you're less likely to trigger an IPS if you use the same tools that the IT group uses!

The remediation for this?  There are a number of things you can do, depending on your situation:

  • Scan your network, look for vulnerable services like this.  NMAP will do the job with some legwork, tools like Nessus or OpenVAS will make it easier and smack you with the proverbial "LOOK HERE" two-by-four.
  • Put vulnerable things that can't be fixed and can't easily be replaced (like these cameras) into a DMZ or a "jail" VLAN, and don't give that subnet access to anything on the inside network.
  • Restrict access to these cameras to VPN or internal access only (you can reach them, they can't reach you).
  • If you have a vendor monitoring your cameras, do the VPN thing with them also.  If you MUST give them direct access, only allow their IP or subnet.  (But also start looking for a different security monitoring vendor if you have to do this)
  • Most important of all, try to head this stuff off at the pass.  Scan new gear during the evaluation phase.  If it doesn't pass your assessment for some reason, phrase your report in business terms, outlining the real risks to the business.  You can't get buy-in from the folks who make these decisions by saying "No, but it's too complicated for me to explain it to you, just No.". 

As always, preventing these problems before they occur is the easiest way to deal with them.  You won't catch them all, but hopefully you'll catch things like this!

If you find one of these cameras on your network, please let us know in our comment section!  Or better yet, if you have a network-connected security camera that has a different web server, please share the server and version in our comments!

Rob VandenBrink

0 comment(s)

CryptXXX ransomware updated

Published: 2016-07-06
Last Updated: 2016-07-06 18:54:06 UTC
by Brad Duncan (Version: 1)
0 comment(s)


When generating exploit kit (EK) traffic earlier today, I noticed a change in post-infection activity on a Windows host infected with CryptXXX ransomware.  This happened after an infection caused by Neutrino EK triggered from the pseudoDarkleech campaign.

Shown above:  Flow chart for Neutrino EK/CryptXXX caused by pseudoDarkleech.

This morning, the decryption instructions for CryptXXX ransomware looked different.  A closer examination indicates CryptXXX has been updated.  As I write this, I haven't found anything online yet describing these recent changes, so this diary takes a quick look at the traffic.

Shown above:  An infected Windows desktop from earlier today.


Today's EK traffic was on using the same domain shadowing technique we've seen before from various campaigns using Neutrino EK (formerly using Angler EK [1, 2, 3] before Angler disappeared).  Post-infection traffic was over on TCP port 443 using custom encoding, a method CryptXXX has used since it first appeared earlier this year [4].

Shown above:  Traffic from today's Neutrino EK/CryptXXX infection filtered in Wireshark.

Below are some screenshots of the Neutrino EK traffic.

Shown above:  Neutrino EK landing page.

Shown above:  Neutrino EK sends a Flash exploit.

Shown above:  Neutrino EK sends the payload (it's encrypted).

In a change of behavior, text and HTML files for the CryptXXX decryption instructions are downloaded in the clear during the post-infection traffic.

Shown above:  Text-based decryption instructions sent on over TCP port 443.

Shown above:  HTML-based decryption instructions sent on over TCP port 443.

I used my Security Onion setup to see what Snort-based alerts triggered.  Looks like the EmergingThreats team already has a signature covering the new CryptXXX post-infection traffic.

Shown above:  My results from Sguil on Security Onion using the ET Pro ruleset.

Below are two screenshots with HTML decryption instructions from the infected Windows host's desktop.

Final words

Although I haven't noticed anything yet, I'm sure some of the usual sources will have a more in-depth article on these recent changes in CryptXXX ransomware.  This diary is just meant to give everyone a heads-up.

Pcap and malware for this diary are located here.

Brad Duncan
brad [at] malware-traffic-analysis.net


[1] http://blogs.cisco.com/security/talos/angler-domain-shadowing
[2] https://blog.malwarebytes.com/threat-analysis/2015/04/domain-shadowing-with-a-twist/
[3] https://www.proofpoint.com/us/threat-insight/post/The-Shadow-Knows
[4] https://www.proofpoint.com/us/threat-insight/post/cryptxxx-new-ransomware-actors-behind-reveton-dropping-angler

0 comment(s)
ISC Stormcast For Wednesday, July 6th 2016 http://isc.sans.edu/podcastdetail.html?id=5069


Diary Archives