Wednesday, June 19, 2024

MMD-0069-2024 - An old ELF Ransomware pivoted crypto (OpenSSL to PolarSSL) Linux/Encoder.1-2

This malware analysis was originally posted in 2015 on my-soon-to-be-closed Japanese blog and to avoid the research information 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). While we were doing the workshop a new Linux ransomware has been distributed in the internet. And as I explained in the workshop why we sometimes need to reverse binaries in UNIX shell, I used that emerged samples as a demonstration on how to do analysis (in a safe environment) and sharing the know-how to the audience and then posted my finding in the kernelmode also.

I analyzed this case by using one tool of radare2 old version (thanks to pancake..I forgot what version was that). About radare2, it is a reverse engineering tool that I always explain in most of my workshops, it is useful framework to work in the shell to analyze binaries.

If you would, I made many screenshots during analysis so you can practice radare2 (again, in a 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

《 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 was not so many, I was so excited to check it out. But then, to be very honest, I was really disappointed when I reversed it to find that the content was too simple, and I wondered if it was made by an amateur programmer judged by the way it is developed.

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

↑As observed, the the binary is entirely compiled from the C programs, with system calls related to malware functions are hardcoded throughout the listed files. This makes the purpose of the code straightforward to understand, making it an excellent sample for beginners in reverse engineering to practice on.
And obviously the starting point and main code of the ransomware is that「main.c」file.

Note: You can quickly search this list of source code using your 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 this ransomware↓
 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 the binary will be reversed as per 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 (stated in the picture) on why they don't want to encrypt "/root/.ssh"
These are the scan-able server's file extentions to be aimed for encryption purpose↓

 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 some additional common and expected functions in this ransomware that you may explore independently during practice, and I may inquire about these during my workshop if we meet. But my focus in this post will be on the encryption functionality, where I will explain how the adversary adapted and pivoted the encryption libraries and propose theories regarding their motivations for doing so.

《 4. Reversing the decryption function 》

【Go to contents】

If we examine the results post-infection, it appears that the extension '.encrypted' has been appended to the affected files. However, what actually occurred reveals a significant flaw in the ransomware's operation. Instead of truly encrypting the original files, the ransomware deleted them using the 'unlink' function and created new files with the '.encrypted' extension. This can be verified both in the source code at the encryption stage and through forensic analysis.
If you know how Linux filesystem works you'll understand why I called it as a "huge flaw" ;-) Suggesting us that the coder knowledge on linux server is not even close to sysadmin level.

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 direct system call, with the arguments used for execution, and the structured programming. Typically a work of an accomplice programmer hired by the bad actor, or a newbies in the field.

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, another PoC of amateur/beginner malcoder in UNIX environment.

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.↓

 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 entirety in that "etc etc.." section. In other words, it is the output from encrypted AES key that was parsed into the binary in a specific steady location, showing as 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 behind this binary. Meaning that we are not dealing with panksters who wanna hack with ransomware but a serious actor who can be assumed to have a plan to mass infecting the compromised servers.

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. Iy can be confirmed in here↓)
[ 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 taken from Mbed-TLP / PolarSSL libraries/source code. So why they did that? What's wrong with the good old OpenSSL?

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 encrypted 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 (well, it is coded in mbedtls/pk.h)

So apparently the coder is copy pasting these codes for this ransomware encryption/decryption purpose. The similar operation can be coded with common SSL Linux libraries (like OpenSSL), so why? 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 avoiding OpenSSL bugs, or avoiding blocking SSL libraraies access, or etc etc other similar reasons. <== One assumption of why Mbed-TLP or Polar SSL code was used/abused.

After that the recovered data on files during the decryption 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), you will see more Mbed-TLS/PolarSSL function was being used, to proof that please follow the below reversing steps↓ (for your convenience the referred code is here)

At 0x400753 there is private_decrypt() function, if you trace it further you will see mbedtls_pk_decrypt() function. That mbedtls_pk_decrypt() function is obviously alsp come from Mbed-TLP / PolarSSL source code with goal to decrypt the AES key encrypted and embedded in the binary, and so 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. <== Another reason Mbed-TLP or Polar SSL code was used/abused.

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" libraries for the encryption purpose. The binaries for the previous version was found later on and confirmed linked to what has been described in here. So for the naming the antivirus using name Encoder.2 for the previous found version. The evidence of the Encoder.2 using the OpenSSL is described in the following two cases below↓

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 later on.

《 7. Conclusion 》

【Go to contents】

- This ransomware binaries are auto-generated by a builder tool. And it needs interface to pass arguments to the binary to execute the crypto operations, which is efficient trick to avoid instant behavior analysis, and also suggesting a possible panel interface for adversaries to control its infection.
- The last version of the encryption function was coded using PolarSSL encryption libraries, and this encrypter is reading and writing with functions from stdio.h, having a decent programming structure, suggesting its development by a programmer.
- System commands are also executed (unlink, chmod, etc.).. Blocking these command's execution can be done for this ransomware series, a lot of Linux ransomware are still using direct shell command or system call also. The thing is, such commands involving file deletion may open chances for restoration tat should be possible to conduct on systems that support recovery fie systems.
- We have confirmed several adversaries IP addresses, these adversaries appear to be from Eastern Europe networks.
- The record when we in KM found this ransomware family is here ==> [click]
- The concept for using multiple encryption similar this case where the file crypter AES key(s) to be RSA-crypted in binaries is also not changed much from 2015 until now, the level of encryption and mode maybe improved but this is still commonly used concept after almost 9 years passed now.
- Original analysis in 2015 (Japanese)

End of report.

reversed by @unixfreaxjp on Nov 11, 2015 and was published in 0day dot jp on Nov 17, 2015.