We have spotted malicious DLL sideloading activity that builds on the classic sideloading scenario, but adds complexity and layers to its execution. Moreover, our investigation indicates that the responsible threat actor(s) fell so much in love with this adaptation of the original scenario that they used multiple variations of it, repeatedly swapping out a particular component in the process to evade detection at this step of the attack chain.
Earlier forms of the attack have been covered previously in the industry, mainly in the Sinophone CTFIoT and Zhizu blogs. The attack is based on a classic sideloading attack, consisting of a clean application, a malicious loader, and an encrypted payload, with various modifications made to these components over time. The latest campaigns add a twist in which a first-stage clean application “side”loads a second clean application and auto-executes it. The second clean application sideloads the malicious loader DLL. After that, the malicious loader DLL executes the final payload.
Figure 1: DLL sideloading, with recently identified extra steps; the clean applications are shown in blue boxes and within the blue outline, while the malicious steps are shown in orange boxes with red type and outlined in red. This chart will appear again in the report with the specifics of each variation highlighted
The threat actor most associated with this attack is variously called “Operation Dragon Breath,” “APT-Q-27,” or “Golden Eye Dog,” and is believed to specialize in the online-gambling space and its participants. These actors liked this two-clean-apps scenario so much that they used multiple scenarios in which the second-stage application is replaced with other clean applications.
The original campaigns targeted Chinese-speaking Windows users engaged in online gambling, and initial infection vectors were distributed via Telegram. We have, to date, identified intended targets in the Philippines, Japan, Taiwan, Singapore, Hong Kong, and China. Sophos normally blocks sideloading attacks during the sideloading process, so the payload never executes and the users are protected.
Figure 2: Where we saw Operation Double Dragon Breath
In this investigation we found several distinct variations on the double-clean-installer approach; variations mainly involved changes to precisely which program was abused in the second stage, with a few knock-on effects caused in turn by those changes. We’ll describe the most commonly encountered code we found at each stage, touching on variations as we go along.
The beginning: Infection vector
Early on, our investigation led us to a Web site (telegramos[.]org) that delivers, or claims to deliver, Chinese-language versions of the Telegram application for Android, iOS, and Windows. We noted that the site — which we and other vendors flag as malicious — occasionally but not consistently ignored our OS choices when we clicked the download links, instead delivering a version based on the user-agent string to which our browser was set, as shown in the screen captures below.
Figure 3: Clicking the ‘Windows” button from the Windows download page meant nothing when our browser reported itself as Android…
Figure 4: …so we changed our UA string to IE
This is the site from which the affected user is thought to have downloaded the package that caused the infection. How the user first encountered the site, whether through phishing or SEO poisoning or some other method, is beyond the scope of this investigation.
First-stage installer: Telegram
As mentioned above, the initial investigation of these attacks involved a malicious Telegram installer. Later in this article we’ll see variations in which other “lure” applications were used, but Telegram was by far the most common lure, and dissecting it provides a good example of how the attack works.
When the malicious Telegram installer (SHA256: 097899b3acb3599944305b064667e959c707e519aef3d98be1741bbc69d56a17) is run, it installs and executes the sideloading package.
Figure 5: This setup screen is actually an evil wizard
It installs multiple components on the system, dropping them to a directory in the user data folder:
Figure 6: Gifts of the evil setup wizard
It also creates a shortcut on the desktop. However, this shortcut does not execute the Telegram program, but an unusual command:
C:UsersredactedAppDataRoamingTg_B518c1A0Ff8CappR.exe /s /n /u /i:appR.dat appR.dll
Figure 7: Its reg description is Bandit, which is accurate
Figure 8: A mostly transliterated version of the Telegram desktop UI
But behind the scenes it drops various sideloading components to a directory:
Figure 9: A directory with problematic files deposited in it
The installer also creates a shortcut file in the user’s startup directory. In this way, the malware establishes persistence and allows for automatic execution after system startup.
Figure 10: A fairly innocuous-looking shortcut is anything but; note “Application.exe,” which we’ll see again in the next stage of the attack
The sideloading components and the startup link are only created when the desktop Telegram link is executed. This could be an anti-analysis trick, since dynamic analysis sandboxes would not see the dropped sideloader files.
A first-stage variation: LetsVPN installer
We also found a trojanized installer for LetsVPN (SHA256: e414fc7bcd80a75d57ee4fdbb1c80a90a0993be8e8bbbe0decfc62870a2e1e86). The malicious parts of the package are the same as in the Telegram cases, but the bundled clean application is LetsVPN:
Figure 11: The LetsVPN variation we found is translated into Chinese on its initial screen, but the installation screen is in English
Figure 12: The icon has changed, but the application to which it truly points remains the same
One more first-stage variation: WhatsApp installer
In one case, we did not have direct contact with the installer file, but our telemetry shows that running a file called Whatsapp.msi also leads to the installation of the malicious files we saw in the other two first-stage examples.
roamingwhatsapp_ae2b02appmain.exe : 91e4eb7517f55ac93b1da109539aa0011e9346be41704dc0da360ebad0f3f63d
roamingwhatsapp_ae2b02appr.dll : e25289d44403a6f6132a470fdbe6b46eade466d08eca0ad44fca519592c54fdf
roamingwhatsapp_ae2b02appr.exe : fffa7a97fba9dfb235f969ecce0e5c4a71a48a37c1bc79b77cd78f0ab72f993d
roamingwhatsapp_ae2b02littleunzip.exe : 81046f943d26501561612a629d8be95af254bc161011ba8a62d25c34c16d6d2a
roamingwhatsapp_ae2b02app-2.2232.8whatsapp.exe : 8d92c7d7f301bc0e4965dbd9253933a4580883805119dd7c27788d04c17d595e
c:userspublicapplication2application.exe : c936f1598721a9a92d7f31c6c13b55013b8a2a344e3df4156e5b033006336544
c:userspublicapplication2xlgameupdate.exe : 769d59d03036af86c7a9950f03ebc7b693a94d3e2f8ecd1d74cf5600ab948105
c:userspublicapplication2libexpat.dll : 31d2076066107bd04ab24ff7bbdf8271aa16dd1d04e70bd9cc492e9aa1e6c82b
c:userspublicapplication2basicnetutils.dll : ae2e145b36ab2ed129a2d34de435b76a1f4e5a4820d9d623e7018b87f24d0648
Second stage: More sideloading
As mentioned, one of the most exciting things about this investigation was spotting a new variation on DLL sideloading – the use of a second “clean” application as a secondary stage in the attack. In these unusual attacks, the beginning (first-stage loader) and the end (payload) were the same; the only difference was in this second-stage sideloading.
In Figure 8 above, we pointed out “Application.exe,” for which the installer left a shortcut on the desktop. In Figure 11 we see it again. It’s actually the program XLGame.exe, signed by Shenzhen Thunder Networking Technologies Ltd, but renamed by the attackers to Application.exe. It has a clean dependency, libexpat.dll, which is part of the package.
Figure 13: The attackers used a clean-but-vulnerable application (named “Application.exe” on the desktop, but really XLGame.exe) that auto-updates itself if it finds a file with a specific name. The names of malicious files are shown in the orange boxes to the right as before, and files renamed by the attacker are shown in quotation marks
Figure 14: XLGame’s digital signatures would seem to indicate everything is in order, despite being renamed to Application.exe
XLGame will automatically perform an automatic update if it finds a program named XLGameUpdate.exe in the same directory. The loading process makes use of this auto-update functionality, as the malicious package contains an executable with this name — but it’s not the real XLGameUpdate.exe. Rather, it is a clean, signed .exe from Beijing Baidu Netcom Science and Technology Co.,Ltd.
Figure 15: XLGameUpdate.exe is actually a different, unnamed application, but renamed to trick “Application.exe” (really, XLGames.exe) into running it
And now we return to the usual DLL-sideloading process. This second-stage loader has a dependency, BASICNETUTILS.dll, which the attackers have replaced with a malicious loader DLL. The malicious loader DLL finds templateX.txt in the same directory, loads the content, decrypts the payload loader shellcode, and executes it. (All these files are of course located in the same directory, as seen in Figure 7 above.)
Second stage: More sideloading (a variation)
As noted in the introduction, the attackers appear to be very fond of their double-dip DLL sideloading strategy, swapping various clean apps into the new spot in the sideloading process. Figure 16 shows a flow very similar to the previous scheme, but the clean executable is different in the second-stage loader. Consequently, the malicious loader DLL has to be renamed to reflect the dependency of the replaced clean application.
Figure 16: The attackers are running the same extra-step playbook as in Figure 13, but they’ve swapped in a new program in the “XLGameUpdate.exe” spot; by extension, the to-be-swapped DLL shown at upper right must change as well. Again, the names of malicious files are shown in the orange boxes to the right, and files renamed by the attacker are shown in quotation marks
As before, “Application.exe” is actually XLGames.exe. The second-stage clean loader is renamed once again to XLGameUpdate.exe, but its original (real) name is KingdomTwoCrowns.exe. It is not digitally signed, so it’s not clear what the benefit might be of replacing the clean, signed loader from Baidu with this one.
Figure 17: It’s still not XLGameUpdate, but this time it’s actually “KingdomTwoCrowns”
It has the following PDB path:
This second-stage loader is used for the usual sideloading scenario; its dependency, UNITYPLAYER.dll, is replaced with a malicious loader DLL. The malicious loader finds templateX.txt in the same directory, loads the content, decrypts the payload loader shellcode, and executes it.
Thus, the second-stage clean loader is different, but the second-stage malicious loader and the payload files in this variation are essentially the same as in the variation described in the previous section (aside from being renamed). In fact, one of the encrypted payload files (3fc9405cfe9272323bd96aacfd082c16b392fea6e0f108545138026aa6f79137) was used in both scenarios. (We’ll discuss the payload in the final section of this article.)
Second stage: More sideloading (one more variation)
Once again, this scenario swaps out the clean executable in the second-stage loader, this time abusing a clean, digitally signed tool once offered by HP. This is very similar to the previous scheme, but since the clean executable is once again different in the second-stage loader, the malicious loader DLL has to once again be renamed to reflect the different dependency.
Figure 18: One more variation on the double-dip sideloading theme, with an HP tool in the XLGameUpdate spot at center-top and yet another DLL in the highlighted malicious spot at upper right. Once again the names of malicious files are shown in the orange boxes to the right, and files renamed by the attacker are shown in quotation marks
The second-stage clean loader is again renamed to XLGameUpdate.exe. Its original name is d3dim9.exe. It is digitally signed by HP Inc.
Figure 19: This time, the application renamed as XLGameUpdate is really a signed, clean application from HP
This second-stage loader is used for the usual sideloading scenario. Its dependency, d3dx9_43.dll, is replaced with a malicious loader DLL. That DLL finds templateX.txt in the same directory and – once again — loads the content, decrypts the payload loader shellcode, and executes it.
Third stage: At last, the malicious DLL
The second-stage loaders had interesting variations, but all roads lead to one thing: cryptowallet theft. To that end, the payloads we saw in this investigation were fairly constant.
At the end of stage 2, the clean second-stage loader (whichever one is in use) calls a specific DLL – and get the malicious, identically named version the attackers have placed in the same directory, in the classic DLL-sideloading fashion. The malicious DLL loads the payload from the file template.txt, then decrypts it.
The payload’s encryption is a simple combination of bytewise SUB and XOR:
int __fastcall decrypt(int a1, int a2)
int result; // eax
for ( result = 0; result < a2; ++result )
*(_BYTE *)(result + a1) = (*(_BYTE *)(result + a1) – 122) ^ 0x19;
The decrypted content is a loader shellcode, which decompresses and executes the final payload. This execution log shows this decompression of the final payload:
40148e VirtualAlloc(base=0 , sz=20a00) = 600000
4016bd RtlDecompressBuffer(fmat=102,ubuf=600000, usz=20a00, cbuf=4016e3, csz=16789) (Outsz: 20a00) = 0
4011e2 VirtualAlloc(base=0 , sz=26000) = 621000
4011f9 RtlMoveMemory(dst=621000, src=600000, sz=400)
401235 RtlMoveMemory(dst=622000, src=600400, sz=17e00)
401235 RtlMoveMemory(dst=63a000, src=618200, sz=4c00)
401235 RtlMoveMemory(dst=63f000, src=61ce00, sz=1800)
401235 RtlMoveMemory(dst=643000, src=61e600, sz=200)
401235 RtlMoveMemory(dst=644000, src=61e800, sz=2200)
Figure 20: The decompression of the final payload
After this, the shellcode loads the final payload DLL into memory and executes it.
Fourth stage: The payload
The payload DLL contains one export, rudely named:
0 1 0x14780 0x15380 F■ck
This creates a flag key in the registry. The name of the key will be HKCUSOFTWARE%COMPUTERNAME%, if GetComputerName returns a value; otherwise UnkNow will be used.
Figure 21: The flag key picked up the name of the machine on which this exploit was dissected
Multiple values are stored under this key:
Time: records the date and time of installation of the malware
CopyC: updated C2 address (encoded with bytewise XOR 5 + BASE64)
ARPD: list of names, separated with