Threat Research

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

Exploits of the venerable vulnerability gain in complexity

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.

A flow chart showing the genericized flow of the double-loading technique described in the article

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.

Map highlighting the affected areas -- China, Hong Kong, Japan, Philippines, Singapore, Taiwan

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.

A (fake) Telegram installation csreen

Figure 3: Clicking the ‘Windows” button from the Windows download page meant nothing when our browser reported itself as Android…

Another fake Telegram installation screen

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.

The fake setup wizard

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:

A file directory showing multiple components and a subdirectory

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:\Users\{redacted}\AppData\Roaming\Tg_B518c1A0Ff8C\appR.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:

The registry entry for the fake installer

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:

The desktop installer for the fake Telegram

Figure 8: A mostly transliterated version of the Telegram desktop UI

But behind the scenes it drops various sideloading components to a directory:

A file directory showing the application, two DLLs, a readme, and the second (updater) application

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.

A closer look at properties of the "Application.exe" item from the previous screenshot

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:

The first half of a screen capture showing the LetsVPN variation of the malwareThe second half of a screen capture showing the LetsVPN variation of the malware

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.

The same file called "Application.exe" above, showing the different icon

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.

\roaming\whatsapp_ae2b02\appmain.exe : 91e4eb7517f55ac93b1da109539aa0011e9346be41704dc0da360ebad0f3f63d

\roaming\whatsapp_ae2b02\appr.dll : e25289d44403a6f6132a470fdbe6b46eade466d08eca0ad44fca519592c54fdf

\roaming\whatsapp_ae2b02\appr.exe : fffa7a97fba9dfb235f969ecce0e5c4a71a48a37c1bc79b77cd78f0ab72f993d

\roaming\whatsapp_ae2b02\littleunzip.exe : 81046f943d26501561612a629d8be95af254bc161011ba8a62d25c34c16d6d2a

\roaming\whatsapp_ae2b02\app-2.2232.8\whatsapp.exe : 8d92c7d7f301bc0e4965dbd9253933a4580883805119dd7c27788d04c17d595e

c:\users\public\application2\application.exe : c936f1598721a9a92d7f31c6c13b55013b8a2a344e3df4156e5b033006336544

c:\users\public\application2\xlgameupdate.exe : 769d59d03036af86c7a9950f03ebc7b693a94d3e2f8ecd1d74cf5600ab948105

c:\users\public\application2\libexpat.dll : 31d2076066107bd04ab24ff7bbdf8271aa16dd1d04e70bd9cc492e9aa1e6c82b

c:\users\public\application2\basicnetutils.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.

A version of the flowchart shown in Figure 1, highlighting how it works in the specific case of XLGame

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

Three views of images showing digital signatures related to XLGame

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.

Three images showing the signatures related to the fake XLGameUpdate application

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.

The flowchart from Figures 1 and 13, showing the specifics for the XLGame version of the attack

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.

A Properties screen showing that XLGameUpdate is once again not that program

Figure 17: It’s still not XLGameUpdate, but this time it’s actually “KingdomTwoCrowns”

It has the following PDB path:

C:\buildslave\unity\build\artifacts\WindowsPlayer\Win32_nondev_i_r\WindowsPlayer_Master_il2cpp_x86.pdb

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.

The flowchart form Figure 1, 13, and 16, showing the change to the clean second-stage executable

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.

A Properties screen showing that once again, XLGameUpdate is not what it seems

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)

The payload decompressed

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 HKCU\SOFTWARE\%COMPUTERNAME%, if GetComputerName returns a value; otherwise UnkNow will be used.

The flag key

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 | . creates new thread for each; searches for strings isARDll, PluginMe, getDllName – may be export names
  • ZU: value is used in the procedure that reads the wallet seed for the Chrome extension; likely provides destination information for exfiltration of wallet contents
  • Remark: stores the hostname

The backdoor supports a set of numeric command codes:

Code Action
0 Shutdown/Reboot/Logoff
1
2 Set registry key “Remark”
3 Set registry key “ZU”
4 Clear event logs
5 Get status of nkbihfbeogaeaoehlefnkodbefgpgknn extension
6 Download and execute file
8 Execute command with ShellExecute, visible window
9 Execute command with ShellExecute, hidden window
112 Get clipboard content
113 Set clipboard content
125 Executes command in a hidden cmd window
126 Writes buffer to file and executes it
128 Sets registry key CopyC
35-37,101-111, 127 Checks for exports PluginMe, isARDL, getDllName, isCSDll, and perhaps more

 

It also contains a string related to MetaMask. MetaMask is a crypto (Ethereum) wallet available as, among other things, a Chrome extension. In the past, attackers looking to steal from cryptowallets have targeted users who have installed this extension, and that’s what appears to be happening here.

C:\Users\%s\AppData\Local\Google\Chrome\User 

C:\Users\%s\AppData\Local\Google\Chrome\User Data\Default\Extensions\nkbihfbeogaeaoehlefnkodbefgpgknn\

The C2 server name, nsjdhmdjs[.]com, has been associated with Operation Dragon Breath (aka “APT-Q-27” or “Golden Eye Dog,” as above). Some of the DLL sideloading characteristics we’ve demonstrated and also the ServerDll.dll name are likewise characteristic of this threat actor.

Fourth stage: Payload variations – a debug build version and the gh0st of a sample

We also found, on VirusTotal, a specific version of the payload (SHA256: d86f1292d83948082197f0a29fcb69fdec9feb4bf3898d7b8e693c7d5a28099c) that contained more internal information than usual. This is also an executable, unlike the usual payloads (which are DLLs).

The PDB path is the usual:

D:\Work\3远控\企业远程控制\Debug\ServerDll.pdb

In this case, however, it contains the source code of the infamous gh0st RAT. The source archive is supposed to be dropped by one of the procedures, but that code is never executed:

  hFile = CreateFileA(lpFileName, 0x40000000u, 1u, 0, 2u, 0, 0);

  if ( hFile == (HANDLE)-1 )

    v4 = 0;

  if ( WriteFile(hFile, &gh0st_rat_src, 0xE5B1Au, &NumberOfBytesWritten, 0) )

    v4 = 1;

  CloseHandle(hFile);

  return v4;

For this sample, the C2 server is 23[.]225[.]147[.]227.

We also saw on VirusTotal a similar sample (sha256: 64613eadd91a803fe103bef5349db04ddfc01b8d115ba7a24a694563123d38ad) that contained gh0st RAT source code, but no debug information and no PDB information. Both these debug versions were submitted to VirusTotal from Hong Kong, one of the regions known to be affected, so it is likely they were indeed used in attacks.

A full list of IoCs is available on our GitHub.

Conclusion

DLL sideloading, first identified in Windows products in 2010 but prevalent across multiple platforms, continues to be an effective and appealing tactic for threat actors. This double-clean-app technique employed by the Dragon Breath group, targeting a user sector (online gambling) that has traditionally been less scrutinized by security researchers, represents the continued vitality of this approach. While speculation about future uses of the technique is beyond the scope of this post, it may be useful for defenders to keep an eye out for the behavior we’ve documented here.

Acknowledgements

Thanks to Xinran Wu of SophosLabs and Andrew Brandt of X-Ops Comms for their assistance on this writeup.