Aka: ZeusLoader, Deloader, Terdot, Zbot is a malware family that downloads Zeus OpenSSL. Parts of the source code of Zeus were leaked back in 2010  and since couple of versions been forked. Each of the version has its malicious capabilities, but all in common do info stealing specially banking information. Zeus in its core does wild stuff from stealing HTTPS session before being encrypted; to split stolen data and send it in multiple channels over different C2 server based on the stolen info-type . The sent data is being encrypted using RC4 algorithm. Given that major parts of the Zeus being well known and very detectable by almost every AV; Zloader is not just a loader/packer to Zeus core functionality. There are some complicated obfuscation techniques and visual encryption implemented on every single unpacked version of Zloader that bypass security and difficulty extracting configuration. Uncommon attack vector like using Google AdSense has been observed lately  also attacker signs Zloader with a certificate compromised from legitimate software in order to evade detection. In this post, we gonna take a look of common Zloader 123 botnet attack that uses maldoc vector. Quickly analyze maldoc, downloader, and the well known unpacking technique with observed behavior which simple and not quite interesting. However, the second part is going to be deep dive into analyzing and reversing techniques of Zloader unpacked version.
File Type Office Open XML Spreadsheet
Size 182.62 KB (187002 bytes)
Creation Time 2021-10-04 13:17:51
In clear text on sheet2, the maldoc give away downloader URL, directory where it’s been dropped, and shell command to run a Dll which is the Zloader.
Enable macro is required to run the above in VBA script.
Downloaded test.dll is just an HTML! that downloads logs.php which is a Zloader Dll file!
File Type Win32 DLL
Names suqyatda.dll, ewviv.dll, ehev.dll, cyvi.dll, logs.php
Size 1.13 MB (1189888 bytes)
Compiler Time-stamp Mon Sep 23 01:29:14 2019
First Submission 2021-10-04 18:23:00
Zloader Dll file is been downloaded and runned in temp location. After Zloader runs:
- Create new process msiexec.exe and inject its loader in it.
- Loader sets new registry values using random hive and key names in:
- Deletes original downloader and copy itself to %AppData%\Roaming\*random name\*.dll
The registry value calls the new directory for persistent in case of host rebooted. Both registry values are encrypted with RC4 but more to that in next section
When checking memory strings for any forensics it spells out great number of C2 values. Noticed that 20 URLs has random name with fixed length. Those are called Domain Generated Algorithm DGA, unlike hardcode C2 URLs those are queried during running. More to that later in next section.
Using pe-sieve64 tool is good way to dump the unpacked Zloader from the running process which is valid PE file to be analyzed. However, just a quick debugging would give same result. In SquirrelWaffle and QakBot recent analysis   it’s been observed that Zloader among other malwares are using same crypters/decryptor for unpacking mechanism for their loaders before injecting them in process. Following the same debugging method in  would reveal the packed Zloader.
File Type Win32 DLL
Size 146.00 KB (149504 bytes)
Compiler Time-stamp Wed Jul 14 08:04:16 2021
First Submission 2021-10-18 15:32:37
The unpacked Zloader is a master piece of obfuscated functions that waste lots of analysis time to dig into. API strings among other static indicators would not be a good clue for analyzing Zloader. Beside, this malware family is known for API hashing, Visual Encryption using XOR, and RC4 encryption to encrypt strings.
There are five main topics we are going to discuss in this section when reversing Zloader: API hashing, XORing string, extracting Configuration, DGA routine, and Zeus function.
Statically analyzing Zloader is a bit of a challenge. However, with a new amazing IDA plugin called HashDB from OpenAnalysis Labs  it’s amazing how much obfuscated strings get out the way when reversing Zloader. Just to show a case of what HashDB can do before and after shots of hashed values in a random function. The hashes been checked among large database of hashes with good prediction of hashing algorithms been used.
With API hashing out of the way. It’s important to get reversing tricks to dig into the main functions and extract configurations. There’re very limited hardcode strings in Zloader that can be clues like those.
First, let’s look at Off_186010 which is an offset of an offset of a memory location rdata:00183D80 with literal string ( #uVTN7’GQ’rxUf5Ly ). When cross referencing this offset it’s been used 4 times in two different functions. And there’s some sort of XOR function in both subroutines which reveal this is the key literal string could be an XOR key value.
Cross referencing both sub_1658F0 and sub_173C90 routines would shows that over 120 times those functions has been called. Randomly checking any of the cross referencing like below
text:001610E0 push offset unk_183E8E
.text:001610E5 call sub_1658F0
text:0016444E push offset unk_184310
text:00164453 call sub_173C90
….. skipped lines……
text:00165685 push offset unk_184040
text:0016568A call sub_1658F0
We noticed both subrouties been called after a push of unknow offsets
Let’s use XOR key (#uVTN7’GQ’rxUf5Ly) with offset unk_184040 value.
Hex: 70 00 1A 00 30 00 20 00 39 00 56 00 55 00 22 00 0D 00 6A 00 1B 00 1B 00 27 00 09 00 46 00 23 00 1F 00 57 00 29 00 56 00
The XORed value/result doesn’t make sense. If anything noticeable that the Hex values has zeros in sequence. Which indicate sub_1658F0 is for wide character and this makes and sub_173C90 for normal character. let’s try again deleting all repeated zeros and XOR with the key
It’s not just strings that been obfuscated, some API calls been XORed too. Almost 120 offset being pushed in stack which means 120 strings are being XORed and to make it readable; Appendix – A contains all the strings with addresses after been XORed.
The other string ‘qhpacozsstaznupphhedjtuoww’ is 26 length. It’s crossed referenced twice in two separate routines.
snipped assembly from sub_161E40 and sub_1673D0 routines
.text:00161EE3 push offset aQhpacozsstaznu ; “qhpacozsstaznupphhedjtuoww”
.text:00161EE8 push offset unk_184404
text:001673D0 sub_1673D0 proc near ; CODE XREF: sub_171400+40↓p
.text:001673D0 push ebp
.text:001673D1 mov ebp, esp
.text:001673D3 push edi
.text:001673D4 push esi
.text:001673D5 mov esi, ecx
.text:001673D7 call sub_1809A0
.text:001673DC mov edi, [eax+30h]
.text:001673DF mov ecx, esi
.text:001673E1 call sub_1809A0
.text:001673E6 add eax, edi
.text:001673E8 push 36Fh
.text:001673ED push offset unk_184404
.text:001673F2 push eax
.text:001673F3 call sub_171D80
.text:001673F8 add esp, 0Ch
.text:001673FB mov ecx, esi
.text:001673FD call sub_1809A0
.text:00167402 mov edi, [eax+34h]
.text:00167405 mov ecx, esi
.text:00167407 call sub_1809A0
.text:0016740C add eax, edi
.text:0016740E push 64h ; ‘d’
.text:00167410 push offset aQhpacozsstaznu ; “qhpacozsstaznupphhedjtuoww”
In both routines notice a repeated push to an offset unk_184404. This offset contains configurations. Noticed that both offset passed into a function sub_1656B0 (name decrypting_rc4)
Decrypting_rc4 function calls multiple function and those are calling other functions. What we are looking here is RC4 algorithm.
To have mind map where RC4 algorithm location lets Xref-from Decrypting_rc4 function where Config strings and key retrieved
Now let’s go back to the configuration ‘config’ offset in data block and copy its hex value to CyberChef and use RC4 algorithm to decrypt it with the key (qhpacozsstaznupphhedjtuoww)
Notice three things: got C2 URLs, list in Table-1, and 123 which is ID for this variant of Zloader, and at the tail there’s this value (djfsf02hf832hf03) which is another RC4 key that decrypt the registry values in \HKEY_CURRENT_USER\Software\Microsoft\bbxk and also encrypt decrypt traffic with C2 .
Decrytped registry key value contains host name and the Zloader in %AppData% directory.
Zloader know for using DGA algorithm and we notice above some of the generated 32 character length URLs. To find the DGA function in this we can look for .com or post.php strings that been deobfuscatd in the previous section of XORing strings.
when cross referencing .com from rdata:001849B4 location we find that it’s been called by one function and let’s name that function the_dga
The_dga function has been called one by another function. Based on , the caller of DGA routine does it math calculating values called Seed based on time and RC4 key (djfsf02hf832hf03) (second key). So the values generated are much different each day passed in used GetLocalTime and SystemTimetoFileTime APIs. Notice that the_dga function has passed value of 32 which is the same length of the URL string with Seed value which in this case makes the entire caller function to calculate Seed value. followed by post.php and https while loop. The caller function got many obfuscated function that slows down analysis and it get complicated calculating generated domains manually.
Zeus uses item ID as list below which is the main one, there are more extended list based on Zloader version   . Each ID passed into a function and dissect information from victim machine. When that information stored in attacker SQL filed it show retrieved info about the host.
|10001||SBCID BOT ID|
|10003||SBCID BOT VERSION|
|10005||SBCID NET LATENCY|
|10006||SBCID TCPPORT S1|
|10007||SBCID PATH SOURCE|
|10008||SBCID PATH DEST|
|10009||SBCID TIME SYSTEM|
|10010||SBCID TIME TICK|
|10011||SBCID TIME LOCALBIAS|
|10012||SBCID OS INFO|
|10013||SBCID LANGUAGE ID|
|10014||SBCID PROCESS NAME|
|10015||SBCID PROCESS USER|
|10016||SBCID IPV4 ADDRESSES|
|10017||SBCID IPV6 ADDRESSES|
|10018||SBCID BOTLOG TYPE|
To get to Zeus item values and function we need to search strings in IDA to find one the common ID values since they are constant.
Notice that most the calls are sub_1657B0, let’s call it z_items_main, it’s been crossed referenced 17 times. List of Zeus items being found in 123 variant.
|10001||SBCID BOT ID|
|10003||SBCID BOT VERSION|
|10007||SBCID PATH SOURCE|
Just to give an example of the level of obfuscation on every stage of Zloader. Not all the items ID values are retrieved in decimal passed to the function. Some values passed into another function and require to calculate separately like below in v29 value return from sub_167890 .
To give an example of how Zeus item works let take a look at this function sub_177110.
sub_16F780 has (20001: CFGID_LAST_VERSION) that updates Zloader version. Looking at it in the disassembler would show so much obfuscated function, but to have an idea of what possibly this update could do let’s see the leaked source code having this similar Item ID in similar fashion .
The successful update would lead to update registry values in HKCU\Software\Mircosoft\bbxk\ which points to %AppData% directory of possible the new Zloader that has new C2 connections
Finally, to have an idea how Zeus function being called here’s a mind map when Xref-to it.
|rdata:00184820||Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36.|
 Zeus opensource, https://github.com/Visgean/Zeus
 Titans’ revenge: detecting Zeus via its own flaws, https://www.honeynet.it/wp-content/uploads/Papers/04-Titans%20revenge.pdf
 Hide and Seek | New Zloader Infection Chain Comes With Improved Stealth and Evasion Mechanisms, https://www.sentinelone.com/labs/hide-and-seek-new-zloader-infection-chain-comes-with-improved-stealth-and-evasion-mechanisms/
 The Squirrel Strikes Back: Analysis of the newly emerged cobalt-strike loader “SquirrelWaffle” , https://elis531989.medium.com/the-squirrel-strikes-back-analysis-of-the-newly-emerged-cobalt-strike-loader-squirrelwaffle-937b73dbd9f9
 QakBot Quick analysis, https://twitter.com/aaqeel87/status/1443255927000424449?s=20
 HashDB project, https://hashdb.openanalysis.net/#section/Using-The-API/Hash-Format
 The “Silent Night” Zloader/Zbot , https://www.malwarebytes.com/resources/files/2020/06/the-silent-night-zloader-zbot_final.pdf
 The DGA of Zloader, https://bin.re/blog/the-dga-of-zloader/