Skip to content

Commit

Permalink
Improve results scanning for Linux malware (chainguard-dev#608)
Browse files Browse the repository at this point in the history
* Improve coverage for timb-machine

* address more Ubuntu high false-positive

* further rule tuning

* further rule tuning

* Renamed rules

* rule tuning
  • Loading branch information
tstromberg authored Nov 10, 2024
1 parent 0f7f75f commit 297b82e
Show file tree
Hide file tree
Showing 244 changed files with 1,728 additions and 983 deletions.
9 changes: 5 additions & 4 deletions pkg/action/testdata/scan_archive
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# testdata/apko_nested.tar.gz ∴ /apko_0.13.2_linux_arm64/apko: medium
c2/addr/ip: medium
c2/server_address: medium
c2/addr/server: medium
collect/archives/zip: medium
credential/keychain: medium
credential/password: low
Expand All @@ -25,14 +25,15 @@ discover/network/interface_list: medium
discover/network/mac_address: medium
discover/network/netstat: medium
discover/processes/pgrep: medium
discover/system/cpu_info: low
discover/system/hostname_get: low
discover/system/cpu: low
discover/system/dmesg: low
discover/system/hostname: low
discover/system/platform: low
discover/user/HOME: low
discover/user/USER: low
discover/user/name_get: medium
evasion/bypass_security/linux/se: medium
evasion/hidden_paths/hidden: medium
evasion/file/prefix: medium
evasion/hide_artifacts/pivot_root: medium
exec/plugin: low
exec/program: medium
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import "math"
import "elf"

rule obfuscated_elf: high linux {
meta:
Expand Down Expand Up @@ -27,21 +27,5 @@ rule obfuscated_elf: high linux {
$debuglink = ".gnu_debuglink" fullword
condition:
uint32(0) == 1179403647 and none of them
}

rule high_entropy_header: high {
meta:
description = "high entropy ELF header (>7)"
hash_2023_UPX_0c25 = "0c25a05bdddc144fbf1ffa29372481b50ec6464592fdfb7dec95d9e1c6101d0d"
hash_2023_UPX_5a59 = "5a5960ccd31bba5d47d46599e4f10e455b74f45dad6bc291ae448cef8d1b0a59"
hash_2023_FontOnLake_38B09D690FAFE81E964CBD45EC7CF20DCB296B4D_elf = "f155fafa36d1094433045633741df98bbbc1153997b3577c3fa337cc525713c0"

strings:
$not_pyinst = "pyi-bootloader-ignore-signals"
$not_go = "syscall_linux.go"
$not_go2 = "vdso_linux.go"
condition:
uint32(0) == 1179403647 and math.entropy(1200, 4096) > 7 and none of ($not*)
filesize > 512 and elf.type == elf.ET_EXEC and uint32(0) == 1179403647 and none of them
}
30 changes: 30 additions & 0 deletions rules/anti-static/elf/entropy.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import "math"

private rule normal_elf {
condition:
filesize < 64MB and uint32(0) == 1179403647
}

private rule small_elf {
condition:
filesize < 400KB and uint32(0) == 1179403647
}

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

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

rule normal_elf_high_entropy_7_4: high {
meta:
description = "high entropy ELF binary (>7.4)"

strings:
$not_whirlpool = "libgcrypt-grub/cipher/whirlpool.c"
condition:
normal_elf and math.entropy(1, filesize) >= 7.4 and none of ($not*)
}
18 changes: 18 additions & 0 deletions rules/anti-static/elf/header.yara
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "elf"
import "math"

rule single_load_rwe: critical {
meta:
Expand Down Expand Up @@ -38,3 +39,20 @@ rule fake_dynamic_symbols: critical {
condition:
elf.type == elf.ET_EXEC and elf.entry_point < filesize and elf.number_of_sections > 0 and elf.dynamic_section_entries > 0 and for any i in (0..elf.dynamic_section_entries): (elf.dynamic[i].type == elf.DT_SYMTAB and not (for any j in (0..elf.number_of_sections): (elf.sections[j].type == elf.SHT_DYNSYM and for any k in (0..elf.number_of_segments): ((elf.segments[k].virtual_address <= elf.dynamic[i].val) and ((elf.segments[k].virtual_address + elf.segments[k].file_size) >= elf.dynamic[i].val) and (elf.segments[k].offset + (elf.dynamic[i].val - elf.segments[k].virtual_address)) == elf.sections[j].offset))))
}

rule high_entropy_header: high {
meta:
description = "high entropy ELF header (>7)"
hash_2023_UPX_0c25 = "0c25a05bdddc144fbf1ffa29372481b50ec6464592fdfb7dec95d9e1c6101d0d"
hash_2023_UPX_5a59 = "5a5960ccd31bba5d47d46599e4f10e455b74f45dad6bc291ae448cef8d1b0a59"
hash_2023_FontOnLake_38B09D690FAFE81E964CBD45EC7CF20DCB296B4D_elf = "f155fafa36d1094433045633741df98bbbc1153997b3577c3fa337cc525713c0"

strings:
$not_pyinst = "pyi-bootloader-ignore-signals"
$not_go = "syscall_linux.go"
$not_go2 = "vdso_linux.go"
$not_module = ".module_license" fullword
condition:
uint32(0) == 1179403647 and elf.type == elf.ET_EXEC and math.entropy(1200, 4096) > 7 and none of ($not*)
}
12 changes: 12 additions & 0 deletions rules/anti-static/elf/tiny.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import "elf"

rule impossibly_small_elf_program: high {
meta:
description = "ELF binary is unusually small"

strings:
$not_hello_c = "hello.c"
condition:
filesize < 8192 and filesize > 900 and uint32(0) == 1179403647 and elf.type == elf.ET_EXEC and none of ($not*)
}
26 changes: 26 additions & 0 deletions rules/anti-static/macho/entropy.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import "math"

private rule smaller_macho {
condition:
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 {
meta:
description = "higher entropy binary (>7.2)"

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

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

strings:
// prevent bazel false positive
$bin_java = "bin/java"
condition:
smaller_macho and math.entropy(1, filesize) >= 7.9 and not $bin_java
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
import "elf"

rule impossibly_small_elf_program: high {
meta:
description = "ELF binary is unusually small"

condition:
filesize < 8192 and uint32(0) == 1179403647 and elf.type == elf.ET_EXEC
}

rule impossibly_small_macho_program: medium {
meta:
description = "machO binary is unusually small"
Expand Down
24 changes: 16 additions & 8 deletions rules/anti-static/obfuscation/bitwise.yara
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,22 @@ rule excessive_bitwise_math: high {
hash_2023_aiohttpp_0_1_setup = "cfa4137756f7e8243e7c7edc7cb0b431a2f4c9fa401f2570f1b960dbc86ca7c6"

strings:
$x = /\-{0,1}[\da-z]{1,8} \<\< \-{0,1}\d{1,8}/
$not_Sodium = "Sodium_Core"
$not_SHA512 = "SHA512"
$not_SHA256 = "SHA256"
$not_MD4 = "MD4"
$not_algbase = "algbase" fullword
$not_jslint = "jslint bitwise"
$not_include = "#define "
$x = /\-{0,1}[\da-z]{1,8} \<\< \-{0,1}\d{1,8}/
$not_Sodium = "Sodium_Core"
$not_SHA512 = "SHA512"
$not_SHA256 = "SHA256"
$not_MD4 = "MD4"
$not_algbase = "algbase" fullword
$not_jslint = "jslint bitwise"
$not_include = "#define "
$not_bitwise = "bitwise" fullword
$not_bitmasks = "bitmasks" fullword
$not_ckbcomp = "ckbcomp" fullword
$not_bit_test = "bits_test" fullword
$not_testing = "*testing.T"
$not_effective_bits = "effective bits"
$not_bit_offsets = "bit offsets"
$not_uuid = "uuid" fullword
condition:
filesize < 192KB and #x > 64 and none of ($not*)
Expand Down
15 changes: 8 additions & 7 deletions rules/anti-static/obfuscation/hex.yara
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,14 @@ rule hex_parse_base64_high: high {
hash_1985_package_index = "8d4daa082c46bfdef3d85a6b5e29a53ae4f45197028452de38b729d76d3714d1"

strings:
$lang_node = /Buffer\.from\(\w{0,16}, {0,2}'hex'\)/
$lang_python = /\.unhexlify\(/
$b_base64 = "base64"
$b_b64decode = "b64decode"
$not_sha256 = "sha256" fullword
$not_sha512 = "sha512" fullword
$not_algorithms = "algorithms" fullword
$lang_node = /Buffer\.from\(\w{0,16}, {0,2}'hex'\)/
$lang_python = /\.unhexlify\(/
$b_base64 = "base64"
$b_b64decode = "b64decode"
$not_sha256 = "sha256" fullword
$not_sha512 = "sha512" fullword
$not_algorithms = "algorithms" fullword
$not_python_base64 = "return binascii.unhexlify(s)"
condition:
filesize < 32KB and any of ($lang*) and any of ($b*) and none of ($not*)
Expand Down
9 changes: 7 additions & 2 deletions rules/anti-static/obfuscation/python.yara
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,11 @@ rule fernet_base64: high {
$o6 = "exec("
$o7 = "eval("
$not_utils = "from cryptography import utils"
$not_fernet_itself = "class Fernet"
condition:
filesize < 2MB and any of ($fernet*) and any of ($bdecode*) and any of ($o*)
filesize < 2MB and any of ($fernet*) and any of ($bdecode*) and any of ($o*) and none of ($not*)
}

rule python_long_hex: medium {
Expand Down Expand Up @@ -261,8 +264,10 @@ rule python_hex_decimal: high {
$trash = /\\x{0,1}\d{1,3}\\/

Check warning on line 265 in rules/anti-static/obfuscation/python.yara

View check run for this annotation

VirusTotal YARA-CI / Rules Analysis

rules/anti-static/obfuscation/python.yara#L265

rule "python_hex_decimal": string "$trash" may slow down scanning
$not_testing_t = "*testing.T" fullword
condition:
filesize < 1MB and any of ($f*) and #trash in (filesize - 1024..filesize) > 100
filesize < 1MB and any of ($f*) and #trash in (filesize - 1024..filesize) > 100 and none of ($not*)
}

rule dumb_int_compares: high {
Expand Down
5 changes: 3 additions & 2 deletions rules/anti-static/packer/cx_freeze.yara
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ rule cxFreeze_Python_executable: high {
hash_2023_MacStealer_weed = "6a4f8b65a568a779801b72bce215036bea298e2c08ec54906bb3ebbe5c16c712"

strings:
$cxfreeze = "cx_Freeze"
$cxfreeze = "cx_Freeze"
$not_importlib = "tool like cx_Freeze"
condition:
filesize < 10485760 and $cxfreeze
filesize < 10485760 and $cxfreeze and none of ($not*)
}
27 changes: 0 additions & 27 deletions rules/anti-static/packer/high_entropy.yara

This file was deleted.

29 changes: 17 additions & 12 deletions rules/c2/addr/ip.yara
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,17 @@ rule elf_hardcoded_ip: high {

strings:
// stricter version of what's above: excludes 255.* and *.0.* *.1.*, and 8.* (likely Google)
$sus_ipv4 = /((25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[2345679])\.){3}(25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[2-9])/ fullword
$not_version = /((25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[2-9])\.){3}(25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[2-9])[\.\-]/
$not_incr = "10.11.12.13"
$not_169 = "169.254.169.254"
$not_spyder = "/search/spider"
$not_ruby = "210.251.121.214"
$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"
$sus_ipv4 = /((25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[2345679])\.){3}(25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[2-9])/ fullword

Check warning on line 33 in rules/c2/addr/ip.yara

View check run for this annotation

VirusTotal YARA-CI / Rules Analysis

rules/c2/addr/ip.yara#L33

rule "elf_hardcoded_ip": string "$sus_ipv4" may slow down scanning
$not_version = /((25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[2-9])\.){3}(25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[2-9])[\.\-]/

Check warning on line 34 in rules/c2/addr/ip.yara

View check run for this annotation

VirusTotal YARA-CI / Rules Analysis

rules/c2/addr/ip.yara#L34

rule "elf_hardcoded_ip": string "$not_version" may slow down scanning
$not_incr = "10.11.12.13"
$not_169 = "169.254.169.254"
$not_spyder = "/search/spider"
$not_ruby = "210.251.121.214"
$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_123456789 = "123.45.67.89"
$not_libebt_among_init = "libebt_among_init"
condition:
filesize < 12MB and uint32(0) == 1179403647 and 1 of ($sus_ip*) and none of ($not*)
Expand Down Expand Up @@ -73,14 +75,17 @@ rule hardcoded_ip_port: high {

strings:
$ipv4 = /([1-9][0-9]{1,2}\.){3}[1-9][0-9]{1,2}:\d{2,5}/ fullword

Check warning on line 77 in rules/c2/addr/ip.yara

View check run for this annotation

VirusTotal YARA-CI / Rules Analysis

rules/c2/addr/ip.yara#L77

rule "hardcoded_ip_port": string "$ipv4" may slow down scanning
$not_ssdp = "239.255.255.250:1900"
$not_ssdp = "239.255.255.250:"
$not_2181 = "10.101.203.230:2181"
$not_meta = "169.254.169.254:80"
$not_vnc = "10.10.10.10:5900"
$not_meta = "169.254.169.254:"
$not_vnc = "10.10.10.10:"
$not_azure_pgsql = "20.66.25.58:5432"
$not_wireguard = "127.212.121.99:999"
$not_minio = "172.16.34.31:9000"
$not_test = "def test_" fullword
$not_12 = "12.12.12.12:"
$not_21 = "21.21.21.21:"
$not_255 = "255.255.255.255:"
condition:
any of ($ip*) and none of ($not*)
Expand Down
28 changes: 14 additions & 14 deletions rules/c2/addr/server.yara
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
rule server_addr: medium {
rule server_address: medium {
meta:
description = "may execute a shell and communicate with a server"
description = "references a 'server address', possible C2 client"
hash_2024_Downloads_3105 = "31054fb826b57c362cc0f0dbc8af15b22c029c6b9abeeee9ba8d752f3ee17d7d"
hash_2023_Linux_Malware_Samples_450a = "450a7e35f13b57e15c8f4ce1fa23025a7c313931a394c40bd9f3325b981eb8a8"
hash_2023_Linux_Malware_Samples_458e = "458e3e66eff090bc5768779d5388336c8619a744f486962f5dfbf436a524ee04"

strings:
$serverAddr = "serverAddr"
$server_addr = "server_addr"
$exec = "exec"
$sh = "/bin/sh" fullword
$sh_bash = "/bin/bash" fullword
$sh_zsh = "/bin/zsh" fullword
$sh_script = "ShellScript"
$sh_exec = "ExecShell"
$sh_cmd = "cmd.exe"
$sh_powershell = "powershell.exe"
$s_underscores = /\w{0,32}server_addr\w{0,32}/
$s_mixed = /\w{0,32}serverAddr\w{0,32}/
$s_url = "serverURL" fullword
$s_url2 = "serverUrl" fullword
$s_connect = /\w{0,32}ConnectServer\w{0,32}/
condition:
filesize < 10MB and any of ($server*) and $exec and any of ($sh*)
any of ($s*)
}

rule server_addr_small: high {
Expand All @@ -34,6 +32,8 @@ rule server_addr_small: high {
$sh_cmd = "cmd.exe"
$sh_powershell = "powershell.exe"
$hash_bang = "#!"
condition:
filesize < 128KB and any of ($server*) and $exec and any of ($sh*)
filesize < 1MB and any of ($server*) and $exec and any of ($sh*) and not $hash_bang in (0..3)
}
Loading

0 comments on commit 297b82e

Please sign in to comment.