According to CrowdStrike, this backdoor was discovered being embedded in a legitimate, signed version of 3CXDesktopApp, and thus constitutes a supply chain attack.
rule win_3cx_backdoor_auto {
meta:
author = "Felix Bilstein - yara-signator at cocacoding dot com"
date = "2024-10-31"
version = "1"
description = "Detects win.3cx_backdoor."
info = "autogenerated rule brought to you by yara-signator"
tool = "yara-signator v0.6.0"
signator_config = "callsandjumps;datarefs;binvalue"
malpedia_reference = "https://malpedia.caad.fkie.fraunhofer.de/details/win.3cx_backdoor"
malpedia_rule_date = "20241030"
malpedia_hash = "26e26953c49c8efafbf72a38076855d578e0a2e4"
malpedia_version = "20241030"
malpedia_license = "CC BY-SA 4.0"
malpedia_sharing = "TLP:WHITE"
/* DISCLAIMER
* The strings used in this rule have been automatically selected from the
* disassembly of memory dumps and unpacked files, using YARA-Signator.
* The code and documentation is published here:
* https://github.com/fxb-cocacoding/yara-signator
* As Malpedia is used as data source, please note that for a given
* number of families, only single samples are documented.
* This likely impacts the degree of generalization these rules will offer.
* Take the described generation method also into consideration when you
* apply the rules in your use cases and assign them confidence levels.
*/
strings:
$sequence_0 = { 49b8ffffffffffffff0f 4c8bf1 493bc0 0f849f010000 488b4910 }
// n = 5, score = 100
// 49b8ffffffffffffff0f | mov dword ptr [ebp - 0x20], edi
// 4c8bf1 | dec eax
// 493bc0 | lea ecx, [esp + 0x48]
// 0f849f010000 | nop
// 488b4910 | inc ebp
$sequence_1 = { 418502 418b01 7409 440fabc0 418901 eba6 }
// n = 6, score = 100
// 418502 | cmp esp, 0x10
// 418b01 | jb 0xba6
// 7409 | nop dword ptr [eax]
// 440fabc0 | nop dword ptr [eax + eax]
// 418901 | dec eax
// eba6 | mov ebx, ecx
$sequence_2 = { 7575 488b7608 4c8b7608 4c3b7610 7443 33c0 }
// n = 6, score = 100
// 7575 | jae 0x5d5
// 488b7608 | dec esp
// 4c8b7608 | lea eax, [ecx + edi]
// 4c3b7610 | dec ecx
// 7443 | mov ecx, eax
// 33c0 | dec eax
$sequence_3 = { 488b8dc0010000 488bc1 4881fa00100000 0f82a30d0000 4883c227 488b49f8 }
// n = 6, score = 100
// 488b8dc0010000 | mov byte ptr [eax + ecx], dl
// 488bc1 | mov byte ptr [eax + ecx + 1], 0
// 4881fa00100000 | jmp 0xc8
// 0f82a30d0000 | inc esp
// 4883c227 | movzx ecx, dl
// 488b49f8 | dec eax
$sequence_4 = { 482bc1 4883c0f8 4883f81f 0f8792090000 e8???????? 4c897580 48c745880f000000 }
// n = 7, score = 100
// 482bc1 | mov dword ptr [esp + 0x58], edx
// 4883c0f8 | inc ecx
// 4883f81f | push edi
// 0f8792090000 | dec eax
// e8???????? |
// 4c897580 | lea ebp, [esp - 0x220]
// 48c745880f000000 | dec eax
$sequence_5 = { c60601 498b4660 48894608 0fb655c8 488d4dd0 e8???????? 488bc6 }
// n = 7, score = 100
// c60601 | jmp ecx
// 498b4660 | cmp eax, 0x57
// 48894608 | jne 0x479
// 0fb655c8 | inc esp
// 488d4dd0 | lea eax, [ebx + 7]
// e8???????? |
// 488bc6 | dec ecx
$sequence_6 = { 4180fa2d 7502 f7db 4584c9 7529 488b07 48ffc8 }
// n = 7, score = 100
// 4180fa2d | dec eax
// 7502 | mov ecx, dword ptr [eax + 8]
// f7db | dec eax
// 4584c9 | mov dword ptr [edx + 8], ecx
// 7529 | mov byte ptr [eax], 0
// 488b07 | dec eax
// 48ffc8 | mov dword ptr [eax + 8], ebx
$sequence_7 = { 4883fa1f 7305 48ffc2 eb06 33d2 4983c104 }
// n = 6, score = 100
// 4883fa1f | dec eax
// 7305 | add edx, 0x27
// 48ffc2 | dec eax
// eb06 | mov ecx, dword ptr [ecx - 8]
// 33d2 | dec eax
// 4983c104 | sub eax, ecx
$sequence_8 = { 89442448 ffc8 8bf8 410fb68c80023f0300 410fb6b480033f0300 488d1c8d00000000 8d040e }
// n = 7, score = 100
// 89442448 | mov dword ptr [esp + 0x20], eax
// ffc8 | mov edx, 0xfff
// 8bf8 | dec eax
// 410fb68c80023f0300 | lea ecx, [ebp + 0x1e0]
// 410fb6b480033f0300 | je 0x172
// 488d1c8d00000000 | dec eax
// 8d040e | mov edx, dword ptr [esp + 0x20]
$sequence_9 = { e8???????? 90 e8???????? 90 488bd3 488d8d80000000 e8???????? }
// n = 7, score = 100
// e8???????? |
// 90 | lea eax, [esi + ecx]
// e8???????? |
// 90 | dec esp
// 488bd3 | mov eax, ebx
// 488d8d80000000 | dec eax
// e8???????? |
condition:
7 of them and filesize < 585728
}
[TLP:WHITE] win_3cx_backdoor_w0 (20230331 | Detects 3CX installers created in March 2023, 3CX was known to be compromised at this time.)
rule win_3cx_backdoor_w0 {
meta:
author = "threatintel@volexity.com"
date = "2023-03-30"
description = "Detects 3CX installers created in March 2023, 3CX was known to be compromised at this time."
hash1 = "aa124a4b4df12b34e74ee7f6c683b2ebec4ce9a8edcf9be345823b4fdcf5d868"
reference = "https://www.reddit.com/r/crowdstrike/comments/125r3uu/20230329_situational_awareness_crowdstrike/"
memory_suitable = 0
license = "See license at https://github.com/volexity/threat-intel/blob/main/LICENSE.txt"
malpedia_reference = "https://malpedia.caad.fkie.fraunhofer.de/details/win.3cx_backdoor"
malpedia_version = "20230331"
malpedia_rule_date = "20230331"
malpedia_hash = ""
malpedia_license = ""
malpedia_sharing = "TLP:WHITE"
strings:
$cert = { 1B 66 11 DF 9C 9A 4D 6E CC 8E D5 0C 9B 91 78 73 }
$app = "3CXDesktopApp.exe"
$data = "202303"
condition:
all of them
}
[TLP:WHITE] win_3cx_backdoor_w1 (20230331 | Detection of malicious ICO files used in 3CX compromise.)
rule win_3cx_backdoor_w1 {
meta:
author = "threatintel@volexity.com"
description = "Detection of malicious ICO files used in 3CX compromise."
date = "2023-03-30"
hash1 = "a541e5fc421c358e0a2b07bf4771e897fb5a617998aa4876e0e1baa5fbb8e25c"
memory_suitable = 0
license = "See license at https://github.com/volexity/threat-intel/blob/main/LICENSE.txt"
malpedia_reference = "https://malpedia.caad.fkie.fraunhofer.de/details/win.3cx_backdoor"
malpedia_version = "20230331"
malpedia_rule_date = "20230331"
malpedia_hash = ""
malpedia_license = ""
malpedia_sharing = "TLP:WHITE"
strings:
$IEND_dollar = {49 45 4e 44 ae 42 60 82 24} // IEND.B`.$
$IEND_nodollar = {49 45 4e 44 ae 42 60 82 } // IEND.B`.
condition:
uint16be(0) == 0x0000 and
filesize < 120KB and
(
$IEND_dollar in (filesize-500..filesize) and not
$IEND_nodollar in (filesize-20..filesize) and
for any k in (1..#IEND_dollar):
(
for all i in (1..4):
(
// in range [0-9a-zA-Z]
uint8(@IEND_dollar[k]+!IEND_dollar[k] + i ) < 123 and
uint8(@IEND_dollar[k]+!IEND_dollar[k] + i) > 47
)
)
)
}