MMD-069-2024 - An old ELF Ransomware pivoted crypto from OpenSSL to PolarSSL

5 months ago 58
BOOK THIS SPACE FOR AD
ARTICLE AD

This malware analysis was originally posted in my soon to be closed Japanese blog in 2015 and to avoid the research info disappearing I re-posted it as an English translation over here.

During AVTOKYO-2015 at "Swimming in the Sea of ELF" Workshop (thanks to attendees & tessy). During the workshop a new Linux ransomware has been distributed in the internet, as I explained in the workshop why we sometimes need to reverse binaries in UNIX shell, I used that samples as a demonstration on how to do analysis and sharing the know-how to the audience and then posted my finding in the kernelmode also.

I analyzed this case by just only using one tool of old radare2 version (thanks to pancake), radare2 which is always explained in most of my workshops is useful for that. If you would, I made many screenshots during analysis so you can practice radare2 (in secure environment) to reverse this old malware threat using my analysis notes as comparison.

Table of contents

(1)Background of the infection
(2)What kind of source code was used?
(3)How does it work to encrypt?
(4)Reversing the decryption function
(5)Why did they use PolarSSL code?
(6)Pivoted from OpenSSL
(7)Conclusion

《 1. Background of the infection 》

【Go to contents】

The infected sites showed errors similar to this one↓(the site had a wordpress file upload plugins vulnerability)

The search keyword is "README_FOR_DECRYPT.txt" and the result came up when you dork it.

If you check the "README_FOR_DECRYPT.txt" contents from an infected site, it looked like this:
(※Click to enlarge)

《 2. What kind of source code was used? 》

【Go to contents】

The intrusion investigation has concluded that the site had been suffered an infection of ransomware aiming Linux servers called 「Linux/Encoder.1」 a ransomware ELF binary file from the exploited vulnerability. It has two version: x86-64 and x86-32 of binaries that has been used by the adversaries in their C2 during the campaign.

Back in 2015 when Linux Ransomware is not so many, it was so excited to check it out. But, to be very honest, I was really disappointed when I reversed it because the content was too simple, and I wondered if it was made by an amateur programmer.

This is the list of the source code set to build the above binaries↓

↑As you can see, it's all written in C, and system-calls related to C file to be used in functions used throughout the malware are all listed up there, so I think it's easy to understand the purpose and it is good to be a sample for RE beginners to practice. Obviously the starting point and main code of the ransomware is that 「main.c」file.

NOTE: Note: You can quickly search this list of source code usingyour text editor if you want (smile).

《 3. How does it work to encrypt? 》

【Go to contents】

As one result of the analysis, as always spotted in all ransomware, there are "OK" and "Prohibited" rules for files/dirs encrypted by malware↓

0x002F1FC /root/.ssh (exclusion) 0x002F207 /usr/bin (exclusion) 0x002F210 /etc/ssh (exclusion) 0x002F219 /home 0x002F21F /root 0x002F225 /var/lib/mysql 0x002F234 /var/www 0x002F23D /etc/nginx 0x002F248 /etc/apache2 0x002F255 /var/log

As you can see it encrypted MySQL libraries (smile), I hope this adversary know what they are doing.

I will guide you on how this can be reversed as following notes (Using x86-32 ELF samples):

Note-1: This is the function that has been used to encrypt the desired (inclusion) targets↓

Note-2: And this is the part where exclusion has been performed to some unwanted targets↓

Please note the reason why they don't want to encrypt "/root/.ssh"
These are the scan-able server's file extentions to be aimed for encryption↓

0x002F25E .php 0x002F2AC .zip 0x002F2FD .mp4 0x002F263 .html 0x002F2B1 .db 0x002F302 .wma 0x002F269 .tar 0x002F2B5 .7z 0x002F307 .aac 0x002F26E .gz 0x002F2B9 .doc 0x002F30C .wav 0x002F272 .sql 0x002F2BE .xls 0x002F311 .pem 0x002F277 .js 0x002F2C3 .properties 0x002F316 .pub 0x002F27B .css 0x002F2CF .xml 0x002F31B .docx 0x002F280 .pdf 0x002F2D4 .jpg 0x002F321 .apk 0x002F285 .tgz 0x002F2D9 .jpeg 0x002F326 .exe 0x002F28A .war 0x002F2DF .png 0x002F32B .dll 0x002F28F .jar 0x002F2E4 .gif 0x002F330 .tpl 0x002F294 .java 0x002F2E9 .mov 0x002F335 .psd 0x002F29A .class 0x002F2EE .avi 0x002F33A .asp 0x002F2A1 .ruby 0x002F2F3 .wmv 0x002F33F .phtml 0x002F2A7 .rar 0x002F2F8 .mp3 0x002F346 .aspx 0x002F34C .csv 0x002F36B .git 0x002F370 .svn

During file scanning it also greps w/regex the files that contain the following keywords↓

0x002F351 public_html 0x002F35D webapp 0x002F364 backup

There are other functions in this ransomware that you can check out yourself during the practise ;-) which I may ask you during my workshop.

《 4. Reversing the decryption function 》

【Go to contents】

If we see the result after infection, it seems that the extension ".encrypted" had been added to encrypted files. What actually happened is, in contrast, a huge flaw in how this ransomware works, in which the real files were just deleted with "unlink" and new files were created with a new extension; you can confirm that in the source code at the encryption part and also during the forensics.
If you know how Linux filesystem works you'll understand why I called it as a "huge flaw" ;-)

There are two decrypter functions, which are: decrypt_all() and decrypt_file() functions.
If we reverse decrypt_all(), the part of the code will look like this↓
[ xrefs: 0x004014f1 0x00401502 0x00401523 0x004014a5 0x004014b6 0x0040098e 0x00400ad3 ]

↑Several points can be observed↓

1. This ransomware crypter binary required arguments to run the function. Without arguments in won't work.
Like this command line is needed ⇒ ./ransombinary [crypt|decrypt] [key]
In the x86-32 sample, the argument switch function looks like this:↓

2. From studying the reversed code, you know that you can decrypt the entire Linux server from the "/" (root) directory.
3. decrypt_all() is actually an interface needed to decrypt all crypted files, by ultimately executing decrypt_file().

decrypt_file() function can be seen at the address below. It goes like this↓
[ addr: 0x00400617 xref: 0x00400a4f xcall: setChmod() ]

Noted that "Decrypting file: %s" string can be used as a hint (smile)

This is interesting, right? See the way it is coded.. even though it's ransomware, a malware, it uses stdio.h rather than using a system call, with the arguments used for execution, and the structured programming. Typically a work of an accomplice programmer hired by the bad actor.

By the way, the data of the opened file is read with fread_unlocked (void *data, size_t size, size_t count, FILE *stream). Well this can only mean that the ransomware is meant to target Linux system with that function intact, so.. theoretically it can not be ported to unsupported UNIX platforms like macOS, FreeBSD, NetBSD, OpenBSD, Minix, AIX, HP-UX, Solaris, Cygwin, mingw, MSVC, and Android, which is good for us ;-) Again, PoC of amateur/beginner malcoder.

The following reversing code explains how to decrypt files encrypted by malware.

First, the decryption mechanism of this ransomware uses the RSA private key (held by the criminals) and the public key (held by the victim) to retrieve the encrypted AES key written in the binary, which can then be used to retrieve files encrypted by the malware.

The AES key is encrypted (in the binary) with the private key.↓

0x002FF58 -----BEGIN ENCRYPTED PRIVATE KEY----- 0x002FF80 9292758453063D803DD603D5E777D7888ED1D5BF35786190FA2F23EBC0848AEADDA92CA6C3D80B32C4D109BE0F36D6AE7130B9CED7ACDF54CFC7555AC14EEBAB93A89813FBF3C4F8066D2D800F7C38A81AE31942917403FF4946B0A83D3D3E05EE57C6F5F5606FB5D4BC6CD34EE0801A5E94BB77B07507233A0BC7BAC8F90F79 0x0030088 24BF6185468786FDD303083D25E64EFC66CA472BC44D253102F8B4A9D3BFA75091386C0077937FE33FA3252D28855837AE1B484A8A9A45F7EE8C0C634F99E8CDDF79C5CE07EE72C7F123142198164234CABB724CF78B8173B9F880FC86322407AF1FEDFDDE2BEB674CA15F3E81A1521E071513A1E85B5DFA031F21ECAE91A34D 0x0030190 C36D0EB7FCD285223CFB5AABA5BDA3D82C01CAD19EA484A87EA4377637E75500FCB2005C5C7DD6EC4AC023CDA285D796C3D9E75E1EFC42488BB4F1D13AC30A57 0x0030218 C000DF51A7C77AE8D7C7370C1FF55B69E211C2B9E5DB1ED0BF61D0D9899620F4910E4168387E3C30AA1E00C339A795088452DD96A9A5EA5D9DCA68DA636032AF 0x00302A0 C1ACF567564274FB07A0BBAD5D26E2983C94D22288ACD763FD8E5600ED4A702DF84198A5F06C2E72236AE490C93F07F83CC559CD27BC2D1CA488811730BB5725 0x0030328 4959CBF6F8FEF750AEE6977C155579C7D8AAEA56749EA28623272E4F7D0592AF7C1F1313CAC9471B5C523BFE592F517B407A1BD76C164B93DA2D32A383E58357 0x00303B0 9AE7FBC99546432DF71896FC239EADAEF38D18D2B2F0E2DD275AA977E2BF4411F5A3B2A5D33605AEBBCCBA7FEB9F2D2FA74206CEC169D74BF5A8C50D6F48EA08 (etc etc…)

Note: We can see the pattern of output from the RSA command is written in its entirety in that "etc etc.." section. In other words, the output from the AES key encryption was parsed into the binary. It is a watermark of what it seems that a builder was used to create the binaries for each Linux ransomware. So there is an automation/framework/tool used for forming this binary. Meaning that we are not dealing with panksters who wanna hack with ransomware at all.

The block cipher spotted in this AES mode of operation is Cipher Block Chaining (CBC) which is a block mode that XORs the previous encrypted block of ciphertext to the next block of plaintext to be encrypted with the 1st encrypted block contains random data.↓)
[ xref: 0x0400836 xcall: aes_decrypt() ]

And, decrypt_file() can be reversed like this↓(in larger picture)
[ xref: 0x00400a4f xcall: setChmod() ]

《 5. Why did they use PolarSSL code? 》

【Go to contents】

When reversing this ransomware, we found functions from Mbed-TLP / PolarSSL source code. Why they did that?

The AES decryption function in this ransomware includes "mbedtls_aes_setkey_dec" and "mbedtls_aes_crypt_cbc" which are functions which are taken from Mbed-TLP / PolarSSL「mbedtls/pk.h」.
If we see the reversing pad picture at address 0x400836, where aes_decrypt'' function was called, if you trailed that function further you will see that the decryption process (for restoring the cryptid files) is using those function of "mbedtls_aes_setkey_dec" and "mbedtls_aes_crypt_cbc", these functions are being used to decrypt AES on the CBC crypt mode if you familiar with the Mbed-TLP or Polar SSL (coded in mbedtls/pk.h) - So apparently the coder is copy pasting these codes for the ransomware encryption/decryption purpose. The similar operation can be coded with common SSL Linux libraries so we can presume to make sure the ransomware encryption can be executed independently while other more generic crypto libraries can be at risk locked by encryption operations or for other similar reasons. After that the data of the files recovered during the decryption function for encrypted files was also written by fwrite_unlocked in stdio.h.

The next is the explanation on how the ransomware decrypts AES key encrypted with RSA.

If you read the asm code for the RSA decryption function (AES key cracking function), the sequence is something like this:↓ (click for bigger picture)
At 0x400753 there is private_decrypt() function, if you trace it further you will see mbedtls_pk_decrypt() function. mbedtls_pk_decrypt() function is obviously also from Mbed-TLP / PolarSSL source code with goal to decrypt the binary encrypted AES key, and that decrypted AES key is then to be used to restore the encrypted files.

The mbedtls_pk_decrypt code itself is the source code of PolarSSL, and the purpose of this round is to decrypt messages that were originally encrypted on SSL. If you check the specifications, you will see that mbedtls_pk_decrypt supports "RSA default padding type PKCS#1 v1.5", which means that mbedtls_pk_decrypt can decrypt RSA encryption. In accordance to the above explanation, if you reverse the decryption function of the AES key, it will look like this:↓
[ xref: 0x0400753 xcall: private_decrypt() ]


《 6. Pivoted from OpenSSL 》

【Go to contents】

So... I wonder what crypto library was used before PolarSSL? Why did "PolarSSL" start being used recently?
Unsurprisingly, there was a version of Linux ransomware before "Linux.Encoder.1" allegedly produced by the same adversary, and I can tell that "PolarSSL" was not used at that time, but they used "OpenSSL". The evidence are the following two cases ↓

Reversing the RSA private key encryption function ↓

Reversing the encryption function of the AES key↓

※The AES key length used from the beginning was 128 bits.

The crypto library was changed probably because of the reason stated above and at that time PolarSSL libraries was more "secure" than OpenSSL to assure the execution of the encryption/decryption. Well, all we can do is just guessing right?


The above picture is my statement that time saying that Encoder.1 (with PolarSSL) was firstly detected and then Encoder.2 (with OpenSSL) was digged afterward.

《 7. Conclusion 》

【Go to contents】

- This threat is automated built, it has API (interface) to execute the crypto operations for its binary, a trick to avoid instant behavior analysis. The last version of the encryption function was coded using PolarSSL, crypto libraries, and this encrypter is reading and writing with functions from stdio.h.
- System commands are also executed (unlink, chmod, etc.)... blocking their execution and restoration should be possible on systems that support journald.
- We have confirmed several adversaries source IP addresses, so the author appears to be from Eastern Europe.
- The record KM folks found this ransomware family is here ==> [click] - Original analysis in 2015 (Japanese)

End of report.

reversed by @unixfreaxjp of MalwareMustDie

Read Entire Article