Comprehensive Analysis of ArmouryLoader – Series Analysis of Typical Loader Families (Five)

The original report is in Chinese, and this version is an AI-translated edition.

Introduction

With the development of network attack technology, the malware loader is becoming the key component of malware execution. Such loaders are a malicious tool used to load various malware into an infected system and are typically responsible for bypassing system security protections, injecting malware into memory and executing, Lay the foundation for the subsequent deployment of malware of the Trojan type. The core functions of the loader include persistence mechanisms, fileless memory execution, and multi-level avoidance techniques.

Antiy CERT has been tracking the reserves of typical malicious loader families over the last few years, aggregating information into special reports and continuing to track new popular loader families. This project will focus on the technical details of the loader, and dig into its core functions in the attack chain, including its obfuscation technology, encryption mechanism and injection strategy. In addition, we will constantly improve our security product capability, take effective technical solutions to further improve that recognition rate and accuracy rate of loader, and help user organizations to identify and prevent potential threats in advance.

1.Overview

The ArmouryLoader  was first discovered in 2024 and has been used to deliver families of malware such as SmokeLoader and CoffeeLoader. The loader is loaded by hijacking the export function of Asus’s Armoury Crate system management software, hence the name ArmouryLoader. The ArmouryLoader has the functions of lifting the weight, persisting and delivering the target payload, and has the capability of resisting the EDR (End Point Detection and Response), so that the subsequent delivering payload can break the system defense line more easily.

The ArmouryLoader will call the OpenCL decryption payload in the loading stage, and it needs the running environment to have GPU or 32-bit CPU to run normally, which can avoid sandbox and virtual machine environment. When ArmouryLoader delivers the target payload, it uses the code segment of the legal DLL in the system to read the sensitive memory and call the system functions. on this basis, it forges the call stack and hides the initiator of the system call to avoid EDR detection. Through the above means, Armoury Loader has strong concealment, which makes it difficult to be detected in sandbox and terminal environment, which improves the success rate of target load delivery and poses a threat to the system security of users.

For more information about this loader, see the Antiy VirusView (Virus Encyclopedia).

Figure 1-1 Long press the identification QR code to view details of the HijackLoader


2.Analysis of the Survival Technology of ArmouryLoader

2.1 Confusing technical analysis

Armoury Loader has three ways of obfuscating code, including adding useless instructions, code self- decryption, and decryption using OpenCL.

Among them, ArmouryLoader has obfuscated code filled with useless instructions in the first and third phases.

Figure 2-1 Useless directive added by ArmouryLoader


Self-decrypting codes are present in the second, fourth and sixth stages to interfere with analysis.

Figure 2-2 Armoury self-decrypting code


In addition, ArmouryLoader will use OpenCL to decrypt that code in the third phase, increase the difficulty of analysis and increase the requirement for the running environment device.

Figure 2-3 ArmouryLoader uses OpenCL to decrypt code


2.2 Analysis of Right-lifting Technology

In the fifth stage, ArmouryLoader will try to use CMSTPLUA COM component to propose authority. in the process of proposing, ArmouryLoader will disguise itself as explorer. exe, and then call the function to obtain the permission of Administrator.

Figure 2-4 ArmouryLoader using the COM component to assign weights


2.3 Analysis of Persistence Technology

Armouryloader is persisted by scheduling tasks. Depending on the version, ArmouryLoader is persisted using either the system tool schtasks or the scheduled task COM component.

Regardless of the manner of persistence, when you have administrator privileges, ArmouryLoader will choose to trigger with user login and obtain the highest privileges, otherwise ArmouryLoader will execute with normal privileges every 30 minutes.

Figure 2-5 Scheduled Tasks Running with Top Privileges


In addition, ArmouryLoader adds systematic, hidden, and read-only attributes to persisted files, and modifies ACLs that deny users to modify and delete files.

Figure 2-6 ArmouryLoader Sets file properties


2.4 Analysis of countermeasures technology

Armouryloader will read sensitive location memory through special gadgets in legitimate DLLs.

Figure 2-7 ArmouryLoader reads sensitive memory data from a gadget


Armouryloader also avoids detection by spoofing the call stack when calling sensitive functions in stages 3 and 8.

Figure 2-8 ArmouryLoader Forges Function Call Stack


Armouryloader will also obtain the system function call number through Halo’s Gate, which has certain anti-syscall hook capability and can directly perform the system call.

Figure 2-9 ArmouryLoader searches for system call numbers using Halo’s Gate technology


3.Attack process

The ArmouryLoader has eight stages, each of which is relatively independent and completes the delivery of the final load in steps. Stages one, three, five, and seven of the ArmouryLoader are responsible for performing specific malicious actions, while stages two, four, six, and eight are responsible for loading the PE payload of the next stage.

Table 3-1 Malicious Behavior in Different Stages of ArmouryLoader

Loading phase Malicious acts
Phase 1 Hijacking the Armoury Crate export function and running the second stage shellcode
Phase II Decrypt and run the third phase PE file
The third stage Decrypt and run the fourth phase of shellcode through OpenCL
Phase IV Decrypt and run the fifth phase PE file
Phase V Carry out the claim and persistence, and run the sixth phase shellcode
Phase VI Decrypt and run the seventh phase PE file
Stage 7 Inject the shellcode of the eighth phase into the 64-bit dllhost. exe
Phase VIII Load and run the target load

4.Sample analysis

4.1 Sample labels

Table 4-1 ArmouryLoader Sample Tags

Virus name Trojan / Win32.ArmouryLoader
Original file name Armoury A.dll
Md5 5a31b05d53c39d4a19c4b2b66139972f
Processor architecture X86
File size 1.41 MB (1,480,552 bytes)
File format Binexecute / Microsoft.EXE [: X86]
Time stamp 2023-12-13 15: 31: 16
Digital signature Asustek COMPUTER INC. (Digital signature is invalid)
Shell type None
Compiled Language Microsoft Visual C / C + + (19.16.27049)
Vt First Upload Time 2024-09-12 18: 34: 23
Vt test result 33 / 72

4.2 The first phase of the ArmouryLoader loader

Armourya. dll is a part of Asus’s Armoury Crate program, and the ArmouryLoader loader runs by hijacking the free Buffer of ArmouryA. dll export function.

This function contains a large amount of useless code to interfere with security personnel’s analysis and will eventually decrypt and execute the second stage payload.

Figure 4-1 ArmouryLoader decrypts and executes the second stage code


4.3 Phase II of the ArmouryLoader

In that second phase of the armoury load, there is a large amount of self-decrypting code to hinder static analysis.

Figure 4-2 ArmouryLoader self-decryption code


In that second phase, the armouryloader load the CreateThread function through the PEB and creates a new thread to execute the subsequent logic.

Figure 4-3 ArmouryLoader creates a new thread and executes the subsequent logic


In the new thread, ArmouryLoader reads the third phase PE file from the two phase payload and loads it into memory for execution.

Figure 4-4 ArmouryLoader Loads the third phase of the PE file


4.4 The third phase of the ArmouryLoader loader

In that third phase, the armouryloader load the OpenCL library and decrypts the fourth phase payload through OpenCL. This phase calls Nvidia, AMD, or Intel devices through the OpenCL library to decrypt shellcode.

Figure 4-5 ArmouryLoader Looking for OpenCL-usable devices

Then ArmouryLoader will XOR the two strings to generate the decryption key, and then the key and the ciphertext will be transmitted to the OpenCL device for XOR decryption, and the Shellcode of the next stage will be obtained for execution.

Figure 4-6 ArmouryLoader uses an OpenCL device to decrypt shellcode


In subsequent releases, this phase load adds a lot of confusion, making it difficult to analyze.

Figure 4-7 ArmouryLoader Phase 3 Confusion


In subsequent release, that frame stack of the function is also falsified by way of construct ROP chains to combat stack backtracking. Taking a program call to GetModuleHandleW as an example, the function in the figure will set the EIP to the GetModuleHandleW function address via the ret 4 instruction, and then unstack the four bytes. At this point, the top of the stack will leave the return address of the GetModuleHandleW function, RtlCreateMemoryBlockLookside + 88, and the string pointer of the function’s parameter, OpenCL.dll. Rtlcreatememoryblocklookside + 88 is actually an assembly instruction of jmp [EBX]. When the GetModuleHandleW function returns, the real return value of the function will be read from the EBX address and set to the EIP to return the control flow of the program.

Figure 4-8 ArmouryLoader Construction of ROP chain against stack traceback


4.5 The fourth stage of the ArmouryLoader

In that fourth phase, the armoury load decrypts and load the fifth phase PE file and executes it in memory.

This phase also has self – decryption logic, but there are fewer layers of encryption, and loop instructions are used to control the loop rather than the jnz of the second phase.

Figure 4-9 ArmouryLoader executes self-decryption logic


After decryption, ArmouryLoader will load the PE file in memory and execute it.

Figure 4-10 ArmouryLoader Loads PE Files to Memory


4.6 The fifth stage of the ArmouryLoader

In that fifth stage, the armoury load first detects whet the program has elevated permissions or belong to a system user group, and selects different persistence location based on the permissions.

Figure 4-11 ArmouryLoader detecting process permissions


The ArmouryLoader then copies itself under% PROGRAMDATA% or% LOCALAPPDATA% and sets the file system, hide, and read-only properties.

Figure 4-12 ArmouryLoader moves itself to a specific directory


Then ArmouryLoader will also add the ACL list of files to prevent users from deleting or modifying their own programs.


Figure 4-13 List of ACL Changes to ArmouryLoader Files


Armouryloader will then persist by creating a scheduled task called AsusUpdateServiceUA that runs every 30 minutes through schtasks.


Figure 4-14 ArmouryLoader persistence through schtasks to create scheduled tasks


If you have administrator privilege, ArmouryLoader will execute with that high privilege when the user logs on.

Figure 4-15 ArmouryLoader Running Scheduled Tasks with Highest Privileges


In newer versions, ArmouryLoader will try to invoke the rights using COM components, in which case ArmouryLoader will first modify the process information in PEB and LDR _ DATA _ TABLE _ ENTRY.

Figure 4-16 ArmouryLoader Modifying Process Information


Then the weights are extracted by the COM component CMLuaUtil.

Figure 4-17 ArmouryLoader using COM components to propose weights


In subsequent update, ArmouryLoader use COM components in place of that schtasks program to create schedule tasks.

Figure 4-18 The ArmouryLoader uses the COM component to create a scheduled task


When you do not have System permissions, the scheduled task is triggered every 10 minutes.

Figure 4-19ArmouryLoader sets a scheduled task that is triggered every 10 minutes


When you have System permissions, ArmouryLoader is set to run the program with the highest permissions.

Figure 4-20 ArmouryLoader Setting Scheduled Task Run Permissions


At this time, the ArmouryLoader scheduled task will be logged in and triggered.

Figure 4-21 ArmouryLoader Setting Scheduled Task Login Trigger


Then run shellcode to execute the next phase.

Figure 4-22 Load the sixth phase of ArmouryLoader execution


4.7 The sixth stage of the ArmouryLoader loader

The sixth stage has the same function as the fourth stage, and is responsible for decrypting and loading the next stage PE files.

Figure 4-23 ArmouryLoader completes redirection and calls the next stage PE file entry point


4.8 Armouryloader 7 Stage of Loader

In phase 7, ArmouryLoader will create a 64 – bit dllhost. exe process and inject shellcode into it to change the runtime environment from 32 – bit to 64 – bit.

Armouryloader first turns off file redirection and creates a 64 – bit dllhost. exe process.

Figure 4-24 ArmouryLoader turns off file redirection


The ArmouryLoader will then search for some 64-bit DLLs to hijack the main process, in which the ArmouryLoader will frequently execute 64-bit code using the door of heaven technology.

Figure 4-25 ArmouryLoader executes 64-bit code through the gates of heaven

Through the Heaven’s Gate, ArmouryLoader can call functions in 64-bit DLLs. As shown in the figure, ArmouryLoader can search and call 64-bit functions through get _ dll64, get _ func64, and call _ func64. Then the specific function is encapsulated to call the 64- bit function just like the normal function.

Figure 4-26 ArmouryLoader encapsulates a 64- bit NtGetContextThread


Finally, the 64- bit shellcode is executed in dllhost. exe by hijacking the main process.

Figure 4-27 ArmouryLoader hijacking the 64-bit dllhost. exe main process


4.9 Armouryloader phase 8

In the eighth stage, ArmouryLoader first obtains the addresses of ZwAddBootEntry, NtAllocateVirtualMemory and NtProtectVirtualMemory functions, and searches for the corresponding system call number.

Figure 4-28 Armoury search function and system call number


In the new version of ArmouryLoader, ArmouryLoader will search ntdll for a gadget of mov rax, [rax]; ret;, and read sensitive memory areas through the gadget to fool EDR that the read behavior is issued by ntdll.

Figure 4-29 ArmouryLoader indirectly reads data through a gadget


Armouryloader will try to search the function for a specific sequence of bytes to get the call number.

Figure 4-30 ArmouryLoader Search System Call Number


If that object function is hook, it will cause ArmouryLoader to fail to search for the byte sequence, which in turn will cause the system call numb to be unavailable. At this point, ArmouryLoader will use the Halo’s Gate technology to further search for the system call number. This technique searches for neighboring Zw functions, from which the system call number is retrieved. The system call number of the objective function can be calculated according to the distance between the adjacent function and the objective function.

Figure 4-31 ArmouryLoader searches for system call numbers using Halo’s Gate technology


In that new version of armoury load, the algorithm is further improved. The ArmouryLoader no longer assumes the size of the Zw function to be 32 bytes, but calculates the minimum spacing of the Zw function through the derivation table of the traversal function to obtain the size of the Zw function.

Figure 4-32 ArmouryLoader Calculates the Minimum Spacing of Zw Function


After searching for the system call number, ArmouryLoader uses NtAllocateVirtualMemory and NtProtectVirtualMemory to request memory space for the final target payload. In this process, ArmouryLoader will first calculate the system function that will be called using syscall in the ZwAddBootEntry function with the system call number. And forge the call stack on this basis.

The procedure searches kernel32. dll for a jmp [rbx] gadget that returns the control flow after the function call ends.

Figure 4-33Armoury Search jmp [rbx] gadget


Then ArmouryLoader obtains the RUNTIME _ FUNCTION information of the function through ExceptionDir in the .pdata section, so as to find the UnwindInfo of the function, where the UnwindInfo contains the frame stack size information of the function.

Figure 4-34 RUNTIME _ FUNCTION information of ArmouryLoader search function


Armouryloader then uses UnwindInfo to calculate the frame stack size of the function where the jmp [rbx] gadget is located and BaseThreadInitThunk and RtlUserThreadStart for subsequent forgery.

Figure 4-35 ArmouryLoader Calculating Function Stack Size


Armouryloader then places the jmp [rbx] gadget at the return address of syscall, and the pointer to the function’s true return address is placed in the rbx register to implement the return control flow. The frame stacks of BaseThreadInitThunk and RtlUserThreadStart functions will be deployed on subsequent call stacks to fool EDR into thinking that syscall is sent from RtlUserThreadStart to BaseThreadInitThunk via a function in kernel32.

Figure 4-36 ArmouryLoader Forges Call Stack


After allocating the memory space, ArmouryLoader copies the final target payload to the specified memory area, completes the redirection, and calls the program entry point to complete the posting. According to the final C2 domain name, the target payload of ArmouryLoader delivery is CoffeeLoader.

Figure 4-37 CoffeeLoader C2 Address


5.IoCs

IoCs
5a31b05d53c39d4a19c4b2b66139972f
90065f3de8466055b59f5356789001ba

6.ATT&CK Mapping Map of Samples

Figure 6-1 Mapping of Technical Features to ATT&CK


Specific ATT & CK technical behavior description table:

Table 6-1 ATT&CK Technical Behavior Description

ATT&CK stages / categories

Specific behavior

Notes

Persistence

Utilization of planned tasks / jobs

Armouryloader is persistent by scheduling tasks

Abuse of enhanced control authority mechanism

Abuse of enhanced control authority mechanism

Armouryloader carries on the authority through the COM component

Defensive evasion

Anti-obfuscate / decode files or information

Armouryloader has a large number of XOR-encrypted code segments

Armouryloader decrypts the code through OpenCL

Armouryloader executes 64-bit code through the Heaven’s Gate

Modify file and directory permissions

Armouryloader prohibits user changes and deletions by adding ACL records

Concealment

Armouryloader adds hidden, system, and read-only properties to persisted files

Execute orders indirectly

Armouryloader reads the target memory through the system DLL widget

Armouryloader directly calls system functions through syscall

Armoury Loader Forges Call Function Call Stack

Counterfeit

Armouryloader disguises Asus system management software and has an invalid digital signature

Confusion of documents or information

The ArmouryLoader code has confusion

Armouryloader retrieves the API through a hash

7.Antiy IEP helps users defend against loader threats

After testing, the terminal security products of Antiy IEP, relying on Antiy’s self-developed threat detection engine and core-level active defense capability, can effectively detect, kill and defend the virus samples found this time.

Antiy IEP can monitor the local disk in real time and automatically detect the virus of new files. In response to this threat, when a user stores the ArmouryLoader loader locally by receiving email attachments, transmitting WeChat messages and downloading via the network, it will immediately alert the virus and clear malicious files. Prevent the terminal from being attacked by the user boot file.

Figure 7-1 When a virus is found, the first time a virus is captured and an alarm is sent


Antiy IEP also provides a unified management platform for users, through which administrators can view details of threats within the network in a centralized manner and handle them in batches, thus improving the efficiency of terminal security operation and maintenance.

Figure 7-2 The IEP Management Center assists the administrator to realize efficient terminal security management


Appendix: Antiy LanDi VILLM (Virus Inspection Large Language Model)

Antiy LanDi VILLM can carry out automatic analysis on the samples. part of the analysis contents are as follows:

Based on the provided logs and analysis results, the following are detailed conclusions and explanations:

  1. Judgment conclusion

Evaluation result: Doubtful (accuracy: About 95%)

  1. Detailed explanation
  2. Basis of feature matching and judgment:
    • Malicious API call: Multiple call of certificate-related API in log, such as GetDeviceIndex, FreeEnvironmentStrings, CertGen, etc. These APIs are often used to handle certificate and security-related tasks, and malware often use these APIs to perform malicious operations, such as bypassing certificate verification and obtaining private keys.
    • String analysis: The log contains a large number of certificate-related URLs and strings, such as crl3. digicert .com, ocsp. digicert, ccerts. Digicert .com, etc. These domain names are usually associated with the CA authority associated with the digital certificate.
    • Obfuscating and coding: Obfuscating snippets of code that appear in logs (such as?? Indicating that it is not selected for use as a feature) may be used to hide malicious behavior, increasing the difficulty of detection.
    • Abnormal behavior pattern: Multiple repeated byte patterns in the log (for example, 04 81 AD 30 81 AA 30 53 A0 51 A0 4F 86 4D 68 74 74 70 3A 2F 2F 63 72 6C) 33 2E 64 69 69 63 65 72 74 2E 63 6F 6D), which may be used to populate data or hide malware.
  3. malware characteristics:
    • Certificate-related operations: There are certificate-related API calls that may be used to obtain, verify, or use certificates for malicious communication.
    • Obfuscation and encryption: The log contains a lot of obfuscated code, which increases the complexity of detection and may be used to hide malicious behavior.
    • Exception string: Multiple domain names and paths associated with digital certificates appear, which may be used to bypass security detections or conduct malicious communications.
  4. Assessment accuracy:
    • High confidence feature: There are many features matching with malware features in the log, which increases the accuracy of detection.
    • Potential ambiguity: Some features (such as?? Indicates that it is not selected for use as a feature) may hide malicious behavior, but the overall feature still shows a high degree of suspicion.
  5. Conclusion

According to the above analysis, the log contains a number of certificate-related and suspicious API calls and strings, which conform to the typical behavior patterns of malware. Therefore, it is reasonable for the analysis tool to determine that the file is Trojan. Win32. Shipcome (or similar malware family).

Accuracy assessment: Approximately 95%

According to the national standard draft, the threat classification is Trojan. Win32. Spybind, and the YARA rules for automatic feature extraction are as follows:

Rule Trojan. Win32.shipcome: Trojan {

Meta:

Description = “This is a section of YARA rules generated by the VILLM V2 model. used to detect Trojan. Win32.shipcome.”

Strings:

$a = {f7 d3 4f 33 f8 c1 c6 17}

$b = {c1 ce 17 33 f8 47 f7 d3}

$c = {4e 33 c3 33 cf f7 d0 33 c5 c1 cf 17 4e 4b}

$d = {f7 d0 f7 d0 87 c7 f7 d2}

$e = {4b 33 cd 87 c1 ff e0}

Condition:

All of them

}

Antiy LanDi VILLM is the first threat detection generation algorithm registered by the State Cyberspace Administration in China. The model is trained based on the massive sample feature engineering data accumulated over the past 20 years by Antiy Cyber Super-brain. The training data includes file identification information, decision information, attribute information, structure information, behavior information, host environment information, data information, and the like, The system supports threat judgment and detailed knowledge understanding of vector features under different scenarios, forms multi-form detection methods applying different requirements and scenarios, and improves the ability to judge hidden threats in the background. Further empowering safe operations.

Figure 8-1 The sample analysis results of Antiy LanDi VILLM


Reference Materials

Antiy.Trojan / Win32.ArmouryLoader virus detailed explanation and protection – computer virus encyclopedia [R / OL]. (2025-07-07)

Https: / / www.virusview.net / malware / Trojan / Win32 / ArmouryLoader