Skip to content

Commit

Permalink
Merge branch 'main' into malcontent-version-bump-v1.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
egibs authored Oct 24, 2024
2 parents c9bb3eb + 6ef18f9 commit 410d75e
Show file tree
Hide file tree
Showing 92 changed files with 1,230 additions and 339 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fix: $(FIXERS)
# END: lint-install ../malcontent

SAMPLES_REPO ?= chainguard-dev/malcontent-samples
SAMPLES_COMMIT ?= 83f0693557b748ab4c395bdd749b85876fa53e92
SAMPLES_COMMIT ?= 01cc2a1248c20c8a3d2b8b0acff0daf04196d487
OUT_DIR=out/samples-$(SAMPLES_COMMIT).tmp
out/samples-$(SAMPLES_COMMIT):
mkdir -p out
Expand Down
7 changes: 5 additions & 2 deletions pkg/action/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ var (
)

// findFilesRecursively returns a list of files found recursively within a path.
func findFilesRecursively(_ context.Context, rootPath string) ([]string, error) {
func findFilesRecursively(ctx context.Context, rootPath string) ([]string, error) {
var files []string

// Follow symlink if provided at the root
Expand All @@ -49,10 +49,13 @@ func findFilesRecursively(_ context.Context, rootPath string) ([]string, error)
}
}

logger := clog.FromContext(ctx)

err = filepath.WalkDir(root,
func(path string, info os.DirEntry, err error) error {
if err != nil {
return fmt.Errorf("walk: %w", err)
logger.Errorf("error: %s: %s", path, err)
return nil
}
if info.IsDir() || strings.Contains(path, "/.git/") {
return nil
Expand Down
21 changes: 18 additions & 3 deletions pkg/render/terminal_brief.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import (
"context"
"fmt"
"io"
"strings"

"github.com/chainguard-dev/malcontent/pkg/malcontent"
"github.com/fatih/color"
)

type TerminalBrief struct {
Expand All @@ -37,10 +37,25 @@ func (r TerminalBrief) File(_ context.Context, fr *malcontent.FileReport) error
return nil
}

fmt.Fprintf(r.w, "├── 📄 %s %s%s%s\n", fr.Path, color.HiBlackString("["), riskInColor(fr.RiskLevel), color.HiBlackString("]"))
fmt.Fprintf(r.w, "├─ %s %s\n", riskEmoji(fr.RiskScore), fr.Path)

for _, b := range fr.Behaviors {
fmt.Fprintf(r.w, "│ %s %s: %s\n", riskEmoji(fr.RiskScore), riskColor(fr.RiskLevel, b.ID), b.Description)
evidence := []string{}
for _, m := range b.MatchStrings {
if len(m) > 2 && !strings.Contains(b.Description, m) {
evidence = append(evidence, m)
}
}

e := strings.Join(evidence, ", ")
if len(e) > 32 {
e = e[0:31] + "…"
}
if len(e) > 0 {
e = ": " + e
}

fmt.Fprintf(r.w, "│ %s %s — %s%s\n", riskColor(fr.RiskLevel, "•"), riskColor(fr.RiskLevel, b.ID), b.Description, e)
}

return nil
Expand Down
9 changes: 5 additions & 4 deletions rules/builtin/kernel_module.yara
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@

rule kmod : high {
rule kmod : medium linux {
meta:
description = "includes Linux kernel module source code"
description = "Linux kernel module source code"
hash_2024_enumeration_deepce = "76b0bcdf0ea0b62cee1c42537ff00d2100c54e40223bbcb8a4135a71582dfa5d"
filetypes = "c,h"
strings:
$ref = "<linux/kmod.h>"
$not_define_linux = "#define _LINUX_MODULE_H"
condition:
any of them
$ref and none of ($not*)
}
39 changes: 0 additions & 39 deletions rules/combo/critical_paths.yara

This file was deleted.

52 changes: 52 additions & 0 deletions rules/combo/degrader/linux_paths.yara
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@

rule linux_critical_system_paths : medium {
meta:
description = "accesses multiple critical Linux paths"
strings:
$p_etc_crontab = "/etc/crontab"
$p_etc_sysctl_conf = "/etc/sysctl.conf"
$p_etc_init_d = /\/etc\/init.d[\w\/\.\-]{0,32}/
$p_etc_cron_d = /\/etc\/cron.d[\w\/\.\-]{0,32}/
$p_etc_selinux = /\/etc\/selinux[\w\/\.\-]{0,32}/
$p_etc_systemd = /\/etc\/systemd[\w\/\.\-]{0,32}/
$p_etc_preload = "/etc/ld.so.preload"
$p_ld_so_cache = "/etc/ld.so.cache"
$p_var_run = /\/var\/run[\w\/\.\-]{0,32}/
$p_var_log = /\/var\/log[\w\/\.\-]{0,32}/
$p_usr_libexec = /\/usr\/libexec[\w\/\.\-]{0,32}/
$p_tmp = /\/tmp\/[\w\/\.\-]{0,32}/
$p_sbin = /\/sbin\/[\w\/\.\-]{0,32}/
$p_lib_systemd = /\/lib\/systemd[\w\/\.\-]{0,32}/
$p_boot = /\/boot\/[\w\/\.\-]{0,32}/
$proc_self_cmdline = "/proc/self/cmdline"
$proc_self_cgroup = "/proc/self/cgroup"
$p_lib = "/usr/lib/x86_64-linux-gnu/"
$p_lib_ld = "/lib64/ld-linux-x86-64.so.2"
$p_sys = /\/sys\/(devices|class)[\w\/\.\-]{0,32}/
$p_sysctl = /sysctl[ -a-z]{0,32}/
$p_dev_watchdog = "/dev/watchdog"
$p_ps = "/usr/bin/ps"
$p_ss = "/usr/bin/lsof"
$p_ssh = "/usr/bin/ssh"
$p_dev_shm = "/dev/shm"
condition:
filesize < 120MB and any of ($p_etc*) and 5 of ($p*)
}

rule linux_critical_system_paths_small_elf : high {
meta:
description = "ELF accesses multiple critical Linux paths"
strings:
$not_vim = "VIMRUNTIME" fullword
condition:
filesize < 10MB and uint32(0) == 1179403647 and linux_critical_system_paths and none of ($not*)
}

rule linux_critical_system_paths_small_shell : high {
meta:
description = "script accesses multiple critical Linux paths"
strings:
$hash_bang = "#!"
condition:
filesize < 64KB and $hash_bang in (0..2) and linux_critical_system_paths
}
8 changes: 6 additions & 2 deletions rules/combo/degrader/selinux_firewall.yara
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@

rule selinux_firewall : high {
rule selinux_firewall : high linux {
meta:
hash_2023_Unix_Downloader_Rocke_228e = "228ec858509a928b21e88d582cb5cfaabc03f72d30f2179ef6fb232b6abdce97"
hash_2023_Unix_Downloader_Rocke_2f64 = "2f642efdf56b30c1909c44a65ec559e1643858aaea9d5f18926ee208ec6625ed"
hash_2023_Unix_Downloader_Rocke_6107 = "61075056b46d001e2e08f7e5de3fb9bfa2aabf8fb948c41c62666fd4fab1040f"
filetypes = "elf,so"
description = "references both SELinux and iptables/firewalld"
strings:
$selinux = /SELINUX[=\w]{0,32}/ fullword
$f_iptables = /iptables[ -\w]{0,32}/
Expand All @@ -12,6 +14,8 @@ rule selinux_firewall : high {
$not_iptables = "iptables-restore"
$not_iptables_nft = "iptables-nft"
$not_selinux_init = "SELINUX_INIT"
$not_define = "#define" fullword
$not_netlink = "NETLINK" fullword
condition:
$selinux and any of ($f*) and none of ($not*)
filesize < 1MB and $selinux and any of ($f*) and none of ($not*)
}
3 changes: 2 additions & 1 deletion rules/combo/dropper/binary.yara
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ rule chmod_executable_shell_binary : high {
$chmod2 = /chmod [\-\w ]{0,4}\+[rw]{0,2}[75][ \$\@\w\/\.]{0,64}/
$http = "http:"
$https = "https:"
$not_example = "try 'chmod +x'"
condition:
filesize < 10MB 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 any of ($chmod*) and any of ($http*)
filesize < 10MB 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 any of ($chmod*) and any of ($http*) and none of ($not*)
}

rule download_and_execute : high {
Expand Down
6 changes: 4 additions & 2 deletions rules/combo/locker/readdir_rename_encrypt.yara
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@

rule conti_alike : high {
rule conti_alike : high posix {
meta:
description = "Reads directories, renames files, encrypts files"
hash_2023_Downloads_06ab = "06abc46d5dbd012b170c97d142c6b679183159197e9d3f6a76ba5e5abf999725"
hash_2023_Downloads_8b57 = "8b57e96e90cd95fc2ba421204b482005fe41c28f506730b6148bcef8316a3201"
hash_2023_Downloads_f864 = "f864922f947a6bb7d894245b53795b54b9378c0f7633c521240488e86f60c2c5"
filetypes = "so,elf,macho"
strings:
$readdir = "readdir" fullword
$rename = "rename" fullword
Expand All @@ -13,6 +14,7 @@ rule conti_alike : high {
$enc3 = "Encrypting file"
$enc4 = "files_encrypted"
$enc5 = "encrypts files"
$not_fscrypt_h = "#define _LINUX_FSCRYPT_H"
condition:
filesize < 1MB and $readdir and $rename and any of ($enc*)
filesize < 1MB and $readdir and $rename and any of ($enc*) and none of ($not*)
}
13 changes: 7 additions & 6 deletions rules/combo/recon/system_network.yara
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ private rule exfil {
filesize < 512KB and any of them
}


rule sys_net_recon_exfil : high {
meta:
description = "may exfiltrate collected system and network information"
condition:
sys_net_recon and (obfuscate or exfil)
}
meta:
description = "may exfiltrate collected system and network information"
strings:
$not_curl = "CURLAUTH_ONLY"
condition:
sys_net_recon and (obfuscate or exfil) and none of ($not*)
}
41 changes: 31 additions & 10 deletions rules/evasion/fake-process.yara
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
rule fake_kworker_val : critical {
rule fake_kworker : critical linux {
meta:
description = "Pretends to be a kworker kernel thread"
hash_2023_Unix_Downloader_Rocke_228e = "228ec858509a928b21e88d582cb5cfaabc03f72d30f2179ef6fb232b6abdce97"
hash_2023_Unix_Downloader_Rocke_2f64 = "2f642efdf56b30c1909c44a65ec559e1643858aaea9d5f18926ee208ec6625ed"
hash_2023_Unix_Downloader_Rocke_6107 = "61075056b46d001e2e08f7e5de3fb9bfa2aabf8fb948c41c62666fd4fab1040f"
strings:
$kworker = /\[{0,1}kworker\/[\d:\]]{1,5}/
$kworker2 = "kworker" fullword
$kworker = /\[{0,1}kworker\/[\w\%:\-\]]{1,16}/
$kworker3 = "[kworker"
condition:
filesize < 100MB and any of ($k*)
}

rule kworker : medium linux {
meta:
description = "Mentions kworker"
strings:
$kworker2 = "kworker" fullword
$not_under_kworker = "_kworker"
condition:
any of ($k*) and none of ($not*)
filesize < 1MB and any of ($k*) and none of ($not*)
}

rule fake_syslogd : critical {
Expand All @@ -20,10 +27,10 @@ rule fake_syslogd : critical {
strings:
$ref = "[syslogd]"
condition:
any of them
filesize < 1MB and any of them
}

rule fake_bash_val : high {
rule fake_bash : high {
meta:
description = "Pretends to be a bash process"
strings:
Expand All @@ -32,18 +39,18 @@ rule fake_bash_val : high {
filesize < 8KB and $bash
}

rule fake_systemd : critical {
rule fake_systemd : critical linux {
meta:
description = "Pretends to be a systemd worker"
strings:
$ref = "systemd-worker" fullword
condition:
filesize < 100MB and $ref
filesize < 10MB and $ref
}

rule fake_process_names : high {
rule known_fake_process_names : high {
meta:
description = "mentions known fake process names"
description = "mentions known fake process name"
strings:
$kdevchecker = "kdevchecker" fullword
$kworkerr = "kworkerr" fullword
Expand All @@ -54,3 +61,17 @@ rule fake_process_names : high {
condition:
filesize < 10MB and any of them
}

rule multiple_known_fake_process_names : critical {
meta:
description = "mentions multiple known fake process names"
strings:
$kdevchecker = "kdevchecker" fullword
$kworkerr = "kworkerr" fullword
$ksoftriqd = "ksoftriqd" fullword
$kdevtmpfsi = "kdevtmpfsi" fullword
$kthreaddk = "kthreaddk" fullword
$deamon = "deamon" fullword
condition:
filesize < 10MB and 2 of them
}
3 changes: 2 additions & 1 deletion rules/evasion/packer/upx.yara
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ rule upx_elf : high {
strings:
$proc_self = "/proc/self/exe"
$prot_exec = "PROT_EXEC|PROT_WRITE failed"
$not_upx_itself = "UPX comes with ABSOLUTELY NO WARRANTY"
condition:
uint32(0) == 1179403647 and $prot_exec and $proc_self
uint32(0) == 1179403647 and $prot_exec and $proc_self and none of ($not*)
}

rule upx_elf_tampered : critical {
Expand Down
Loading

0 comments on commit 410d75e

Please sign in to comment.