惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
IT之家
IT之家
博客园 - 聂微东
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Privacy International News Feed
人人都是产品经理
人人都是产品经理
PCI Perspectives
PCI Perspectives
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 叶小钗
V
Vulnerabilities – Threatpost
美团技术团队
S
Secure Thoughts
N
News | PayPal Newsroom
L
LINUX DO - 最新话题
腾讯CDC
Application and Cybersecurity Blog
Application and Cybersecurity Blog
雷峰网
雷峰网
B
Blog
MyScale Blog
MyScale Blog
T
The Blog of Author Tim Ferriss
TaoSecurity Blog
TaoSecurity Blog
N
News and Events Feed by Topic
Blog — PlanetScale
Blog — PlanetScale
C
Check Point Blog
T
Tailwind CSS Blog
月光博客
月光博客
Simon Willison's Weblog
Simon Willison's Weblog
Hacker News: Ask HN
Hacker News: Ask HN
The Last Watchdog
The Last Watchdog
Google DeepMind News
Google DeepMind News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
MongoDB | Blog
MongoDB | Blog
S
Security @ Cisco Blogs
Jina AI
Jina AI
Engineering at Meta
Engineering at Meta
S
Security Affairs
Forbes - Security
Forbes - Security
P
Palo Alto Networks Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 司徒正美
博客园 - 三生石上(FineUI控件)
T
Tor Project blog
O
OpenAI News
L
Lohrmann on Cybersecurity
Security Archives - TechRepublic
Security Archives - TechRepublic
P
Proofpoint News Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
L
LangChain Blog
B
Blog RSS Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More

Black Hills Information Security, Inc.

Bad Habits: An ANTISOC Operation Same Problem, Different Angles: When Red Team and Blue Team Actually Talk to Each Other How to Identify and Exploit New Vulnerabilities Swapper – A Pure Regex Match/Replace Burp Extension A Practical Guide to BloodHound Data Collection Network Engineering Basics Signed, Trusted, and Abused: Proxy Execution via WebView2 Getting Started In Pentesting – Advice From The BHIS Pentest Lead Cloud Security: Tips and Resources for Securing the Cloud Lessons From A Chatbot Incident How to Lead Effective Tabletops Understanding GRC: How to Navigate Risks and Compliance Standards The “P” in PAM is for Persistence: Linux Persistence Technique Malware Analysis: How to Analyze and Understand Malware OSINT: How to Find, Use, and Control Open-Source Intelligence What to Do with Your First Home Lab When the SOC Goes to Deadwood: A Night to Remember Social Engineering and Microsoft SSPR: The Road to Pwnage is Paved with Good Intentions Common Cyber Threats Finding the Right Penetration Testing Company Deceptive-Auditing: An Active Directory Honeypots Tool The Curious Case of the Comburglar How to Set Smart Goals (That Actually Work For You) Inside the BHIS SOC: A Conversation with Hayden Covington Abusing Delegation with Impacket (Part 3): Resource-Based Constrained Delegation Why You Got Hacked – 2025 Super Edition Abusing Delegation with Impacket (Part 2): Constrained Delegation Abusing Delegation with Impacket (Part 1): Unconstrained Delegation GoSpoof – Turning Attacks into Intel Model Context Protocol (MCP) Bypassing WAFs Using Oversized Requests Getting Started with AI Hacking Part 2: Prompt Injection Wrangling Windows Event Logs with Hayabusa & SOF-ELK (Part 2) DomCat: A Domain Categorization Tool Wrangling Windows Event Logs with Hayabusa & SOF-ELK (Part 1) Microsoft Store and WinGet: Security Risks for Corporate Environments Default Web Content MailFail Commonly Abused Administrative Utilities: A Hidden Risk to Enterprise Security Stop Spoofing Yourself! Disabling M365 Direct Send Bypassing CSP with JSONP: Introducing JSONPeek and CSP B Gone Offensive Tooling Cheatsheets: An Infosec Survival Guide Resource DNS Triage Cheatsheet GraphRunner Cheatsheet Burp Suite Cheatsheet Impacket Cheatsheet Wireshark Cheatsheet Hashcat Cheatsheet EyeWitness Cheatsheet Nmap Cheatsheet Netcat (nc) Cheatsheet Hunt for Weak Spots in Your Wireless Network with Airodump-ng from the Aircrack-ng Suite Detecting ADCS Privilege Escalation Vulnerability Scanning with Nmap Getting Started with NetExec: Streamlining Network Discovery and Access How to Use Dirsearch Augmenting Penetration Testing Methodology with Artificial Intelligence – Part 3: Arcanum Cyber Security Bot How to Design and Execute Effective Social Engineering Attacks by Phone Abusing S4U2Self for Active Directory Pivoting Why Use a Macro Pad? Espanso: Text Replacement, the Easy Way Caging Copilot: Lessons Learned in LLM Security Augmenting Penetration Testing Methodology with Artificial Intelligence – Part 2: Copilot Augmenting Penetration Testing Methodology with Artificial Intelligence – Part 1: Burpference Intercepting Traffic for Mobile Applications that Bypass the System Proxy How to Root Android Phones Communicating Security to the C-Suite: A Strategic Approach Offline Memory Forensics With Volatility Getting Started with AI Hacking: Part 1 Go-Spoof: A Tool for Cyber Deception How to Test Adversary-in-the-Middle Without Hacking Tools Canary in the Code: Alert()-ing on XSS Exploits How to Hack Wi-Fi with No Wi-Fi Why Your Org Needs a Penetration Test Program Burp Suite Extension: Copy For Light at the End of the Dark Web Wi-Fi Forge: Practice Wi-Fi Security Without Hardware Avoiding Dirty RAGs: Retrieval-Augmented Generation with Ollama and LangChain Gone Phishing: Installing GoPhish and Creating a Campaign 5 Things We Are Going to Continue to Ignore in 2025 John Strand’s 5 Phase Plan For Starting in Computer Security Questions From a Beginner Threat Hunter GRC for Security Managers: From Checklists to Influence AI Large Language Models and Supervised Fine Tuning Attack Tactics 9: Shadow Creds for PrivEsc w/ Kent & Jordan One Active Directory Account Can Be Your Best Early Warning Introduction to Zeek Log Analysis Indecent Exposure: Your Secrets are Showing Creating Burp Extensions: A Beginner’s Guide Pitting AI Against AI: Using PyRIT to Assess Large Language Models (LLMs) The Top Ten List of Why You Got Hacked This Year (2023/2024) ICS Hard Knocks: Mitigations to Scenarios Found in ICS/OT Backdoors & Breaches Intro to Data Analytics Using SQL Finding Access Control Vulnerabilities with Autorize The Detection Engineering Process Cyber Risk Lessons We Can Learn From Hurricane Preparedness Intro to Desktop Application Testing Methodology What Is Penetration Testing? Adversary in the Middle (AitM): Post-Exploitation Pentesting, Threat Hunting, and SOC: An Overview
Avoiding Memory Scanners
Kassie Kimball · 2022-09-23 · via Black Hills Information Security, Inc.

Kyle Avery //

Introduction

This post compliments a presentation I gave at DEF CON 30 – “Avoiding Memory Scanners: Customizing Malware to Evade YARA, PE-sieve, and More,” which included the public release of a new tool called AceLdr. The slides for this presentation are available on the conference website.

As open-source tools and commercial security products improve their ability to scan process memory for malware on Windows, red teams are forced to improve their tradecraft to evade them consistently.

Typically, beaconing C2 implants follow a common paradigm in which the malware executes an instruction and then sleeps for a period. This process presents a set of opportunities for detection and evasion, which this post aims to detail.

Memory Scanner Capabilities

Open-source memory scanners have varying features that can be defined into the following categories.

Pattern Matching

Signature or pattern matching may be the most recognized feature of memory scanners and commercial security products. A prime example of this technique is YARA. YARA can perform string and byte pattern matching with conditional logic. For example, consider the following example rule:

rule Example
{
  strings:
    $a = "This program cannot" xor
    $b = { 41 42 ( 43 | 44 ) ?? 46 }

  condition:
    $a or $b
}

In this rule, the target must contain one of the following to match:

  • The string “This program cannot” or any single-byte XOR encrypted variation.
  • The bytes 41 and 42, either 43 or 44, any single byte, and 46.

This simple example should provide a good picture of what is possible with YARA. Anything from simple string or byte patterns to relatively complex combinations of these primitives can be defined.

Since YARA scans all memory allocated by a target process, many projects build off YARA to create more efficient scanners with specific goals. For example, BeaconEye only scans heap memory in search of Cobalt Strike configuration structures which are dynamically allocated at initialization.

Commercial security products like AV and EDR are also known to use YARA. Namely, Carbon Black and CrowdStrike explicitly mention using YARA, and other vendors will likely use it.

A quick Google search can find many YARA rules for Cobalt Strike. For example, the following demonstration scans two cmd.exe processes with a set of rules targeting Cobalt Strike: one benign and one injected with an implant.

Detecting Cobalt Strike with YARA

Memory Attributes

Attributes of memory, such as permissions and mapping information, can also be used to identify potentially malicious code. Memory can be readable, writeable, or executable and mapped as image commit or private commit data. Memory is “image commit” if it was created by loading a file from disk such as an EXE or DLL. Memory is “private commit” if the process dynamically allocated it through API calls such as VirtualAlloc.

Moneta scans memory pages to look for both executable and private commit memory. All code must be executable, but code on Windows tends to be loaded from disk. Executable private memory occurs legitimately in JIT environments such as the .NET runtime or web browsers. Additionally, Moneta will check the start address of all threads for private commit memory addresses. This check is simple enough to evade, since the start address of a thread is not changed after creation. A new thread with an image commit start address can be created in a suspended state, modified to execute the target shellcode, and resumed.

PE-sieve will scan executable, non-executable, or inaccessible memory for patterns that typically occur in shellcode, depending on the usage. In addition, PE-sieve will check the return address of all threads for private commit memory addresses.

Detecting Cobalt Strike with Moneta and PE-sieve

Stack Tracing

Finally, more recent memory scanners have introduced tracing of thread call stacks to identify potentially malicious code. Tools like BeaconHunter and Hunt-Sleeping-Beacons operate on a simple premise: identify any thread with a wait reason of “DelayExecution”. Since Cobalt Strike and many other implants use the Sleep API call, this method can reliably detect malware implants. Unfortunately, there are often many false positives associated with the technique.

Since the initial release of AceLdr, Hunt-Sleeping-Beacons has been updated with a new method to detect FOLIAGE (more on this in the next section). The scanner now looks for threads with a wait reason of “UserRequest”, which also have a return address to KiUserApcDispatcher somewhere on their call stack. This will be covered in further detail below.

An interesting variation of stack tracing can be found in MalMemDetect. This scanner hooks API calls such as RtlAllocateHeap to check the return address at execution time. When Beacon calls one of these APIs, the return address on the stack will point to the implant shellcode, which resides in private commit memory.

Detecting Cobalt Strike with MalMemDetect

The tools discussed above have capabilities outside this post’s scope. I’d recommend looking through the code of each scanner if you’re interested in learning more.

Bypassing Memory Scanners

Developers can take advantage of their C2 implant’s sleep period to implement protections that obfuscate the malware to reduce the likelihood that a scanner will detect it. The longer an implant’s sleep time, the less likely it will be found by scanners evaded by said protections.

A bypass in the context of this post does not generate false positives. It is not meant to confuse analysts or blend in with existing results. A true bypass results in zero results from a memory scanner before and after an implant is injected.

Encrypting Data

The first technique that comes to mind for encrypting data is often single-byte XOR. Single-byte XOR is conveniently easy to implement, doesn’t require API calls, and runs relatively quickly. Unfortunately, tools like YARA and PE-sieve realized this and found ways to detect this encryption method with ease.

An alternative solution might implement functions that perform multi-byte XOR, AES, or RC4. However, it will become apparent in the following sections that this is not a viable option either. To completely evade scanners like Moneta, which search for any executable private memory, the code used for encrypting data must reside in image commit memory.

You can perform AES encryption using Windows APIs, but it requires a combination of multiple API calls to encrypt and decrypt data. An excellent solution for this problem is hinted at in Mimikatz. The author implements SystemFunction032: a system function that can be resolved from advapi32.dll to perform RC4 encryption and decryption. This API call accepts two arguments that contain the target memory and a key, allowing us to dynamically generate a key and encrypt data without executing code in private commit memory. Technically, SystemFunction032 is for encryption, and SystemFunction033 is for decryption. The RC4 cipher is bidirectional, though, so you can use either API for encryption or decryption.

Heap Encryption

Now that we’ve identified a method of encrypting data, we must decide which data should be encrypted. The beginning of this post referenced BeaconEye, a tool that scans dynamically allocated memory for Cobalt Strike configuration data structures.

Heap encryption is probably best performed in one of two ways:

  • Tracking heap entries created by Beacon
  • Utilizing a secondary heap for Beacon’s allocations

The official Sleep Mask Kit from Cobalt Strike provides a list of memory addresses for encryption. Their solution is clean, but it requires the use of Sleep Mask Kit, which, as described in the following section, prevents us from bypassing some scanners.

Last year, I released a fork of TitanLdr, which creates a new heap before Beacon is loaded. The GetProcessHeap API is hooked in the implant’s IAT to force it to resolve that heap when resolving the process heap to allocate memory. This allows us to encrypt all entries on the secondary heap, since only the implant should use it. The following demonstration uses this fork to bypass BeaconEye.

Avoiding BeaconEye

Obfuscating Executable Code

Consistently bypassing tools like Moneta and PE-sieve requires a combination of encryption to evade pattern matching and memory permission control to evade attribute scanning.

Executable Masking Stub

An executable stub such as that used in Sleep Mask Kit or Shellcode Fluctuation can encrypt the implant code at rest and make it non-executable. Both examples require at least one executable region to remain unchanged, though. There will always be at least one point of detection from scanners using the “masking stub” technique, and YARA rules can be created to detect the stub itself.

Return Oriented Programming (ROP)

The Gargoyle PoC influenced the creation of the other techniques discussed in this section. The author used asynchronous procedure calls to queue and execute a series of ROP gadgets that run while the initiating code is non-executable.

Gargoyle is only provided for 32-bit Windows, and the PoC only executes a message box. Earlier this year, Waldo-irc released YouMayPasser: a 64-bit implementation of Gargoyle, ready to use with Cobalt Strike.

Redirecting Execution with Contexts

Gargoyle and YouMayPasser achieve our goal of changing the implant code to non-executable. Still, they suffer the same issues as many ROP exploits: different versions of Windows require modifications to the gadget offsets. There are ways to solve this problem, but they can introduce significant complexity.

Inspired by Gargoyle, Austin Hudson released FOLIAGE: an alternative to traditional ROP, which uses the NtContinue API call to control execution during sleep. NtContinue is typically used in error handling to restore the execution context of a thread. It accepts a new context as the single argument and modifies the current thread to use this context. A context structure specifies values for CPU registers, including the instruction pointer, so it can redirect execution to a specified address. FOLIAGE queues a series of APCs which execute NtContinue to switch contexts repeatedly. A new context structure is used for each of the following steps in a chain that obfuscates the implant:

  1. Waits on a new event to keep the thread from exiting
  2. Changes the implant memory to be non-executable
  3. Instructs the KsecDD driver to encrypt the implant memory
  4. Saves the context of the original thread
  5. Sets the context of the original thread to a fake context (more on this later)
  6. Sleeps for the specified time with NtDelayExecution
  7. Instructs the KsecDD driver to decrypt the implant memory
  8. Restores the original thread context
  9. Changes the implant memory to be executable
  10. Exits the new thread

This process can be further examined by reviewing lines 217-512 of sleep.c in FOLIAGE.

A couple of months ago, C5pider claimed to have reversed MDSec NightHawk to create Ekko: an alternative to FOLIAGE which uses CreateTimerQueueTimer instead of NtQueueApcThread to queue calls to NtContinue.

The following demonstration uses FOLIAGE to bypass Moneta and PE-sieve.

Avoiding Moneta and PE-sieve

NtContinue is not the only API call that forcefully changes execution with context structures. It conveniently requires only one argument, but there are also viable alternatives.

Avoiding Sleep

Tools like BeaconHunter and Hunt-Sleeping-Beacons alert on threads with a wait reason of “DelayExecution”. This detection can be easily evaded using an alternative method of delaying execution which does not set this wait reason. WaitForSingleObject is an API that fits this requirement and sets a wait reason of “UserRequest”. The following demonstration replaces the Sleep API call with WaitForSingleObject to bypass these tools.

Avoiding Hunt-Sleeping-Beacons

Return Address Spoofing

Spoofing the return address involves modifying the call stack return address, so it does not point to private commit memory. This section can be split into two distinct techniques: at rest, and execution return address spoofing.

Spoofing at Rest

The term “at rest” refers to the implant during sleep. Most of the techniques discussed so far focus on this time as well. Commercial security products do not appear to be scanning the thread call stacks at rest, but open-source scanners such as PE-sieve will check return addresses when scanning.

This detection is partially evaded using a technique such as ThreadStackSpoofer. This PoC hides the return address by overwriting it with zero, effectively truncating the stack. Then, depending on the state of the stack, this technique may leak arguments onto the stack. These arguments may resemble memory addresses to create an indicator for scanners that inspect return addresses.

A more stable technique is demonstrated in FOLIAGE. The author uses NtSetContextThread to overwrite the original thread’s context with a manufactured context that sets the desired return address. The usage of NtSetContextThread is relatively rare and may be a point of detection. The author had not observed open-source scanners or commercial security products raising alerts on this behavior at the time of release.

Spoofing at Execution

The other time a thread’s call stack may be captured is “at execution”. This is demonstrated most clearly in MalMemDetect, as described above. Our return address must point to image commit memory when we make hooked API calls to evade tools like this.

The x64 Return Address Spoofing PoC accomplishes this nicely. A ROP gadget from a loaded DLL is stored as the return address before the API call is made, which jumps to a stub that restores the context necessary to continue execution.

Avoiding MalMemDetect

Since the release of AceLdr, Hunt-Sleeping-Beacons has been updated to detect FOLIAGE. The scanner will now check all threads with a wait reason of “UserRequest” which also have a return address to KiUserApcDispatcher somewhere on their call stack. This cannot be easily bypassed with the public implementation of FOLIAGE as it requires call stack spoofing of API calls in the sleep chain at execution. Since FOLIAGE is obfuscating the shellcode used for return address spoofing, it cannot be called by the APC thread to spoof return addresses.

AceLdr

As a part of this research, I released an implementation of the previously discussed techniques called AceLdr. This tool is a user-defined reflective loader (UDRL) for Cobalt Strike with the following features at the time of release:

  • Bypasses every referenced scanner
  • Easy to use – import a single CNA script
  • Encryption using SystemFunction032
  • Dynamic memory encryption using a secondary heap
  • Code obfuscation and encryption using FOLIAGE
  • Delayed execution using WaitForSingleObject
  • Return address spoofing at execution for InternetConnectA, NtWaitForSingleObject, and RtlAllocateHeap

Black Hills Information Security used this tool for approximately one year before releasing it publicly. Below is a demonstration of AceLdr bypassing several memory scanners.

Avoiding Memory Scanners with AceLdr

Closing Thoughts

While AceLdr is made explicitly for Cobalt Strike, the techniques demonstrated in this post can be easily ported to many other projects. Each method presented here bypasses existing scanners. However, this does not guarantee they will evade future implementations, as we’ve already seen with Hunt-Sleeping-Beacons.

Memory scanners and commercial security products are not the same, but they share many characteristics. For example, evading open-source scanners does not guarantee security product evasion. In addition, security product evasion often does not require a complete memory scanner bypass since system resources and development costs limit vendors.

Credits



Ready to learn more?

Level up your skills with affordable classes from Antisyphon!

Pay-What-You-Can Training

Available live/virtual and on-demand