Add rules for detecting donut-related features (#997)

* Initial additions for detecting donut features

Signed-off-by: Still Hsu <dev@stillu.cc>

* Lint rules

Signed-off-by: Still Hsu <dev@stillu.cc>

* Update ATT&CK for donut rule

Signed-off-by: Still Hsu <dev@stillu.cc>

* Fix comment for dynamic scope on donut loader

Signed-off-by: Still Hsu <dev@stillu.cc>

* Require at least one donut function match for donut rule

Signed-off-by: Still Hsu <dev@stillu.cc>

* Add offset for examples

Signed-off-by: Still Hsu <dev@stillu.cc>

* Add indirect call for IAssembly matching

Signed-off-by: Still Hsu <dev@stillu.cc>

* Match known vtable offsets for assembly loading

* Remove loop matching

---------

Signed-off-by: Still Hsu <dev@stillu.cc>
This commit is contained in:
Still / Azaka 2025-03-22 00:15:28 +08:00 committed by GitHub
parent 2800fd34de
commit 7269873b0c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 186 additions and 1 deletions

View file

@ -6,6 +6,7 @@ rule:
- "@r3c0nst (Frank Boldewin)"
- moritz.raabe@mandiant.com
- cdong49@gatech.edu
- still@teamt5.org
description: detects decompression function of library aPLib
scopes:
static: function
@ -25,7 +26,9 @@ rule:
- instruction:
- description: line 138, if (offs >= 32000)
- mnemonic: cmp
- number: 32000
- or:
- number: 31999
- number: 32000
- instruction:
- description: line 144, if (offs < 128)
- mnemonic: cmp

View file

@ -0,0 +1,42 @@
rule:
meta:
name: encrypt data using chaskey
namespace: data-manipulation/encryption/chaskey
authors:
- still@teamt5.org
scopes:
static: function
dynamic: unsupported # requires characteristic, mnemonic features
att&ck:
- Defense Evasion::Obfuscated Files or Information [T1027]
mbc:
- Defense Evasion::Obfuscated Files or Information::Encryption-Standard Algorithm [E1027.m05]
references:
- https://mouha.be/chaskey/
- https://github.com/TheWover/donut/blob/47758d787209dd1744f58c140102ac91b649df16/encrypt.c#L37
examples:
- d890c1c67d83f1131c065b5eb5f263cbf54559dbcdb4562c3bde3dc30d1a3205:0x19495
features:
- and:
- count(characteristic(nzxor)): 6 or more
- match: contain loop
- instruction:
- or:
- mnemonic: rol
- mnemonic: shl
- number: 13
- instruction:
- or:
- mnemonic: rol
- mnemonic: shl
- number: 8
- instruction:
- or:
- mnemonic: rol
- mnemonic: shl
- number: 7
- instruction:
- or:
- mnemonic: rol
- mnemonic: shl
- number: 5

View file

@ -0,0 +1,37 @@
rule:
meta:
name: encrypt data using speck
namespace: data-manipulation/encryption/speck
authors:
- still@teamt5.org
scopes:
static: function
dynamic: unsupported # requires characteristic, mnemonic features
att&ck:
- Defense Evasion::Obfuscated Files or Information [T1027]
mbc:
- Defense Evasion::Obfuscated Files or Information::Encryption-Standard Algorithm [E1027.m05]
references:
- https://github.com/maxmouchet/gfc/blob/8d818b0fe2023c92cbf8d7eb89674916bdc78f62/src/gfc.c#L15
- https://github.com/TheWover/donut/blob/47758d787209dd1744f58c140102ac91b649df16/hash.c#L35
examples:
- d890c1c67d83f1131c065b5eb5f263cbf54559dbcdb4562c3bde3dc30d1a3205:0x1929D
features:
- and:
- 2 or more:
- mnemonic: rol
- mnemonic: ror
- mnemonic: shl
- mnemonic: imul
- count(characteristic(nzxor)): 2 or more
- match: contain loop
- instruction:
- mnemonic: cmp
- or:
- number: 0x1A = encryption loop
- number: 0x1B = encryption loop
- instruction:
- mnemonic: cmp
- or:
- number: 0x3 = master key copy loop
- number: 0x4 = master key copy loop

View file

@ -0,0 +1,39 @@
rule:
meta:
name: load assembly via IAssembly
namespace: load-code/dotnet
authors:
- still@teamt5.org
scopes:
static: function
dynamic: unsupported
references:
- https://github.com/TheWover/donut/blob/master/loader/inmem_dotnet.c
examples:
- d890c1c67d83f1131c065b5eb5f263cbf54559dbcdb4562c3bde3dc30d1a3205:0x1641B
features:
- and:
- 3 or more:
- instruction:
- description: _MethodInfoVtbl->Invoke_3
- or:
- mnemonic: call
- mnemonic: mov
- or:
- operand[1].offset: 0x128
- operand[1].offset: 0x94
- instruction:
- description: _AssemblyVtbl->InvokeMember_3
- or:
- mnemonic: call
- mnemonic: mov
- or:
- operand[1].offset: 0xE4
- operand[1].offset: 0x88
- instruction:
- mnemonic: mov
- number: 0x2008 = VT_ARRAY | VT_BSTR (for passing args)
- instruction:
- mnemonic: mov
- number: 0x118 = BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public (InvokeMember_3)
- characteristic: indirect call

View file

@ -0,0 +1,64 @@
rule:
meta:
name: load shellcode via donut
namespace: malware-family/donut-loader
authors:
- still@teamt5.org
scopes:
static: file
dynamic: unsupported # requires mnemonic features
att&ck:
- Defense Evasion::Obfuscated Files or Information [T1027]
- Defense Evasion::Obfuscated Files or Information::Software Packing [T1027.002]
- Execution::Native API [T1106]
- Execution::Command and Scripting Interpreter::Visual Basic [T1059.005]
- Execution::Command and Scripting Interpreter::JavaScript [T1059.007]
- Execution::Inter-Process Communication::Component Object Model [T1559.001]
examples:
- d890c1c67d83f1131c065b5eb5f263cbf54559dbcdb4562c3bde3dc30d1a3205
features:
- and:
- 3 or more:
- match: encrypt data using chaskey
- match: encrypt data using speck
- match: load assembly via IAssembly
- match: decompress data using aPLib
- or:
- function:
- and:
- description: match donut DownloadFromHTTP
- 3 or more:
- number: 0x3380 = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_WRONG_USAGE | SECURITY_FLAG_IGNORE_REVOCATION
- number: 0x84600200 = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_AUTO_REDIRECT
- number: 0x20000013 = HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER
- number: 0x20000005 = HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER
- instruction:
- mnemonic: or
- or:
- number: 0x800000 = INTERNET_FLAG_SECURE
- number: 0x3000 = INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
- number: 0x803000 = INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
- instruction:
- mnemonic: cmp
- number: 200 = HTTP_STATUS_OK
- instruction:
- mnemonic: cmp
- number: 3 = DONUT_ENTROPY_DEFAULT
- function:
- and:
- description: match donut MainProc
- and:
- description: calculate allocation size based on DONUT_MODULE size
- instruction:
- mnemonic: add
- number: 0x530 = DONUT_MODULE struct size # not super reliable if donut ever changes the struct or different arch
- and:
- description: get required DLLs by splitting DLL names
- instruction:
- mnemonic: cmp
- number: 0x3B = ';'
- instruction:
- mnemonic: cmp
- or:
- number: 259 = MAX_PATH
- number: 260 = MAX_PATH