Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ELF malware detection improvements based on Wolfsbane analysis #680

Merged
merged 17 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions pkg/action/testdata/scan_archive
Original file line number Diff line number Diff line change
Expand Up @@ -1626,15 +1626,16 @@
"RuleName": "temp"
},
{
"Description": "Uses mktemp to create temporary files",
"Description": "creates temporary files",
"MatchStrings": [
"mktemp",
"temp file"
"temp file",
"tmpfile"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/fs/tempdir/tempfile-create.yara#mktemp",
"ID": "fs/tempdir/tempfile_create",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/fs/tempfile.yara#mktemp",
"ID": "fs/tempfile",
"RuleName": "mktemp"
},
{
Expand Down
12 changes: 12 additions & 0 deletions rules/anti-static/elf/multiple.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import "elf"

rule multiple_elf: medium {
meta:
description = "multiple ELF binaries within an ELF binary"

strings:
$elf_head = "\x7fELF"

condition:
uint32(0) == 1179403647 and #elf_head > 1
}
10 changes: 10 additions & 0 deletions rules/anti-static/obfuscation/hidden_literals.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
rule hidden_literals: medium {
meta:
description = "references hidden literals"

strings:
$ref = "hidden_literals"

condition:
filesize < 10MB and $ref
}
61 changes: 26 additions & 35 deletions rules/anti-static/xor/xor-commands.yara
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,32 @@ rule xor_commands: high {
description = "commands obfuscated using xor"

strings:
$b_chmod = "chmod " xor(1-31)
$b_curl = "curl -" xor(1-31)
$b_bin_sh = "/bin/sh" xor(1-31)
$b_bin_bash = "/bin/bash" xor(1-31)
$b_openssl = "openssl" xor(1-31)
$b_dev_null = "/dev/null" xor(1-31)
$b_usr_bin = "/usr/bin" xor(1-31)
$b_usr_sbin = "/usr/sbin" xor(1-31)
$b_var_tmp = "/var/tmp" xor(1-31)
$b_var_run = "/var/run" xor(1-31)
$b_screen_dm = "screen -" xor(1-31)
$b_zmodload = "zmodload" xor(1-31)
$b_dev_tcp = "/dev/tcp" xor(1-31)
$b_bash_i = "bash -i" xor(1-31)
$b_bash_c = "bash -c" xor(1-31)
$b_base64 = "base64" xor(1-31)
$b_eval = "eval(" xor(1-31)
$b_chmod2 = "chmod " xor(33-255)
$b_curl2 = "curl -" xor(33-255)
$b_bin_sh2 = "/bin/sh" xor(33-255)
$b_bin_bash2 = "/bin/bash" xor(33-255)
$b_openssl2 = "openssl" xor(33-255)
$b_dev_null2 = "/dev/null" xor(33-255)
$b_usr_bin2 = "/usr/bin" xor(33-255)
$b_usr_sbin2 = "/usr/sbin" xor(33-255)
$b_var_tmp2 = "/var/tmp" xor(33-255)
$b_var_run2 = "/var/run" xor(33-255)
$b_screen_dm2 = "screen -" xor(33-255)
$b_zmodload2 = "zmodload" xor(33-255)
$b_dev_tcp2 = "/dev/tcp" xor(33-255)
$b_bash_i2 = "bash -i" xor(33-255)
$b_bash_c2 = "bash -c" xor(33-255)
$b_base642 = "base64" xor(33-255)
$b_eval2 = "eval(" xor(33-255)

$b_chmod = "chmod " xor(1-31)
$b_curl = "curl -" xor(1-31)
$b_bin_sh = "/bin/sh" xor(1-31)
$b_bin_bash = "/bin/bash" xor(1-31)
$b_openssl = "openssl" xor(1-31)
$b_screen_dm = "screen -" xor(1-31)
$b_zmodload = "zmodload" xor(1-31)
$b_dev_tcp = "/dev/tcp" xor(1-31)
$b_bash_i = "bash -i" xor(1-31)
$b_bash_c = "bash -c" xor(1-31)
$b_base64 = "base64" xor(1-31)
$b_eval = "eval(" xor(1-31)
$b_chmod2 = "chmod " xor(33-255)
$b_curl2 = "curl -" xor(33-255)
$b_bin_sh2 = "/bin/sh" xor(33-255)
$b_bin_bash2 = "/bin/bash" xor(33-255)
$b_openssl2 = "openssl" xor(33-255)
$b_screen_dm2 = "screen -" xor(33-255)
$b_zmodload2 = "zmodload" xor(33-255)
$b_dev_tcp2 = "/dev/tcp" xor(33-255)
$b_bash_i2 = "bash -i" xor(33-255)
$b_bash_c2 = "bash -c" xor(33-255)
$b_base642 = "base64" xor(33-255)
$b_eval2 = "eval(" xor(33-255)
$b_xterm = "TERM=xterm" xor(1-31)
$b_xterm2 = "TERM=xterm" xor(33-255)
$not_password_list = "qwer1234"

condition:
Expand Down
32 changes: 32 additions & 0 deletions rules/anti-static/xor/xor-paths.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
rule xor_paths: high {
meta:
description = "paths obfuscated using xor"

strings:
$dev_shm = "/dev/shm" xor(1-31)
$dev_shm2 = "/dev/shm" xor(33-255)
$dev_null = "/dev/null" xor(1-31)
$dev_null2 = "/dev/null" xor(33-255)
$dev_stdin = "/dev/stdin" xor(1-31)
$dev_stdin2 = "/dev/stdin" xor(33-255)
$dev_stderr = "/dev/stderr" xor(1-31)
$dev_stderr2 = "/dev/stderr" xor(33-255)
$proc_net_tcp = "/proc/net/tcp" xor(1-31)
$proc_net_tcp2 = "/proc/net/tcp" xor(33-255)
$var_log_wtmp = "/var/log/wtmp" xor(1-31)
$var_log_wtmp2 = "/var/log/wtmp" xor(33-255)
$var_run_utmp = "/var/run/utmp" xor(1-31)
$var_run_utmp2 = "/var/run/utmp" xor(33-255)
$usr_bin = "/usr/bin" xor(1-31)
$usr_sbin = "/usr/sbin" xor(1-31)
$var_tmp = "/var/tmp" xor(1-31)
$var_run = "/var/run" xor(1-31)
$usr_bin2 = "/usr/bin" xor(33-255)
$usr_sbin2 = "/usr/sbin" xor(33-255)
$var_tmp2 = "/var/tmp" xor(33-255)
$var_run2 = "/var/run" xor(33-255)

condition:
filesize < 10MB and any of them
}

26 changes: 26 additions & 0 deletions rules/anti-static/xor/xor-terms.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
rule xor_terms: high {
meta:
description = "terms obfuscated using xor"

strings:
$LIBRARY = "LIBRARY" xor(1-31)
$LIBRARY2 = "LIBRARY" xor(33-255)
$INFECT = "INFECT" xor(1-31)
$INFECT2 = "INFECT" xor(33-255)
$MAGIC = "MAGIC" xor(1-31)
$MAGIC2 = "MAGIC" xor(33-255)
$plugin = "plugin" xor(1-31)
$plugin2 = "plugin2" xor(33-255)
$debug = "debug" xor(1-31)
$debug2 = "debug2" xor(33-255)
$evil = " evil " xor(1-31)
$evil2 = " evil " xor(33-255)
$environ = "environ" xor(1-31)
$environ2 = "environ" xor(33-255)

$xterm = "xterm" xor(1-31)
$xterm2 = "xterm" xor(33-255)

condition:
filesize < 5MB and any of them
}
38 changes: 36 additions & 2 deletions rules/discover/multiple.yara
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ rule sys_net_recon: medium {
$net_ipconfig = "ipconfig" fullword
$net_ipaddr = "ipaddr" fullword
$sys_getpass = "getpass.getuser"
$sys_whoami = "whoami" fullword
$sys_platform_node = "platform.node()" fullword
$sys_platform_platform = "platform.platform()" fullword
$sys_platform_system = "platform.system()" fullword
Expand All @@ -19,15 +20,48 @@ rule sys_net_recon: medium {
$sys_id = "id" fullword
$sys_lspi = "lspci"
$sys_sudo = /sudo.{0,4}-l/
$sys_uname = "uname -a"
$sys_whoami = "whoami" fullword
$sys_uname_a = "uname -a"
$sys_uname_r = "uname -r"
$sys_macos = "isPlatformOrVariant"
$sys_systeminfo = "systeminfo" fullword

condition:
filesize < 512KB and any of ($sys*) and any of ($net*)
}

rule user_sys_net_disk_recon: high {
meta:
description = "collects user, system, disk, and network information"

strings:
$net_ipconfig = "ipconfig"
$net_ipaddr = "ipaddr" fullword
$user_getpass = "getpass.getuser"
$user_whoami = "whoami"
$sys_platform_node = "platform.node()" fullword
$sys_platform_platform = "platform.platform()" fullword
$sys_platform_system = "platform.system()" fullword
$sys_tasklist = /tasklist.{0,4}\/svc/ fullword
$net_ifconfig = "ifconfig" fullword
$net_ip_addr = /ip.{0,4}addr/ fullword
$net_ip_route = /ip.{0,4}route/
$net_netstat = /netstat.{0,4}-[arn]/
$net_ufw = /ufw.{0,4}status/
$sys_hostname = "hostname" fullword
$sys_id = "id" fullword
$sys_lspi = "lspci"
$sys_sudo = /sudo.{0,4}-l/
$sys_uname_a = "uname -a"
$sys_uname_r = "uname -r"
$sys_macos = "isPlatformOrVariant"
$sys_systeminfo = "systeminfo" fullword
$disk_df_h = "df -h"
$disk_space = "Disk space"

condition:
filesize < 512KB and any of ($sys*) and any of ($net*) and any of ($user*) and any of ($disk*)
}

private rule discover_obfuscate {
strings:
$b64decode = "b64decode"
Expand Down
2 changes: 1 addition & 1 deletion rules/evasion/file/location/multiple.yara
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
rule multiple_elf: high linux {
rule multiple_elf_system_paths: high linux {
meta:
description = "references multiple system paths, may be trying to hide content"

Expand Down
12 changes: 12 additions & 0 deletions rules/evasion/file/prefix/prefix.yara
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ rule static_hidden_path: medium {
$ref
}

rule known_hidden_path: critical {
meta:
description = "known hidden file path"

strings:
$xl1 = /[a-z\/]{0,24}\/(var|usr|tmp|lib)\/[a-z\/]{0,24}\/\.Xl1[\w\_\-\.]{0,16}/
$kde_root = /[a-z\/]{0,24}\/(var|usr|tmp|lib)\/[a-z\/]{0,24}\/\.kde-root[\w\_\-\.]{0,16}/

condition:
any of them
}

rule hidden_path: medium {
meta:
description = "hidden path in a system directory"
Expand Down
12 changes: 12 additions & 0 deletions rules/evasion/logging/hide_shell_history.yara
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ rule hide_shell_history: high {
any of ($h*) and none of ($not*)
}

rule histfile_xor: high {
meta:
description = "commands obfuscated using xor"

strings:
$HISTFILE = "HISTFILE" xor(1-31)
$HISTFILE2 = "HISTFILE" xor(33-255)

condition:
filesize < 10MB and any of them
}

rule histfile_savehist_ld: high {
meta:
description = "likely hides shell command history"
Expand Down
16 changes: 16 additions & 0 deletions rules/evasion/rootkit/userspace.yara
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,22 @@ rule readdir_intercept: high {
filesize < 2MB and uint32(0) == 1179403647 and all of ($r*) and none of ($not*)
}

rule readdir_dlsym_interceptor: high {
meta:
description = "userland rootkit designed to hide files (readdir)"

filetypes = "so,c"

strings:
$dlsym = "dlsym" fullword
$readdir64 = "readdir64" fullword
$readlink_maybe_not_needed = "readlink"
$proc = "/proc"

condition:
filesize < 1MB and uint32(0) == 1179403647 and all of them
}

rule readdir_tcp_wrapper_intercept: high {
meta:
description = "userland rootkit designed to hide files and bypass tcp-wrappers"
Expand Down
3 changes: 2 additions & 1 deletion rules/exec/dylib/symbol-address.yara
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ rule dlsym: medium {
description = "get the address of a symbol"

strings:
$ref = "dlsym" fullword
$ref = "dlsym" fullword
$ref2 = "dlvsym" fullword

condition:
any of them
Expand Down
22 changes: 22 additions & 0 deletions rules/exec/program/program.yara
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,25 @@ rule npm_exec: medium {
condition:
all of them
}

rule hash_bang_bash_exec: high {
meta:
description = "starts program from a hash-bang line"

strings:
$bin_bash = /#!\/bin\/bash\s{1,256}\/[\w\/\.\-]{2,64}/

condition:
all of them and $bin_bash at 0
}

rule hash_bang_sh_exec: high {
meta:
description = "starts program from a hash-bang line"

strings:
$bin_sh = /#!\/bin\/sh\s{1,256}\/[\w\/\.\-]{2,64}/

condition:
all of them and $bin_sh at 0
}
1 change: 1 addition & 0 deletions rules/exec/shell/arbitrary_command-dev_null.yara
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ rule cmd_dev_null_quoted: high {
strings:
$ref = /"%s" {0,2}[12&]{0,1}> {0,1}\/dev\/null/
$ref2 = "\"%s\" >/dev/null"
$ref3 = /.{0,64} %s 2\>\/dev\/null/

condition:
any of them
Expand Down
15 changes: 15 additions & 0 deletions rules/fs/proc/pid-cmdline.yara
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import "math"

rule proc_s_cmdline: high {
meta:
description = "access command-line of other processes"
Expand Down Expand Up @@ -45,3 +47,16 @@ rule proc_py_cmdline: high {
condition:
any of them
}

rule proc_cmdline_near: high {
meta:
description = "access command-line for other processes"

strings:
$proc = "/proc" fullword
$fmt = "cmdline" fullword
$fmt_d = "%d" fullword

condition:
all of them and math.abs(@proc - @fmt) < 64 and math.abs(@fmt - @fmt_d) < 64
}
12 changes: 12 additions & 0 deletions rules/fs/proc/pid-fd.yara
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,15 @@ rule proc_fd_high: medium {
condition:
$ref and none of ($not*)
}

rule inspects_opened_sockets: high {
meta:
description = "inspects open file descriptors, looking for sockets"

strings:
$ref = "socket:[" fullword
$ref2 = /\/proc\/[%{$][\w\}]{0,12}\/fd/

condition:
all of them
}
Loading
Loading