mirror of
https://github.com/mbirth/wiki.git
synced 2024-12-25 23:04:06 +00:00
171 lines
7.0 KiB
Markdown
171 lines
7.0 KiB
Markdown
---
|
|
title: Crypto-Virus decrypted
|
|
language: en
|
|
layout: default
|
|
created: 2016-07-08 15:41:41 +0200
|
|
updated: 2016-07-08 15:41:41 +0200
|
|
toc: false
|
|
tags:
|
|
- know-how
|
|
- hacking
|
|
- virus
|
|
- cryptovirus
|
|
- cryptor
|
|
---
|
|
A friend received the following mail from (supposedly) **FedEx International**:
|
|
|
|
![]({{ site.url }}/assets/cryptovirusmail.png)
|
|
|
|
The attached zip file contained a file `000794681.doc.js`. Since `.js` is a
|
|
known file type in Windows, it would show up as `000794681.doc` and you'd think
|
|
it's a Word file. But clicking on it will run the JavaScript using the *Windows
|
|
Scripting Host*.
|
|
|
|
|
|
The entry point
|
|
===============
|
|
The JavaScript looks like this ([GIST](https://gist.github.com/mars3142/3fc6a5522fcb752cdcbde3a5c1bca434)):
|
|
|
|
![]({{ site.url }}/assets/codedocjs.png)
|
|
|
|
The various `g55(number, string)` calls do nothing but sorting the string into
|
|
the number's position in an array. In the last but one line, the snippets in
|
|
the array are joined in the numeric order which turns out to be valid
|
|
JavaScript (or JScript) code again. In the last line, that code is executed.
|
|
|
|
If you omit the last line and, instead, output the contents of `h72`, you'll
|
|
get the unobfuscated code of the first stage: [GIST](https://gist.github.com/mbirth/d21bf52a024d0634f731e90dca94d254).
|
|
|
|
What this does is basically:
|
|
|
|
* Download 5 files (incl. backup servers if one is taken down) into `%TEMP%`
|
|
* `a1.exe` (some Visual Basic program)
|
|
* `a2.exe` (some NSIS installer, unpacks files to `AppData` then waits)
|
|
* `a.exe` (php.exe, PHP runtime)
|
|
* `php4ts.dll` (PHP library)
|
|
* `a.php` (the actual encrypting PHP code)
|
|
* If all 3 PHP files are downloaded:
|
|
* Write message into `a.txt`
|
|
* Register autostart to open `a.txt` after login
|
|
* Register extension `.crypted` to open/display `a.txt` whenever you click on
|
|
a crypted file
|
|
* Copy `a.txt` to your Desktop as `DECRYPT.txt`
|
|
* Run the actual encryption of your files (see next chapter)
|
|
* Display `a.txt`
|
|
* Overwrite the `a.php` (containing the encryption key) with the BitCoin
|
|
address (so it can't be undeleted to get the actual key)
|
|
* Delete `a.exe`, `php4ts.dll` and, of course, the `a.php`
|
|
|
|
The files to download are selected by 3 parameters:
|
|
|
|
* `ad`, the BitCoin address you should send money to
|
|
* `id`, some identifier?, can be omitted
|
|
* `rnd`, file selector
|
|
|
|
The `ad` parameter is used to generate your encryption key (see next chapter).
|
|
|
|
The `rnd` parameter selects the file you download. It's made up of the current
|
|
mirror server's number (0..4) and the file to download (1..5). So it starts
|
|
with `01`, `02`, etc. and if that server doesn't answer, it'll continue with
|
|
`11`, `12` .. `15`. The files you get with `01`, `11`, `21`, etc. are the same.
|
|
|
|
However, there seem to be some variation with the files returned for `*1`. I'm
|
|
not sure if it's time based or randomly selected each time you start a
|
|
download. When downloading from different servers in a short time, you'll
|
|
mostly get the same file. In rare occasions, one (the last file downloaded)
|
|
was different. I've found 5 different variations which differ in length and
|
|
bytes starting from position 0x43cb6. Could also be random data to confuse
|
|
antivirus products.
|
|
|
|
I think the files `a1.exe` and `a2.exe` are there to either confuse some
|
|
antivirus products or just filler material for future use.
|
|
|
|
What's also interesting is, that the files are returned with a MIME type of
|
|
`image/png`. Also, the download only works when the user agent string
|
|
contains `Windows NT`, otherwise you'll get an empty (0 bytes) response.
|
|
|
|
|
|
Encryption code
|
|
===============
|
|
|
|
The downloaded PHP script (`a.php`) seems to be freshly obfuscated each time
|
|
you download it. But while the obfuscated version differs every time, the
|
|
deobfuscated code is the same.
|
|
|
|
This is how it looks after download:
|
|
|
|
![]({{ site.url }}/assets/codeaphp.png)
|
|
|
|
After removing the first layer of obfuscation, it turns into this:
|
|
|
|
![]({{ site.url }}/assets/codeaphp2.png)
|
|
|
|
And now it becomes clearer, what's happening here. In `$h772` we have an
|
|
`eval()` command with the code to *evaluate* being encoded in base64.
|
|
|
|
In `$e51` there's a regular expression with the `/e` modifier, which enabled
|
|
callbacks in older PHP versions. This means, whenever the parser finds a
|
|
match, a given piece of code is called. And as you might have guessed, that
|
|
code is the one in `$h772`. And to have the parser find something, the subject
|
|
in the `preg_replace` call is exactly the same as the search string in `$e51`.
|
|
|
|
So to get to the actual code, we just have to `base64_decode()` the string
|
|
without `eval()`ing it. And this brings us to the final code. You can see all
|
|
iterations in this [GIST](https://gist.github.com/mbirth/11979a35a152478427928dbdf593797b).
|
|
|
|
(I've annotated and reformatted the final stage.)
|
|
|
|
Fun fact: The base64 encoded code contains proper indentation and Windows line
|
|
endings (CR+LF instead of LF only). They could've saved a lot of space by
|
|
removing all unneccessary spaces and line breaks.
|
|
|
|
The code does this:
|
|
|
|
* Try all drives from `C:` to `Z:`
|
|
* For each drive, check the contents of the root directory
|
|
* If it's a folder and it's not `winnt`, `windows`, `appdata`, etc., check that
|
|
folder (recursively)
|
|
* If it's a file, check if the extension is `zip`, `rar`, `doc`, etc. and if so,
|
|
encrypt it and add `.crypted` to the filename
|
|
|
|
Now the interesting things are right at the beginning of the `Tree($p)` method.
|
|
There are 3 variables defined:
|
|
|
|
* `$a` which defines the intended action, `e` is for encryption, `d` for
|
|
decryption
|
|
* `$k` is the key, which is decoded from base64
|
|
* `$s` is a backslash character to not have to mess around with proper escaping
|
|
|
|
I noticed that with different `ad` values in the download URL (see previous
|
|
chapter), you'll get different encryption keys in `$k`. `ad` is the BitCoin
|
|
address you are asked to send money to. This means the encryption key is based
|
|
on the BitCoin address.
|
|
|
|
E.g., an `ad` value of `17DmGrhMXJcvsmj9tihgTRGAhACynuBmSo` returns a PHP
|
|
script with the key:
|
|
|
|
MWKTbqXczBBUtCGOY6rxrB6Q2ECoaLUCGHDI5C54QaQHiP5010q99mPQNqAKkMkCtCicYss0uCCIDHPa5DiMDF6wYajvGFmaKJD4mtscEVSXPLUuduRStiug/kCCoA16swZZvi2c
|
|
|
|
If you change `ad` to `27DmGrhMXJcvsmj9tihgTRGAhACynuBmSo`, the key changes to:
|
|
|
|
MmSWbqXczBBUtCGOY6rxrB6Q2ECoaLUCGHDI5C54QaQHiP5010q99mPQNqAKkMkCtCicYss0uCCIDHPa5DiMDF6wYajvGFmaKJD4mtscEVSXPLUuduRStiug/kCCoA16swZZvi2c
|
|
^^^
|
|
|
|
In other words: This script is generic and can be used for different BitCoin
|
|
accounts which will generate different encryption keys. And you need to wire
|
|
your money to the correct one to get the correct decryption key.
|
|
|
|
|
|
Decrypting encrypted files
|
|
==========================
|
|
|
|
So let's imagine you accidentally run the script and all your important files
|
|
are now encrypted and renamed to `important.doc.crypted`. What can you do?
|
|
|
|
Well, we've learned that the encryption key is based on the `ad` value. And that
|
|
you still have in that mail with the bogus zip file. Using that, we can download
|
|
the PHP script again, which contains the actual key.
|
|
|
|
After deobfuscating it, you just have to change `$a='e'` to `$a='d'` and run it
|
|
and it should decrypt all your files again. Problem solved.
|