Bypass YARA Rule f0b627fc for CobaltStrike to Evade EDRs
Learn how to bypass the YARA rule Windows_Trojan_CobaltStrike_f0b627fc targeting Cobalt Strike’s signature shellcode by replacing key bytes with alternative shellcode and using a Python script to randomize the shellcode with NOPs, for EDRs evasion.
Table of Contents
- Overview of YARA rule evasion
- A More Effective Bypass
- Randomizing Shellcode with NOP Instructions
- Key Considerations for Implementing Shellcode Alternatives
- Script Usage Example and GitHub Repository for Scripts Mentioned in this Blog
Overview of YARA rule evasion
In a White Knight Labs blog post about EDR evasion with Cobalt Strike, they discussed methods for bypassing YARA rules targeting Cobalt Strike. One of the most challenging rules to bypass is Windows_Trojan_CobaltStrike_f0b627fc.
This specific rule targets a 10-byte sequence found within the Cobalt Strike binary:
1
\x25\xff\xff\xff\x00\x3d\x41\x41\x41\x00
Even after employing sleep masks and utilizing the sleep mask kit to generate custom masks, this byte sequence persists in the final shellcode. Using the Defuse.ca x64 Disassembler, we can see that this shellcode translates to the following assembly instructions:
1
2
and eax, 0xffffff
cmp ecx, 0x414141
In the White Knight Labs post, they bypassed this detection by modifying the instruction from AND EAX, 0xFFFFFF
to MOV EAX, 0xFFFFFF
. This results in the following altered shellcode:
1
\xB8\xFF\xFF\xFF\x00\x3D\x41\x41\x41\x00
However, while this approach alters the AND
instruction, the CMP
instruction remains the same, meaning that this modified shellcode could still be detected by a newly crafted YARA rule.
A More Effective Bypass
Through experimentation, I found that you can actually remove the cmp instruction altogether. By simply setting EAX to 0xFFFFFF, the Cobalt Strike beacon functions as expected.
Here are some alternative shellcode sequences you can use to avoid detection:
MOV EAX, 0x00414141
XOR EAX, EAX; MOV EAX, 0x00414141
In this case, XOR EAX, EAX
zeroes out the EAX
register before setting it to 0x00414141
.
This slight variation in the instructions changes the shellcode without affecting the overall functionality, making it harder for static analysis tools to signature.
Randomizing Shellcode with NOP Instructions
While the above methods help evade the original rule, the new shellcode could still be signatured.
To counter this, I developed a script that automatically replaces the original byte sequence \x25\xff\xff\xff\x00\x3d\x41\x41\x41\x00
with the alternative shellcode, and then randomly inserts NOP instructions (\x90
and \x87\xC0
) into the shellcode.
NOP (No Operation) instructions don’t affect the execution flow but add randomization to the shellcode. By inserting NOPs at random positions—at the start, middle, or end of the shellcode—you can further obfuscate the shellcode, making it even more challenging to signature.
Key Considerations for Implementing Shellcode Alternatives
When implementing alternative shellcode, keep the following in mind:
- Shellcode Size: The total shellcode size cannot exceed 10 bytes, as that is the length of the original sequence.
- Smaller Sizes for Randomization: It’s preferable to use shellcode sequences shorter than 10 bytes, allowing the Python script to insert NOPs and reuse them in future iterations for better evasion.
Script Usage Example and GitHub Repository for Scripts Mentioned in this Blog
Here’s an usage example, where I replace the bytes of http_x64.xthread.bin and save it to beacon.bin:
You can find the Python script for bypassing the YARA rule on my GitHub:
https://github.com/WafflesExploits/CobaltStrike-YARA-Bypass-f0b627fc
In addition, I’ve included Python scripts from White Knight Labs for generating Rich headers and prepend headers, with minor improvements.