A doubled “Dragon Breath” adds new air to DLL sideloading attacks

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

Here appR.exe is the regsvr32.exe Windows component, renamed. It will execute the appR.dll library, which is another renamed Windows component, scrobj.dll — the script execution engine. It will then execute the Javascript code stored in appR.dat:

Figure 7: Its reg description is Bandit, which is accurate

When the shortcut is executed, the JavaScript code runs. To the user, it displays the expected Telegram desktop UI, mostly in Chinese:

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

As the Telegram installer did, it creates a shortcut on the desktop. The program that the shortcut launches invokes the JavaScript code that does the ultimate installation of the sideloading package.

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;
  return result;

The decrypted content is a loader shellcode, which decompresses and executes the final payload. This execution log shows this decompression of the final payload:

4010ae    GetProcAddress(LoadLibraryA)
4010ae    GetProcAddress(VirtualAlloc)
4010ae    GetProcAddress(VirtualFree)
4010ae    GetProcAddress(lstrcmpiA)
401153    LoadLibraryA(ntdll)
4010ae    GetProcAddress(RtlZeroMemory)
4010ae    GetProcAddress(RtlMoveMemory)
40148e    VirtualAlloc(base=0 , sz=20a00) = 600000
401635    GetProcAddress(LoadLibraryA)
401697    LoadLibraryA(ntdll)
401635    GetProcAddress(RtlDecompressBuffer)
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)
4012ed    LoadLibraryA(KERNEL32.dll)

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:

dllname: ServerDll.dll
  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

Latest Posts