REvil or Sodinokibi ransomware is a powerful ransomware that encrypts files. It uses advanced encryption techniques and can operate without connection to control servers.
So, let’s get started
Malware sample
: https://app.any.run/tasks/2336fa81-a8c9-41b5-8a7a-e958047097f2/#File Info
: PE32 executable (GUI) Intel 80386 (stripped to external PDB), for MS Windows, UPX compressedMD5
: 61c19e7ce627da9b5004371f867a47d3SHA1
: 4f3b4329871ec269043068a98e9cc929f603268dSHA256
: bf7114f025fff7dbc6b7aff8e4edb0dd8a7b53c3766429a3c5f10142609968f9SSDEEP
: 6144:YONNYdX7HkqEHcTY6uoZzFyKAuGnlOOkl8tuGogbOIVmda9J4:YONNoX7HMHcTY6uoZzFyfONlwNB2
Unpacking
Hmm, this executable has been packed using the UPX packer. We can either use the UPX packer to unpack it or unpack it dynamically (which is an interesting method). To do that, we’ll set breakpoints on some functions such as CreateProcessInternalW
(whenever a new process is created), VirtualProtect
(whenever permissions of a memory region are changed), ResumeThread
(whenever a thread resumes). Also, we need to calculate the return value of VirtualAlloc
(to find the address of the newly allocated memory segment). Set a breakpoint at some instruction when VirtualAlloc
is about to return, let’s say ret, note down the value of rax, follow that address in dump and then continue.
Boom, a PE file! We can dump it and then start reversing it using IDA.
First of all, we need to note down the entry point using IDA. It is present at the offset 0x36E6. Now, let’s follow call sub_40369d
. We immediately notice the instruction call dword_41cb64
(a call to dword instead of some address). This points to the fact that the address of API call has not been resolved yet which means that some dynamic import would be resolved here. Now, there’s only one function before this call instruction(0x406A4D), so it might be the function where dynamic imports are being handled. Here, in IDA, the executable base address is 0x400000 and the function we’re looking for is present at the offset 0x6A4D. One more thing, we cannot see any import table in IDA.
Now, let us construct the import table using Scylla
. To do this, load the executable in x32dbg, follow the function with the offset 0x369d until you reach the one with the offset 0x6A4D. Step over this instruction and yeah, now we can see that the imports have been resolved. Using Scylla (a plugin present in x64/x32dbg), take a dump, click on IAT Autosearch
, after that click on GetImports
to view the imported DLLs. Everything is set, now we can fix the dump by clicking on the Fix Dump
option. This would fix the dump we took earlier and save the new file.
Let’s us look the fixed dump in PEBear to verify whether the imports have been fixed or not.
Now, we can change the value of the Entry Point to 36E6 using PE bear. Interesting, everything is set! Now we can use IDA to reverse this dump.
Interesting!!!!
String Decryption
Now, let us surf through some functions to find out something interesting.
Here, we can see that the program calls CreateMutexW(0, 0, Name);
This buffer Name
is a local buffer which is passed by reference to the function sub_EC4E03
.
1 | sub_EC4E03(&unk_EDCC28, 1982, 15, 86, Name); |
unk_EDCC28
is just some data, we need to find out the working of the function sub_EC4E03
.
1 | int __cdecl sub_EC4E03(int a1, int a2, int a3, int a4, int a5) |
Okay, so sub_EC4E03
calls another function which contains some interesting code snippets. Basically, this function is an implementation of RC4 algorithm. Let’s rename some variables and arguments to make our life easier.
1 | _BYTE *__cdecl sub_EC4E03(char *arg_enc_data, int arg_off_1982, int arg_off_15, int arg_off_86, int arg_str_decrypted) |
Okay, so 15 is probably the length of the key for RC4 decryption, starting from arg_enc_data[1982]
. The program is probably trying to decrypt the data present at arg_enc_data[1982+15]
. We can extract the key and some encrypted data that is passed to the function.
Interesting! So, the key is 485A8EEEF3041AE753246740A753FF
. We can pick some amount of data from arg_enc_data[1997]
and decrypt it using cyberchef.
Yes, our assumption was correct. This is actually RC4 because the string Global
is a valid string. Now, we need to find xrefs(cross references) to the function sub_EC4E03
to decrypt various encrypted strings present in the malware. Performing it manually is boring and time consuming task. We can use IDAPython API to automate the process. In fact, we can create a script to automatically decrypt the encrypted strings using IDAPython API.
1 | import idaapi,idc,idautils |
Jeez! The decrypted strings are:
1 | b'fld' |
TO BE CONTINUED….