Skip to content

Commit

Permalink
Improve detection of machO backdoors & stealers (#631)
Browse files Browse the repository at this point in the history
* improve malicious dmg detection

* Improve detection of machO backdoors & stealers

* improve rules

* update testdata

* update testdata

* tune rules

* tune rules

---------

Co-authored-by: Evan Gibler <[email protected]>
  • Loading branch information
tstromberg and egibs authored Nov 16, 2024
1 parent abb3d3f commit 6cd4c4b
Show file tree
Hide file tree
Showing 128 changed files with 619 additions and 210 deletions.
8 changes: 4 additions & 4 deletions pkg/action/testdata/scan_archive
Original file line number Diff line number Diff line change
Expand Up @@ -1100,8 +1100,8 @@
"MatchStrings": [
"/home/sha2561.32.11.33.01.33.11.33.21.34.01.34.11.35.01.36.0ID"
],
"RiskScore": 2,
"RiskLevel": "MEDIUM",
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/fs/path/home.yara#home_path",
"ID": "fs/path/home",
"RuleName": "home_path"
Expand Down Expand Up @@ -1911,8 +1911,8 @@
],
"RiskScore": 2,
"RiskLevel": "MEDIUM",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/net/http/content-length-0.yara#content_length_0",
"ID": "net/http/content_length_0",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/net/http/content-length.yara#content_length_0",
"ID": "net/http/content_length",
"RuleName": "content_length_0"
},
{
Expand Down
6 changes: 5 additions & 1 deletion pkg/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,16 @@ var rulesWithWarnings = map[string]bool{
"osascript_quitter": true,
"exfil_libcurl_elf": true,
"small_opaque_archaic_gcc": true,
"elf_hardcoded_ip": true,
"bin_hardcoded_ip": true,
"python_hex_decimal": true,
"python_long_hex": true,
"python_long_hex_multiple": true,
"pam_passwords": true,
"decompress_base64_entropy": true,
"macho_opaque_binary": true,
"macho_opaque_binary_long_str": true,
"long_str": true,
"macho_backdoor_libc_signature": true,
}

func Recursive(ctx context.Context, fss []fs.FS) (*yara.Rules, error) {
Expand Down
44 changes: 0 additions & 44 deletions rules/anti-static/base64/eval.yara
Original file line number Diff line number Diff line change
Expand Up @@ -57,47 +57,3 @@ rule python_exec_near_enough: high {
condition:
all of them and math.abs(@base64 - @exec) < 200
}

rule echo_decode_bash_probable: high {
meta:
description = "likely pipes base64 into a shell"

strings:
$echo = "echo" fullword
$base64_decode = "base64 --decode"
$base64_d = "base64 -d"
$bash = "bash" fullword
$sh = "sh" fullword
$not_uucp = "UUCP" fullword
$not_git = "git-core"
$not_copyright = "Copyright (c)"
$not_syntax = "syntax file"
condition:
filesize < 15KB and $echo and ($bash or $sh) and ($base64_decode or $base64_d) and none of ($not*)
}

rule acme_sh: override {
meta:
description = "acme.sh"
echo_decode_bash_probable = "medium"
iplookup_website = "medium"

strings:
$ref = "https://github.com/acmesh-official"
condition:
$ref
}

rule echo_decode_bash: critical {
meta:
description = "executes base64 encoded shell commands"

strings:
$bash = /[\w=\$]{0,8} ?\| ?base64 -d[ecod]{0,5} ?\| ?bash/
$sh = /[\w=\$]{0,8} ?\| ?base64 -d[ecod]{0,5} ?\| ?z?sh/
condition:
filesize < 64KB and any of them
}
50 changes: 49 additions & 1 deletion rules/anti-static/base64/exec.yara
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ rule base64_commands: high {
$b_tar_c = "tar -c" base64
$b_tar_x = "tar -x" base64
$b_bash_c = "bash -c" base64
$b_type_nul = "type nul" base64
$not_kandji = "kandji-parameter-agent"
$not_mdmprofile = "mdmprofile"
$not_example = "commands are encoded"
Expand All @@ -46,3 +45,52 @@ rule base64_suspicious_commands: critical {
condition:
filesize < 64KB and any of them
}

rule base64_exec: critical {
meta:
description = "executes base64 encoded commands"

strings:
$os_system = /os\.system\(b64[\"\'\(\)\w\=]{3,96}/ fullword
condition:
any of them
}

rule echo_decode_bash: critical {
meta:
description = "executes base64 encoded shell commands"

strings:
$ref = /base64 {0,2}(-d|--decode) {0,2}\| {0,2}(bash|zsh|sh)/ fullword
condition:
filesize < 256KB and any of them
}

import "math"

rule echo_decode_bash_probable: high {
meta:
description = "likely pipes base64 into a shell"

strings:
$decode = /base64 {0,2}(-d|--decode)/ fullword
$shell = /(bash|zsh|sh)/ fullword
condition:
filesize < 256KB and any of them and (@shell[#shell] - @decode[#decode]) < 32 and (@shell[#shell] - @decode[#decode]) > 0
}

rule acme_sh: override {
meta:
description = "acme.sh"
echo_decode_bash_probable = "medium"
iplookup_website = "medium"

strings:
$ref = "https://github.com/acmesh-official"
condition:
$ref
}
27 changes: 26 additions & 1 deletion rules/anti-static/binary/opaque.yara
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import "math"

rule opaque_binary: medium {
meta:
description = "binary contains little text content"

strings:
$word_with_spaces = /[a-z]{2,} [a-z]{2,}/
$word_with_spaces = /[a-z]{2,16} [a-uxyz]{2,16}/ fullword

Check warning on line 8 in rules/anti-static/binary/opaque.yara

View check run for this annotation

VirusTotal YARA-CI / Rules Analysis

rules/anti-static/binary/opaque.yara#L8

rule "opaque_binary": string "$word_with_spaces" may slow down scanning
$not_gmon_start = "__gmon_start__"
$not_usage = "usage:" fullword
$not_usage2 = "Usage:" fullword
Expand All @@ -13,3 +15,26 @@ rule opaque_binary: medium {
condition:
filesize < 52428800 and (uint32(0) == 1179403647 or uint32(0) == 4277009102 or uint32(0) == 3472551422 or uint32(0) == 4277009103 or uint32(0) == 3489328638 or uint32(0) == 3405691582 or uint32(0) == 3199925962) and #word_with_spaces < 4 and none of ($not*)
}

rule mystery_regex_binary: high {
meta:
description = "opaque binary with suspicious libc calls and regex usage"

strings:
$f_environ = "environ" fullword
$f_chdir = "chdir" fullword
$f_fork = "fork" fullword
$f_fopen = "fopen" fullword
$f_fwrite = "fwrite" fullword
$f_mkdir = "mkdir" fullword
$f_opendir = "opendir" fullword
$f_rand = "rand" fullword
$f_popen = "popen" fullword
$f_readdir = "readdir" fullword
$f_srand = "srand" fullword
$f_regexec = "regexec" fullword
$f_umask = "umask" fullword
condition:
filesize < 512KB and opaque_binary and math.entropy(1, filesize) >= 3.6 and all of them
}
6 changes: 3 additions & 3 deletions rules/anti-static/elf/entropy.yara
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ private rule small_elf {
filesize < 400KB and uint32(0) == 1179403647
}

rule normal_elf_high_entropy_7: medium {
rule higher_elf_entropy_68: medium {
meta:
description = "higher entropy ELF binary (>7.1)"
description = "higher entropy ELF binary (>6.95)"

condition:
normal_elf and math.entropy(1, filesize) >= 7.1
normal_elf and math.entropy(1, filesize) >= 6.95
}

rule normal_elf_high_entropy_7_4: high {
Expand Down
12 changes: 6 additions & 6 deletions rules/anti-static/macho/entropy.yara
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ private rule smaller_macho {
filesize < 64MB and (uint32(0) == 4277009102 or uint32(0) == 3472551422 or uint32(0) == 4277009103 or uint32(0) == 3489328638 or uint32(0) == 3405691582 or uint32(0) == 3199925962)
}

rule high_entropy_7_2: medium {
rule higher_entropy_6_9: medium {
meta:
description = "higher entropy binary (>7.2)"
description = "higher entropy binary (>6.9)"

condition:
smaller_macho and math.entropy(1, filesize) >= 7.2
smaller_macho and math.entropy(1, filesize) >= 6.9
}

rule high_entropy_7_9: high {
rule high_entropy_7_2: high {
meta:
description = "high entropy binary (>7.9)"
description = "high entropy binary (>7.2)"

strings:
// prevent bazel false positive
$bin_java = "bin/java"
condition:
smaller_macho and math.entropy(1, filesize) >= 7.9 and not $bin_java
smaller_macho and math.entropy(1, filesize) >= 7.2 and not $bin_java
}
4 changes: 2 additions & 2 deletions rules/anti-static/obfuscation/js.yara
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ rule js_hex_obfuscation: critical {

rule high_entropy: medium {
meta:
description = "high entropy javascript (>5.37)"
description = "high entropy javascript (>6)"

condition:
probably_js and math.entropy(1, filesize) >= 5.37
probably_js and math.entropy(1, filesize) >= 6
}

rule very_high_entropy: critical {
Expand Down
10 changes: 10 additions & 0 deletions rules/anti-static/obfuscation/sh.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
rule echo_base64_decode: high {
meta:
description = "echo and decode base64 text"

strings:
$ref = /echo [\w=\$]{2,256} {0,2}\| {0,2}base64 {0,2}(-d|--decode)/ fullword
condition:
filesize < 256KB and any of them
}
11 changes: 9 additions & 2 deletions rules/c2/addr/ip.yara
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,18 @@ rule hardcoded_ip: medium {
$not_1_2_3_4 = "1.2.3.4"
$not_root_servers_h = "128.63.2.53"
$not_root_servers_i = "192.36.148.17"
$not_send_att = "3.2.5.7"
condition:
filesize < 200MB and 1 of ($sus_ip*) and none of ($not*)
}

rule elf_hardcoded_ip: high {
private rule elf_or_macho {
condition:
uint32(0) == 1179403647 or (uint32(0) == 4277009102 or uint32(0) == 3472551422 or uint32(0) == 4277009103 or uint32(0) == 3489328638 or uint32(0) == 3405691582 or uint32(0) == 3199925962 or uint32(0) == 3405691583 or uint32(0) == 3216703178)
}

rule bin_hardcoded_ip: high {
meta:
description = "ELF with hardcoded IP address"

Expand All @@ -36,9 +42,10 @@ rule elf_hardcoded_ip: high {
$not_123456789 = "123.45.67.89"
$not_10_11_12_13 = "10.11.12.13"
$not_libebt_among_init = "libebt_among_init"
$not_send_att = "3.2.5.7"
condition:
filesize < 12MB and uint32(0) == 1179403647 and 1 of ($sus_ip*) and none of ($not*)
filesize < 12MB and elf_or_macho and 1 of ($sus_ip*) and none of ($not*)
}

rule http_hardcoded_ip: high exfil {
Expand Down
11 changes: 11 additions & 0 deletions rules/c2/connect/curl_easy.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
rule curl_easy: medium {
meta:
description = "uses curl_easy for HTTP transfers, possibly to a C2"

strings:
$curl = "curl_easy_init" fullword
condition:
filesize < 1MB and all of them
}

10 changes: 10 additions & 0 deletions rules/collect/databases/sql.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
rule sql: low {
meta:
description = "accesses SQL databases"

strings:
$ref = "SQL" fullword
condition:
any of them
}
2 changes: 2 additions & 0 deletions rules/crypto/tls.yara
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ rule tls {
$tlsversion = "TLSVersion"
$TLS123 = "TLS13"
$tls123 = "tls123"
$require = "require(\"tls\")"
$require2 = "require('tls')"
condition:
any of them
Expand Down
2 changes: 1 addition & 1 deletion rules/data/random/bytes.yara
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ rule rand {
$ref = ".randomBytes(" fullword
condition:
$ref
any of them
}
1 change: 0 additions & 1 deletion rules/discover/system/hardware.yara
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ rule macos_hardware_profiler: medium {

strings:
$p_system_profiler = "system_profiler SPHardwareDataType"
$p_uuid = "IOPlatformUUID"
$p_ioreg = "ioreg -"
$p_hw_model = "hw.model"
$p_machineid = "machineid.ID"
Expand Down
1 change: 1 addition & 0 deletions rules/discover/system/hostname.yara
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ rule gethostname {
$proc = "/proc/sys/kernel/hostname"
$python = "socket.gethostname"
$nodejs = "os.hostname()"
$js = "os.default.hostname"
condition:
any of them
Expand Down
10 changes: 10 additions & 0 deletions rules/evasion/indicator_blocking/close_window.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
rule tell_terminal_to_close: high {
meta:
description = "closes Terminal window"

strings:
$close = "tell application \"Terminal\" to close first window"
condition:
filesize < 10MB and all of them
}
Loading

0 comments on commit 6cd4c4b

Please sign in to comment.