YARA's strength, is also its Achilles' heel
YARA rules stand as powerful sentinels against static cyber threats. Their strength, however, is also their Achilles' heel. The static nature of YARA rules means they can be effortlessly circumvented, especially when they are made public. Elastic Security, for instance, publishes their YARA rules on Github: Elastic Security - Protection Artifacts, potentially offering adversaries a blueprint to dodge detection simply by trivially altering their malicious code.
In a recent Karma-X blog, we took a look at Havoc C2 Framework, which describes itself as a "modern and malleable post-exploitation command and control framework." In revisiting that post, we would be remiss if we didn't point out that other EDR vendors already had published some detection mechanisms for this Framework.
That said, by publishing their YARA rules, an adversary can trivially make changes to generated Havoc agents to bypass their YARA. Let's take a closer look. Elastic publishes 3 YARA rules for Havoc C2:
rule Windows_Trojan_Havoc_77f3d40e {
meta:
author = "Elastic Security"
id = "77f3d40e-9365-4e76-a1a3-36d128e775a9"
fingerprint = "95d35d167df7f77f23b1afb1b7655cc47830c9986c54791b562c33db8f2773ae"
creation_date = "2022-10-20"
last_modified = "2022-11-24"
threat_name = "Windows.Trojan.Havoc"
reference_sample = "3427dac129b760a03f2c40590c01065c9bf2340d2dfa4a4a7cf4830a02e95879"
severity = 100
arch_context = "x86"
scan_context = "file, memory"
license = "Elastic License v2"
os = "windows"
strings:
$core = { 48 ?? ?? 2C 06 00 00 00 ?? ?? 48 ?? ?? 5C 06 00 00 00 ?? ?? ?? ?? ?? ?? 48 8B ?? 5C 06 00 00 ?? F6 99 5A 2E E8 ?? ?? ?? ?? 48 8B ?? 48 ?? ?? 4C 02 00 00 48 8B ?? 5C 06 00 00 ?? 23 DB 07 03 E8 ?? ?? ?? ?? 48 8B ?? 48 ?? ?? 44 02 00 00 48 8B ?? 5C 06 00 00 ?? DA 81 B3 C0 E8 ?? ?? ?? ?? 48 8B ?? 48 ?? ?? 54 02 00 00 48 8B ?? 5C 06 00 00 ?? D7 71 BA 70 E8 ?? ?? ?? ?? 48 8B ?? 48 ?? ?? 64 02 00 00 48 8B ?? 5C 06 00 00 ?? 88 2B 49 8E E8 ?? ?? ?? ?? 48 8B ?? 48 ?? ?? 84 02 00 00 48 8B ?? 5C 06 00 00 ?? EF F0 A1 3A E8 ?? ?? ?? ?? }
$commands_table = { 0B 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 64 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 15 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 10 10 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 0C 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? [0-12] 0F 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 14 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 01 20 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 03 20 00 00 ?? ?? ?? ?? ?? ?? ?? ?? C4 09 00 00 ?? ?? ?? ?? ?? ?? ?? ?? CE 09 00 00 ?? ?? ?? ?? ?? ?? ?? ?? D8 09 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 34 08 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 16 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 18 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 1A 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 28 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? 5C 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? }
$hashes_0 = { F6 99 5A 2E }
$hashes_1 = { DA 81 B3 C0 }
$hashes_2 = { D7 71 BA 70 }
$hashes_3 = { 88 2B 49 8E }
$hashes_4 = { EF F0 A1 3A }
$hashes_5 = { F5 39 34 7C }
$hashes_6 = { 2A 92 12 D8 }
$hashes_7 = { 8D F1 4F 84 }
$hashes_8 = { 5B BC CE 73 }
$hashes_9 = { 59 24 93 B8 }
$hashes_10 = { 02 9E D0 C2 }
$hashes_11 = { E5 36 26 AE }
$hashes_12 = { 5C 3C B4 F3 }
$hashes_13 = { 2F 87 D8 1C }
$hashes_14 = { D7 53 22 AC }
condition:
$core or ($commands_table and all of ($hashes*))
}
rule Windows_Trojan_Havoc_9c7bb863 {
meta:
author = "Elastic Security"
id = "9c7bb863-b6c2-4d5f-ae50-0fd900f1d4eb"
fingerprint = "cda55a9e65badb984e71778b081929db2bdef223792b78bba32b2259757f1348"
creation_date = "2023-04-28"
last_modified = "2023-06-13"
threat_name = "Windows.Trojan.Havoc"
reference_sample = "261b92d9e8dcb9d0abf1627b791831ec89779f2b7973b1926c6ec9691288dd57"
severity = 100
arch_context = "x86"
scan_context = "file, memory"
license = "Elastic License v2"
os = "windows"
strings:
$a1 = { 56 48 89 E6 48 83 E4 F0 48 83 EC 20 E8 0F 00 00 00 48 89 F4 5E C3 }
$a2 = { 65 48 8B 04 25 60 00 00 00 }
condition:
all of them
}
rule Windows_Trojan_Havoc_88053562 {
meta:
author = "Elastic Security"
id = "88053562-ae19-44fe-8aaf-d6b9687d6b80"
fingerprint = "818011b7972ab71cbfe07ec2266f504ba0ec7df30136e414d15366aa68ad5b8a"
creation_date = "2024-01-04"
last_modified = "2024-01-12"
threat_name = "Windows.Trojan.Havoc"
reference_sample = "2f0b59f8220edd0d34fba92905faf0b51aead95d53be8b5f022eed7e21bdb4af"
severity = 100
arch_context = "x86"
scan_context = "file, memory"
license = "Elastic License v2"
os = "windows"
strings:
$a = { 48 81 EC F8 04 00 00 48 8D 7C 24 78 44 89 8C 24 58 05 00 00 48 8B AC 24 60 05 00 00 4C 8D 6C 24 78 F3 AB B9 59 00 00 00 48 C7 44 24 70 00 00 00 00 C7 44 24 78 68 00 00 00 C7 84 24 B4 00 00 00 }
condition:
all of them
}
We tested them using yara64.exe:
Interestingly, the Demon agent we compiled from the previous blog already evades Elastic's first YARA rule written in 2022. That tests our theory, maybe the authors of HAVOC C2 specifically rewrote something to evade Elastic's YARA rule. Either way, it looks like Elastic has two more rules that do detect the latest version.
Let's take a look at Ghidra to see what they are detecting:
That's interesting, taken at face value, it appears like there are two unique patterns of bytes that Elastic thinks are inherently attributable to the Havoc framework. We didn't dig too deeply, but the second one seems to be DemonConfig function where source is provided. The first signature focuses on the very beginning of the Demon assembly shellcode which is provided as source and compiles each time an agent is configured.
Ok, let's just modify the assembly and include a NOP instruction to evade the first YARA rule:
Follow the same steps as previous blog on recompiling Havoc, and wallah:
So that takes care of the 2nd yara rule. The third YARA rule is in the Demon source. That's a little harder to compile, and rather than spend the time necessary to rebuild that (despite author warnings), let's just modify something inconsequential with HxD. As long as we don't add any bytes, we shouldn't have to worry about any offset issues.
All we should have to modify is the instructions which reserve stack space and decommit stack space. We could easily add a stack variable in source, but let's knock this out.
We change the stack size to 0x5f8 instead of 0x4f8 and save. Let's rerun with Elastic's YARA rule:
Anyways, let's see what happens if we inject that directly into Karma-X (without any YARA rules to target this binary):
We updated the Elastic YARA rule here: Karma-X Github
For more information about how Karma-X protects you in a more sophisticated way than static signatures, you can start by accessing Vitamin-K for free here! (after signing up and logging in)
From small business to enterprise, Karma-X installs simply and immediately adds peace of mind
Karma-X doesn't interfere with other software, only malware and exploits, due to its unique design.
Whether adversary nation or criminal actors, Karma-X significantly reduces exploitation risk of any organization
Update to deploy new defensive techniques to suit your organization's needs as they are offered