This post is also available in: 日本語 (Japanese)
Executive Summary
To better detect attacks that affect the actions of signed applications – such as supply-chain attacks, dynamic-link libraries (DLL) hijacking, exploitation and malicious thread injection – we have devised a suite of analytics detectors that are able to detect global statistical anomalies.
Using these new detectors, we found what seems to be an industrial espionage attack. The observed activity includes performing a specially crafted DLL hijacking attack used by a previously unknown piece of malware that we dubbed "Popping Eagle" due to several artifacts found in the samples. It also includes a second stage malicious tool written in Go dubbed "Going Eagle." In this particular case, we observed the attacker following this by performing several network scans and lateral movement steps.
Discovering Popping Eagle using this new suite of analytics detectors underscores the following key points:
- These analytical and statistical methods have capabilities that allow for the identification of malware that might otherwise have been missed.
- Though the malware loaded itself into a signed process with the goal of remaining undetected, these detectors found it due to the attempted obfuscation.
In this blog post, we discuss the hunting method, analyze the tools used in the attack and detail the actions performed by the attacker in the victim’s environment.
Palo Alto Networks customers are protected from this kind of attack by Cortex XDR, as well as the WildFire cloud-delivered security subscription for the Next-Generation Firewall. (Please see the Conclusion section for more detail.)
Malware Discussed | Popping Eagle, Going Eagle |
Hunting for Statistical Irregularities in Signed Applications
Motivation
Over the last couple of years, the number of supply-chain attacks has increased dramatically. Examples include SolarStorm, NotPetya, Kaseya, KeRanger and others.
From previous events, we learned that even though threat actors leveraging supply-chain attacks usually run code on a large number of organizations, they tend to focus the attack’s "second stage" on a small number of high-value targets.
Leveraging a large Cortex XDR dataset, we built a global baseline of "normal" application behavior and hunted for anomalies.
Identifying these anomalies detects several kinds of techniques – examples include supply chain attacks, DLL side-loading or malicious thread injections – and any attack that may cause a legitimate signed application to behave differently.
Implementation
Each application can perform several different types of actions. Actions that are shared across multiple environments are more likely to be benign, so we leverage them to create a global baseline for each application.
In addition, some actions are unique to each organization, even when performed by the same application (for example, connecting to the domain of the organization itself). Recognizing this, we also build a local baseline for each organization and for each application.
Using these baselines, we compare actions performed by each application and flag anomalous activities.
Once we have a set of suspicious cases, we further analyze them to validate if these are actual attacks.
Finding Popping Eagle
After filtering out cases with known malicious indicators of compromise (IoCs), we came across the following case:
The application clicksharelauncher.exe, signed by "Barco N.V.," had been seen in a few hundred different environments, indicating we have a good baseline on its behavior, but it performed unique domain resolutions in only one environment. Furthermore, the domain it contacted, dnszonetransfer[.]com, was only seen in that environment, and only on three unique agents out of thousands.
In the course of the research, we found two types of tools left on the hosts that sparked our curiosity as they were unknown not only by hash but also by all other IoCs found during the research (see “Searching for Related IoCs” for further elaboration).
Analyzing Popping Eagle’s First Stage
Loading Method – DLL Proxy
Looking into the causality chain of clicksharelauncher.exe, we saw that before it contacted the dnszonetransfer[.]com domain, it loaded an unsigned DLL from the same directory as the executable named uxtheme.dll.
This DLL name also belongs to a known Microsoft signed DLL that's usually located at %windir%\SysWOW64\UxTheme.dll, and the DLL name is also in the import table of clicksharelauncher.exe.
This is a classic example of DLL Search Order Hijacking; clicksharelauncher.exe tries to load uxtheme.dll from the current directory before %windir%\SysWOW64\, so it loads the attacker’s DLL instead of Microsoft’s DLL.
Comparing the export table of the unsigned uxtheme.dll with the original one also shows the same functions, with the addition of one additional exported function: popo.
Analyzing the uxtheme.dll Sample
This executable was written as a 32-bit DLL in C++. The original compiled name from the DLL metadata is CoL_Final_Lib.dll, and its compile timestamp records the same day we first saw it. In conjunction with the fact that each of the three hosts we saw it on had a different SHA256 hash, this may indicate that it was compiled "on the spot."
The use of the Barco software as a loader also indicates that the sample was tailor-made to this victim’s environment – its use as a loader is rather unique.
Checking the memory locations of its entry point and exports shows mostly strings, while only one is an actual function. This further indicates that this DLL doesn't implement actual logic for these functions and they only exist to better mimic the proxied DLL.
To run its functionality right away on load (avoiding the need to wait to be called explicitly), the malware runs its main code on the main DLL entry point and in a new thread (to not block the rest of the DLL load flow).
This main function decodes the C2 URL (using a simple one-byte XOR) and connects to it using a Win32API function. From strings found in the code, it seems that the malware authors used the open-source C++ project WinHttpClient to perform the network logic. The malware then enters its main event loop, which performs these actions:
- Sends a POST request to the URL with a hardcoded old Linux user agent and message.
- Verifies that the response starts with Unicode 726563697074 – "recipt" (may suggest a non-native English-speaking author).
- Parses a struct with several different commands including:
- Saving files on the remote host.
- Loading and running DLLs from a specific folder.
- Sleeps for one hour + a randomly generated timeframe.
Going Eagle Second Stage Analysis
Most of the time this DLL was observed, it didn't seem to receive any commands from the malicious actor. But on one occasion the IP resolved by dnszonetransfer[.]com temporarily changed to 51.38.89[.]53 for a few days when the attacker was active. This is a common tactic attempting to avoid detection where the C2 domain only points to the attacker’s infrastructure when the malware needs to be controlled. This attacker-controlled IP used the first-stage malware to load a second stage DLL that we call “Going Eagle.”
Analyzing ClickRuntime-amd86.dll
This executable was written as a 32-bit DLL in Go. The original "compiled name" from the DLL metadata is iphlpapi.dll. Somewhat interestingly, this DLL proxies a different Microsoft DLL by the same name (and mimics all the relevant named export functions). This isn’t necessary as the first stage loads it with LoadLibrary and not by the DLL-hijacking technique.
There are more similarities between the DLLs although they were written in different languages (C++, Go)
- Compile timestamp – created and dropped on the same day.
- Created as a proxy DLL.
- Has an export function named popo
- The DllMain and popo functions call a function that invokes the malware’s inner logic in another thread (so the malware logic will run right on the DLL load or on another popo invocation).
This tool was created for one task only – to create a reverse SOCKS proxy to get the attacker control over the machine (as described in the “Lateral Movement” section later on).
Since the malware is written in Go, we can extract extra data from its plaintext strings:
- Original package name Eagle2.5-Client-Dll (outlined in red in Figure 6).
- Original function names (like main.StartEagle).
- Packages from Go standard and extended library (like bufio, log, x/net).
- Packages from other resources like GitHub repositories (outlined in yellow and green in Figure 6).
Lateral Movement
Using the second-stage SOCKS binary, Going Eagle, the attackers tunneled their machine to perform several network-based attacks.
At first, they scanned multiple hosts for open Remote Desktop Protocol (RDP) and Server Message Block (SMB) ports, in order to find targets toward which to move laterally. Leveraging password reuse of the local administrator account on several different hosts, the attackers used Impacket's wmiexec to run discovery commands on multiple machines.
This caused the following detectors to be raised:
In addition to wmiexec, the attackers used RDP to move laterally through the network. They uploaded PsExec and used it to run taskmgr.exe as SYSTEM to gather credentials by dumping lsass memory.
This was blocked by the Cortex XDR agent as well and raised several other alerts from Cortex XDR Analytics and Cortex XDR BIOCs:
At a certain point, the attackers managed to acquire a privileged domain account and tried using it to steal secrets from the domain controller using Impacket's secretsdump. But their attempts were blocked by the Cortex XDR agent.
It seems that the attacker failed to reach their goals and stopped trying to move laterally due to the multiple protections in place.
Second-Stage Timeline
Time (UTC) | MITRE Technique | Action | Detection |
---|---|---|---|
Day 1 17:28 | Dynamic Resolution | The attacker changed IP resolution for dnszonetransfer[.]com to 51.38.89[.]53 | |
Day 2 20:19 | Application Layer Protocol | The infected host got the first command from 51.38.89[.]53 | |
Signed Binary Proxy Execution | Loaded the second-stage DLL, Going Eagle (ClickRuntime-amd86.dll) | Globally uncommon image load from a signed process (Added after the fact) | |
Application Layer Protocol | First transmission to reporterror[.]net | Globally uncommon root domain from a signed process (Added after the fact) |
|
Proxy | Attacker machine was tunneled using the SOCKS proxy | ||
Day 2 20:29 | Network Service Scanning | Scanned multiple hosts for open RDP, SMB and Remote Procedure Call (RPC) ports | Failed Connections |
Day 2 20:35 | Remote Services | Connected to the first host using wmiexec | Remote WMI process execution |
Rare NTLM Access By User To Host | |||
Command execution via wmiexec | |||
Behavioral Threat Protection (suspicious_remote_service) | |||
Behavioral Threat Protection (impacket_cmd) | |||
System Network Configuration Discovery | Run discovery commands | Uncommon IP Configuration Listing via ipconfig.exe | |
Account Discovery | Uncommon user management via net.exe | ||
Uncommon ARP cache listing via arp.exe | |||
Multiple Discovery Commands | |||
Day 2 20:50 | Remote Services | Connected to the second host using wmiexec | Remote WMI process execution |
Rare NTLM Access By User To Host | |||
Command execution via wmiexec | |||
Behavioral Threat Protection (suspicious_remote_service) | |||
Behavioral Threat Protection (impacket_cmd) | |||
System Network Configuration Discovery | Run discovery commands | Uncommon IP Configuration Listing via ipconfig.exe | |
Account Discovery | Uncommon user management via net.exe | ||
Uncommon ARP cache listing via arp.exe | |||
Multiple Discovery Commands | |||
Day 2 20:53 |
Network Service Scanning | Scanned multiple hosts for open RDP, SMB and RPC ports | Failed Connections |
Day 2 20:54 | Remote Services | Connected to the third host using wmiexec | Remote WMI process execution |
Rare NTLM Access By User To Host | |||
Command execution via wmiexec | |||
Behavioral Threat Protection (suspicious_remote_service) | |||
Behavioral Threat Protection (impacket_cmd) | |||
System Network Configuration Discovery | Run discovery commands | Uncommon IP Configuration Listing via ipconfig.exe | |
Uncommon user management via net.exe | |||
Account Discovery | Uncommon ARP cache listing via arp.exe | ||
Multiple Discovery Commands | |||
Day 2 21:40 | Network Service Scanning | Scanned multiple hosts for open RDP, SMB and RPC ports | Failed Connections |
Day 2 21:54 | Remote Desktop Protocol | Laterally moved using RDP to the fourth host | |
Day 2 21:56 | LSASS Memory | Tried to dump lsass using taskmgr | Behavioral Threat Protection (minidumpwritedump_handle_terminate) |
Day 2 22:01 | LSASS Memory | Tried to dump lsass using taskmgr running as SYSTEM | Behavioral Threat Protection (minidumpwritedump_handle_terminate) |
Suspicious process executed with a high integrity level | |||
PsExec execution EulaAccepted flag added to the Registry | |||
PsExec runs with System privileges | |||
Day 3 01:10 | NTDS | Run secretsdump on the first DC and was blocked | heuristic.b.save_sam_or_security_remote (SYNC - Credential Gathering - 3406296443) |
Day 3 01:36 | NTDS | Run secretsdump on the second DC and was blocked | heuristic.b.save_sam_or_security_remote (SYNC - Credential Gathering - 3406296443) |
Day 8 11:16 | Dynamic Resolution | The attacker changed dnszonetransfer[.]com IP resolution to a benign IP |
Table 4. Timeline of activities, attack techniques and detections involved in the Popping Eagle attack.
Searching for Related IoCs
After we finished analyzing the malware's behavior, we set our goals to find related samples by the same actor.
Hypothesis
Observing the facts:
- The first stage downloads and loads the second stage DLL and invokes the function popo from it. Both DLLs export the popo function.
- The second stage unnecessarily proxies the DLL.
Also, both of the DLLs contain possible indicator strings for a version or a development ready status
- CoL_Final_Lib.dll
- Eagle2.5-Client-Dll
This data can sum up to a possible modus operandi of an adversary:
- Create and use multiple small-effort tools written using known public projects and libraries.
- It is feasible to assume that they have a framework to easily create proxy DLLs with a single export function (in our case: popo).
- Developer(s) knowledgeable in several programming languages (C++, Go, Python).
Hunting and Searching Methodology
At first we searched for the initial indicators (hash, domain, IP, URL) on AutoFocus and common public threat intel platforms, but nothing new was found.
Additionally, while analyzing the malware, we created generic "hunting" and specific "adversary" Yara rules to search for related samples. The generic rules yielded surprisingly good results by finding additional "Go socks" samples unrelated to this actor, most of which are malware.
The specific adversary rules did not find any additional samples.
Conclusion
As seen in the case above, attackers are using open-source code to develop custom malware that's designed to evade security detection. In order to combat more advanced actors, we must leverage more sophisticated detection techniques. Hunting for anomalous actions done by signed applications has proven itself successful in finding previously unknown attacks and "dormant" backdoors.
Due to the malware's apparently being tailor-made for the attacked network and the use of common attack tools, we couldn't attribute it to a specific actor.
Palo Alto Networks customers are protected from this kind of attack by the following:
1. Cortex XDR's Global Analytics BIOC alerts, implementing, among many things, the statistical techniques described earlier.
2. Cortex XDR Agent Behavioral Threat Protection blocks the DLL hijacking attack on the vulnerable application, preventing future malware from using the same loading method.
3. WildFire, a cloud-delivered security subscription for the Next-Generation Firewall, and Cortex XDR identify and block all IoCs mentioned as well as all future IoCs identified by the Yara rules
Appendix
Indicators of Compromise
SHA256 | File Name |
e5e89d8db12c7dacddff5c2a76b1f3b52c955c2e86af8f0b3e36c8a5d954b5e8 | uxtheme.dll |
95676c8eeaab93396597e05bb4df3ff8cc5780ad166e4ee54484387b97f381df | uxtheme.dll |
59d12f26cbc3e49e28be13f0306f5a9b1a9fd62909df706e58768d2f0ccca189 | uxtheme.dll |
0dc8f17b053d9bfab45aed21340a1f85325f79e0925caf21b9eaf9fbdc34a47a | ClickRuntime-amd86.dll |
Domain |
dnszonetransfer[.]com |
reporterror[.]net |
IP |
51.38.89[.]53 |
51.75.57[.]245 |
URL |
hxxps[:]//dnszonetransfer[.]com/Protocol/extensions.php |
User agent |
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36 |
Hunting Yara Rules
Suspicious Go Executables
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
rule general_win_golang_socks { meta: author = "paloaltonetworks" date = "2022-03-13" description = "potentially unwanted GO application with proxy communication capabilities" strings: $go_name_1 = "main.go" nocase ascii // default go name for the “func main(){...}” in "package main” $go_name_2 = "eagle" nocase ascii $go_name_3 = "popo" nocase ascii $go_name_4 = "-Client-Dll/" nocase ascii $go_pkg_1 = "github.com/armon/go-socks5" nocase wide ascii $go_pkg_2 = "github.com/hashicorp/yamux" nocase wide ascii $go_pkg_3 = "github.com/fatedier/frp/vendor" wide ascii $go_pkg_4 = "github.com/rofl0r/rocksocks5" wide ascii condition: uint16(0) == 0x5a4d and filesize < 7MB and ( 1 of ($go_name_*) and 2 of ($go_pkg_*) ) } rule general_win_dll_golang_socks { meta: author = "paloaltonetworks" date = "2022-03-13" description = "Highly suspicious GO DLL with proxy communication capabilities" condition: general_win_golang_socks and (pe.characteristics & pe.DLL) and pe.is_dll() } |
Possible Tools From This Adversary
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
rule general_win_faked_dlls_export_popo { meta: author = "paloaltonetworks" date = "2022-03-13" description = "Detects DLL files with an export function named 'popo'" hash0 = "e5e89d8db12c7dacddff5c2a76b1f3b52c955c2e86af8f0b3e36c8a5d954b5e8" // fake uxtheme.dll hash1 = "95676c8eeaab93396597e05bb4df3ff8cc5780ad166e4ee54484387b97f381df" // fake uxtheme.dll hash2 = "59d12f26cbc3e49e28be13f0306f5a9b1a9fd62909df706e58768d2f0ccca189" // fake uxtheme.dll hash3 = "0dc8f17b053d9bfab45aed21340a1f85325f79e0925caf21b9eaf9fbdc34a47a" // ClickRuntime-amd86.dll condition: (pe.characteristics & pe.DLL) and pe.is_dll() and filesize < 20MB and ( pe.exports("popo") or pe.exports("Popo") ) } |