Friday, 11 September 2015

How to fail at ransomware


Ransomware sucks. It is annoying and persistent, and apparently very lucrative. For this reason alone we can expect, and indeed find, that even the unskilled will try their hand at developing a ransomware payload. What better low-cost-of-entry method than powershell.  The only problem is (at least for the samples described below) that using deterministic symmetric encryption sorta, well, renders the entire encryption process trivially reversible...


I had originally been taking a look at this CHM dropper [md5: 21e1a87bd0418381a1bc8df088ee5c91] which carries out a download and execute of a powershell based "ransomware" script [md5: be03eb109cab04a1a70b5bbc7b22949e].

The download and execute from the CHM:

CHM dropper referencing

Colorful domain names notwithstanding, we can see the simplicity here. Looking at the actual ransomware script reveals a very basic .Net approach to enumerating all drives on the system, and then systematically recursing for a laundry list of various file extensions.  Each matching file is then sent through the encryption routine.

I have cleaned up some of the variable names for legibility here, but obfuscation can't really mask the issues with this one.

In a more legitimate attempt to effect a crypto based ransomware ploy, one would need to encrypt the victim data asymmetrically.  There a few reasonable ways to go about this, but unfortunately the author of this script decided to go another way entirely - the way which uses symmetric encryption with a completely deterministic key and IV.

I had originally written a simple decryption script for this corresponding Powershell encryption script, but after re-checking the download site after a couple of days it does appear that the script was/is being modified (reference md5: 9fe45fc4c402932248cd2c26b65f883d). The modification or revision process has not improved the overall sophistication of the encryption however, but has merely modified the salt value being used to generate the Rijndael encryption key. I updated my decryption script (link at bottom) to accommodate a user - supplied salt value which can be extracted from line 7 of  the original encryption script [see update below]:

Another interesting change is that the 'decryption instructions' HTML file that gets written to the victims' hard drive has been completely redesigned and is an obvious style ripoff of the Cryptolocker ransom instruction page:

Original decryption instructions from be03eb109cab04a1a70b5bbc7b22949e

New version from 9fe45fc4c402932248cd2c26b65f883d

These instruction files also reference an ID# which is obviously supposed to lend support to the fact that there is some asymmetric encryption taking place which requires a specific private key to decrypt.  It is possible that this ID is somehow deterministic, although it is definitely not machine based - I tried downloading the script from multiple different IP addresses using different operating systems on a single day and received an identical copy of the script having the same ID# each time.  It may be date based, and I will update this post with any additional information that comes out of future checks.

Why you never pay the ransom

Further examination of the encryption script shows that any files less than 42871 bytes in size will be encrypted in their entirety, but those above or equal to this size will have only the first 42871 bytes encrypted.  

I would almost pay the ransom value just to know why the author chose this arbitrary seeming value of 42871 bytes.  The net result of this choice, combined with the 128 bit block size and choice of zero padding is that for any file of 42871 or more bytes, the original file will have 9 bytes of unrecoverable data. 

Whenever the file length is 42871 or more bytes, the encryption will read in the first 42871 bytes, encrypt them and pad out to the next 16 byte (128 bit) boundary which happens to be 42880 bytes. The destructive flaw in the script is that the original file is overwritten in place - thus bytes at offsets 42872 to 42880 are overwritten with the padded bytes.  Upon decryption these bytes cannot be recovered as they were not encrypted originally but simply overwritten. 

Thus - even if you actually had to pay the ransom - it would only recover files which were less than 42871 bytes in size.

In case you were infected with this, I wrote a simple decryption script to recover the files subject to the restrictions described above.  It can be found here.

Update 09/17/2015

New variants of this crypto script are now attempting to delete any existing volume shadow copies prior to executing the encryption routine:

$hdGhncrThhsHhjs = Get-WmiObject Win32_ShadowCopy
ForEach($QhdThscGhsjdR in $hdGhncrThhsHhjs) {

Regarding the salt used in the decryption script, these recent variations have modified the location of the salt from where it had previously existed at line 7 of the crypto script. The salt required by the decryption script is set by the call to GetBytes and stored in a variable used as the second argument to Security.Cryptography.Rfc2898DeriveBytes.