From 23ae8cfd93914371dbab26bc37c00afacfbb378b Mon Sep 17 00:00:00 2001 From: egibs <20933572+egibs@users.noreply.github.com> Date: Thu, 22 May 2025 07:12:55 -0500 Subject: [PATCH] Revert usage of include statements Signed-off-by: egibs <20933572+egibs@users.noreply.github.com> --- pkg/compile/compile.go | 57 ---- rules/anti-behavior/random_behavior.yara | 19 +- rules/anti-static/elf/entropy.yara | 18 +- rules/anti-static/macho/entropy.yara | 9 +- rules/anti-static/macho/footer.yara | 7 +- rules/anti-static/packer/aes.yara | 8 +- rules/anti-static/unmarshal/marshal.yara | 13 +- rules/c2/addr/ip.yara | 9 +- rules/c2/addr/url.yara | 9 +- rules/c2/tool_transfer/download.yara | 10 +- rules/c2/tool_transfer/macos.yara | 12 +- rules/c2/tool_transfer/python.yara | 74 +++- rules/data/builtin/multiple.yara | 29 +- rules/discover/multiple.yara | 33 +- rules/discover/user/username-get.yara | 21 +- .../indicator_blocking/hidden_window.yara | 21 +- .../indicator_blocking/mask_exceptions.yara | 18 +- rules/evasion/logging/wipe.yara | 23 +- rules/evasion/net/hide_ports.yara | 12 +- .../evasion/self_deletion/run_and_delete.yara | 22 +- rules/exec/program/opaque.yara | 14 +- rules/exec/shell/relative-semicolon.yara | 10 +- rules/exfil/discord.yara | 35 +- rules/exfil/nodejs.yara | 29 +- rules/exfil/npm.yara | 25 +- rules/exfil/oauth.yara | 12 +- rules/fs/path/applications.yara | 16 +- rules/global/global.yara | 320 ------------------ rules/impact/degrade/firewall.yara | 16 +- rules/impact/exploit/breakout.yara | 14 +- rules/impact/exploit/exploit.yara | 18 +- rules/impact/remote_access/backdoor.yara | 25 +- rules/impact/remote_access/py_setuptools.yara | 51 ++- rules/impact/wipe/crypto.yara | 9 +- rules/malware/family/amos.yara | 18 +- rules/malware/family/clapzok.yara | 7 +- rules/malware/family/poseidon_stealer.yara | 14 +- rules/net/download/fetch.yara | 14 +- rules/sus/compiler.yara | 12 +- rules/sus/entitlement.yara | 12 +- 40 files changed, 584 insertions(+), 511 deletions(-) delete mode 100644 rules/global/global.yara diff --git a/pkg/compile/compile.go b/pkg/compile/compile.go index 14ba0918a..9b0eb07ec 100644 --- a/pkg/compile/compile.go +++ b/pkg/compile/compile.go @@ -4,14 +4,11 @@ package compile import ( - "bytes" "context" "fmt" "io/fs" - "os" "path/filepath" "regexp" - "runtime" "strings" "github.com/chainguard-dev/clog" @@ -20,11 +17,6 @@ import ( yarax "github.com/VirusTotal/yara-x/go" ) -const ( - globalInclude = `include "rules/global/global.yara"` - globalPath = "rules/global/global.yara" -) - var FS = rules.FS // badRules are noisy 3rd party rules to silently disable. @@ -167,47 +159,6 @@ func removeRules(data []byte, rulesToRemove []string) []byte { return newlinePattern.ReplaceAll(modified, []byte("\n\n")) } -// findRoot locates the packages's root directory on the fly. -func findRoot() (string, error) { - _, here, _, ok := runtime.Caller(0) - if !ok { - return "", fmt.Errorf("failed to get current file path") - } - - dir := filepath.Dir(here) - current := dir - for { - rulesPath := filepath.Join(current, "rules") - if fi, err := os.Stat(rulesPath); err == nil && fi.IsDir() { - return current, nil - } - - parent := filepath.Dir(current) - if parent == current { - break - } - current = parent - } - - rulesPath := filepath.Join(filepath.Dir(dir), "rules") - if fi, err := os.Stat(rulesPath); err == nil && fi.IsDir() { - return filepath.Dir(dir), nil - } - - return "", fmt.Errorf("could not find rules directory from %s", dir) -} - -// replaceGlobal updates the include string to reference the absolute path of rules/global/global.yara -// by default, the relative path is valid for local compilations and builds done from the root of the repository, -// but this is not valid for test files located in various directories. -func replaceGlobal(data []byte, path string) []byte { - modified := data - if bytes.Contains(data, []byte(globalInclude)) { - modified = bytes.Replace(data, []byte(globalInclude), fmt.Appendf(nil, `include "%s"`, path), 1) - } - return modified -} - func Recursive(ctx context.Context, fss []fs.FS) (*yarax.Rules, error) { if ctx.Err() != nil { return nil, ctx.Err() @@ -218,11 +169,6 @@ func Recursive(ctx context.Context, fss []fs.FS) (*yarax.Rules, error) { return nil, fmt.Errorf("yarax compiler: %w", err) } - rootPath, err := findRoot() - if err != nil { - return nil, err - } - rulesToRemove := getRulesToRemove() for _, root := range fss { @@ -243,9 +189,6 @@ func Recursive(ctx context.Context, fss []fs.FS) (*yarax.Rules, error) { bs = removeRules(bs, rulesToRemove) - globalAbs := filepath.Join(rootPath, globalPath) - bs = replaceGlobal(bs, globalAbs) - yxc.NewNamespace(path) if err := yxc.AddSource(string(bs), yarax.WithOrigin(path)); err != nil { return fmt.Errorf("failed to parse %s: %v", path, err) diff --git a/rules/anti-behavior/random_behavior.yara b/rules/anti-behavior/random_behavior.yara index 36cd1a7a0..6e45dbe2f 100644 --- a/rules/anti-behavior/random_behavior.yara +++ b/rules/anti-behavior/random_behavior.yara @@ -1,6 +1,21 @@ import "math" -include "rules/global/global.yara" +private rule random_behavior_pythonSetup { + strings: + $if_distutils = /from distutils.core import .{0,32}setup/ + $if_setuptools = /from setuptools import .{0,32}setup/ + $i_setuptools = "import setuptools" + $setup = "setup(" + + $not_setup_example = ">>> setup(" + $not_setup_todict = "setup(**config.todict()" + $not_import_quoted = "\"from setuptools import setup" + $not_setup_quoted = "\"setup(name=" + $not_distutils = "from distutils.errors import" + + condition: + filesize < 128KB and $setup and any of ($i*) and none of ($not*) +} rule setuptools_random: critical { meta: @@ -12,7 +27,7 @@ rule setuptools_random: critical { $not_easy_install = "pid = random.randint(0, sys.maxsize)" condition: - global_python_setup and $ref and none of ($not*) + random_behavior_pythonSetup and $ref and none of ($not*) } rule java_random: low { diff --git a/rules/anti-static/elf/entropy.yara b/rules/anti-static/elf/entropy.yara index c81189ea4..885270703 100644 --- a/rules/anti-static/elf/entropy.yara +++ b/rules/anti-static/elf/entropy.yara @@ -1,6 +1,14 @@ import "math" -include "rules/global/global.yara" +private rule normal_elf { + condition: + filesize < 64MB and uint32(0) == 1179403647 +} + +private rule small_elf { + condition: + filesize < 400KB and uint32(0) == 1179403647 +} rule higher_elf_entropy_68: medium { meta: @@ -8,7 +16,7 @@ rule higher_elf_entropy_68: medium { filetypes = "elf" condition: - global_normal_elf and math.entropy(1, filesize) >= 6.95 + normal_elf and math.entropy(1, filesize) >= 6.95 } rule normal_elf_high_entropy_7_4: high { @@ -21,7 +29,7 @@ rule normal_elf_high_entropy_7_4: high { $not_bazel = "BazelLogHandler" condition: - filesize < 30MB and global_normal_elf and math.entropy(1, filesize) >= 7.4 and none of ($not*) + filesize < 30MB and normal_elf and math.entropy(1, filesize) >= 7.4 and none of ($not*) } rule normal_elf_high_entropy_footer_7_4: high { @@ -30,7 +38,7 @@ rule normal_elf_high_entropy_footer_7_4: high { filetypes = "elf" condition: - global_normal_elf and math.entropy(filesize - 8192, filesize) >= 7.4 + normal_elf and math.entropy(filesize - 8192, filesize) >= 7.4 } rule normal_elf_high_entropy_footer_7_4_rc4: high { @@ -43,5 +51,5 @@ rule normal_elf_high_entropy_footer_7_4_rc4: high { $cmp_r_x_256 = { 48 81 f? 00 01 00 00 } // cmp {rbx, rcx, …}, 256 condition: - filesize < 25MB and global_normal_elf and math.entropy(filesize - 8192, filesize) >= 7.4 and any of them + filesize < 25MB and normal_elf and math.entropy(filesize - 8192, filesize) >= 7.4 and any of them } diff --git a/rules/anti-static/macho/entropy.yara b/rules/anti-static/macho/entropy.yara index e8e9589f7..6a821c505 100644 --- a/rules/anti-static/macho/entropy.yara +++ b/rules/anti-static/macho/entropy.yara @@ -1,6 +1,9 @@ import "math" -include "rules/global/global.yara" +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 higher_entropy_6_9: medium { meta: @@ -8,7 +11,7 @@ rule higher_entropy_6_9: medium { filetypes = "macho" condition: - global_small_macho and math.entropy(1, filesize) >= 6.9 + smaller_macho and math.entropy(1, filesize) >= 6.9 } rule high_entropy_7_2: high { @@ -21,5 +24,5 @@ rule high_entropy_7_2: high { $bin_java = "bin/java" condition: - global_small_macho and math.entropy(1, filesize) >= 7.2 and not $bin_java + smaller_macho and math.entropy(1, filesize) >= 7.2 and not $bin_java } diff --git a/rules/anti-static/macho/footer.yara b/rules/anti-static/macho/footer.yara index b806d761f..5ee0acac5 100644 --- a/rules/anti-static/macho/footer.yara +++ b/rules/anti-static/macho/footer.yara @@ -1,6 +1,9 @@ import "math" -include "rules/global/global.yara" +private rule anti_static_macho { + condition: + (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 high_entropy_trailer: high { meta: @@ -12,5 +15,5 @@ rule high_entropy_trailer: high { $page_zero = "_PAGEZERO" condition: - filesize < 10MB and global_macho and $page_zero and math.entropy(filesize - 1024, filesize - 1) >= 4 + filesize < 10MB and anti_static_macho and $page_zero and math.entropy(filesize - 1024, filesize - 1) >= 4 } diff --git a/rules/anti-static/packer/aes.yara b/rules/anti-static/packer/aes.yara index 81445e1d5..9f6c446d3 100644 --- a/rules/anti-static/packer/aes.yara +++ b/rules/anti-static/packer/aes.yara @@ -1,6 +1,10 @@ import "math" -include "rules/global/global.yara" +private rule smallBinary { + condition: + // matches ELF or machO binary + filesize > 1MB and filesize < 8MB 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) +} rule go_aes: high { meta: @@ -13,5 +17,5 @@ rule go_aes: high { $decrypt = "NewCFBDecrypter" condition: - global_small_binary and math.entropy(1, filesize) >= 7 and all of them + smallBinary and math.entropy(1, filesize) >= 7 and all of them } diff --git a/rules/anti-static/unmarshal/marshal.yara b/rules/anti-static/unmarshal/marshal.yara index 619840366..e2da33b3d 100644 --- a/rules/anti-static/unmarshal/marshal.yara +++ b/rules/anti-static/unmarshal/marshal.yara @@ -1,6 +1,15 @@ import "math" -include "rules/global/global.yara" +private rule pySetup { + strings: + $i_distutils = "from distutils.core import setup" + $i_setuptools = "setuptools" + $setup = "setup(" + $not_setuptools = "setuptools.command" + + condition: + filesize < 2097152 and $setup and any of ($i*) and none of ($not*) +} rule unmarshal_py_marshal: medium { meta: @@ -20,5 +29,5 @@ rule setuptools_py_marshal: suspicious { filetypes = "py" condition: - global_python_setup and unmarshal_py_marshal + pySetup and unmarshal_py_marshal } diff --git a/rules/c2/addr/ip.yara b/rules/c2/addr/ip.yara index 75baa9bd8..c51da388d 100644 --- a/rules/c2/addr/ip.yara +++ b/rules/c2/addr/ip.yara @@ -1,5 +1,3 @@ -include "rules/global/global.yara" - rule hardcoded_ip: medium { meta: description = "hardcoded IP address" @@ -21,6 +19,11 @@ rule hardcoded_ip: medium { filesize < 200MB and 1 of ($sus_ip*) and none of ($not*) } +private rule ip_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" @@ -45,7 +48,7 @@ rule bin_hardcoded_ip: high { $not_2345 = "23.45.67.89" condition: - filesize < 12MB and global_elf_or_macho and 1 of ($sus_ip*) and none of ($not*) + filesize < 12MB and ip_elf_or_macho and 1 of ($sus_ip*) and none of ($not*) } rule http_hardcoded_ip: high exfil { diff --git a/rules/c2/addr/url.yara b/rules/c2/addr/url.yara index a0db1d369..963e89ffc 100644 --- a/rules/c2/addr/url.yara +++ b/rules/c2/addr/url.yara @@ -1,6 +1,9 @@ import "math" -include "rules/global/global.yara" +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 unusual_nodename: medium { meta: @@ -82,7 +85,7 @@ rule binary_with_url: low { $ref = /https*:\/\/[\w\.\/]{8,160}[\/\w\=\&]{0,32}/ condition: - filesize < 150MB and global_elf_or_macho and $ref + filesize < 150MB and elf_or_macho and $ref } rule binary_url_with_question: high { @@ -99,7 +102,7 @@ rule binary_url_with_question: high { $not_mesibo = "https://api.mesibo.com/api.php?" condition: - filesize < 150MB and global_elf_or_macho and $ref and none of ($not*) + filesize < 150MB and elf_or_macho and $ref and none of ($not*) } rule script_url_with_question: high { diff --git a/rules/c2/tool_transfer/download.yara b/rules/c2/tool_transfer/download.yara index ada9603c9..13acfe6a4 100644 --- a/rules/c2/tool_transfer/download.yara +++ b/rules/c2/tool_transfer/download.yara @@ -1,5 +1,3 @@ -include "rules/global/global.yara" - rule download_sites: high { meta: ref = "https://github.com/ditekshen/detection/blob/e6579590779f62cbe7f5e14b5be7d77b2280f516/yara/indicator_high.yar#L1001" @@ -115,6 +113,12 @@ rule http_archive_url: medium { any of ($ref*) and none of ($not*) } +private rule smallerBinary { + condition: + // matches ELF or machO binary + 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) +} + rule http_archive_url_higher: high { meta: description = "accesses hardcoded archive file endpoint" @@ -125,5 +129,5 @@ rule http_archive_url_higher: high { $not_foo_bar = "http://foo/bar.tar" condition: - global_small_binary and any of ($ref*) and none of ($not*) + smallerBinary and any of ($ref*) and none of ($not*) } diff --git a/rules/c2/tool_transfer/macos.yara b/rules/c2/tool_transfer/macos.yara index 70c70683d..4c82c9b22 100644 --- a/rules/c2/tool_transfer/macos.yara +++ b/rules/c2/tool_transfer/macos.yara @@ -1,4 +1,12 @@ -include "rules/global/global.yara" +private rule tool_transfer_macho { + strings: + $not_jar = "META-INF/" + $not_dwarf = "_DWARF" + $not_kext = "_.SYMDEF SORTED" + + condition: + (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) and none of ($not*) +} rule macos_chflags_hidden: critical { meta: @@ -30,5 +38,5 @@ rule cocoa_bundle_dropper: critical { $platform = "isPlatformOrVariantPlatformVersionAtLeast" fullword condition: - global_specific_macho and $shared and 5 of them + tool_transfer_macho and $shared and 5 of them } diff --git a/rules/c2/tool_transfer/python.yara b/rules/c2/tool_transfer/python.yara index d5a59b4c6..386c0fb0d 100644 --- a/rules/c2/tool_transfer/python.yara +++ b/rules/c2/tool_transfer/python.yara @@ -1,4 +1,36 @@ -include "rules/global/global.yara" +private rule py_fetcher: medium { + meta: + description = "fetches content" + filetypes = "py" + + strings: + $http_requests = "requests.get" fullword + $http_requests_post = "requests.post" fullword + $http_urllib = "urllib.request" fullword + $http_urlopen = "urlopen" fullword + $git_git = /git.Git\(.{0,64}/ + $http_curl = "curl" fullword + $http_wget = "wget" fullword + + condition: + any of them +} + +private rule py_runner { + meta: + description = "runs programs" + filetypes = "py" + + strings: + $os_system = /os.system\([\"\'\w\ \-\)\/]{0,64}/ + $os_startfile = /os.startfile\([\"\'\w\ \-\)\/]{0,64}/ + $os_popen = /os.spopen\([\"\'\w\ \-\)\/]{0,64}/ + $subprocess = /subprocess.\w{1,32}\([\"\'\/\w\ \-\)]{0,64}/ + $system = /system\([\"\'\w\ \-\)\/]{0,64}/ + + condition: + any of them +} rule py_dropper: medium { meta: @@ -10,7 +42,7 @@ rule py_dropper: medium { $write = "write(" condition: - filesize < 16384 and $open and $write and global_py_fetcher and global_py_runner + filesize < 16384 and $open and $write and py_fetcher and py_runner } rule py_arch_dropper: medium { @@ -33,7 +65,7 @@ rule py_arch_dropper: medium { $exec_run = "run" fullword condition: - filesize < 1MB and any of ($os*) and any of ($arch*) and any of ($download*) and (any of ($exec*) or global_py_runner) + filesize < 1MB and any of ($os*) and any of ($arch*) and any of ($download*) and (any of ($exec*) or py_runner) } rule py_dropper_obfuscated: high { @@ -48,7 +80,7 @@ rule py_dropper_obfuscated: high { $ob_codecs = "codecs.decode" condition: - filesize < 16000 and $open and $write and any of ($ob_*) and global_py_fetcher and global_py_runner + filesize < 16000 and $open and $write and any of ($ob_*) and py_fetcher and py_runner } rule py_dropper_tiny: high { @@ -61,7 +93,7 @@ rule py_dropper_tiny: high { $write = "write(" condition: - filesize < 900 and $open and $write and global_py_fetcher and global_py_runner + filesize < 900 and $open and $write and py_fetcher and py_runner } rule py_dropper_chmod: high { @@ -77,7 +109,29 @@ rule py_dropper_chmod: high { $val_770 = "770" condition: - filesize < 1MB and global_py_fetcher and global_py_runner and $chmod and any of ($val*) + filesize < 1MB and py_fetcher and py_runner and $chmod and any of ($val*) +} + +private rule tool_transfer_pythonSetup { + strings: + $if_distutils = /from distutils.core import .{0,32}setup/ + $if_setuptools = /from setuptools import .{0,32}setup/ + $i_setuptools = "import setuptools" + $setup = "setup(" + + $not_setup_example = ">>> setup(" + $not_setup_todict = "setup(**config.todict()" + $not_import_quoted = "\"from setuptools import setup" + $not_setup_quoted = "\"setup(name=" + $not_distutils = "from distutils.errors import" + $not_dir = "dist-packages/setuptools" + $not_fetch = "fetch_distribution" + $not_hopper1 = "PACKAGE_NAME = \"flashattn-hopper\"" + $not_hopper2 = "check_if_cuda_home_none(\"--fahopper\")" + $not_hopper3 = "name=\"flashattn_hopper_cuda\"," + + condition: + filesize < 128KB and $setup and any of ($i*) and none of ($not*) } rule setuptools_fetcher: suspicious { @@ -86,7 +140,7 @@ rule setuptools_fetcher: suspicious { filetypes = "py" condition: - global_python_setup and global_py_fetcher + tool_transfer_pythonSetup and py_fetcher } rule setuptools_fetch_run: critical { @@ -100,7 +154,7 @@ rule setuptools_fetch_run: critical { $not_hopper3 = "name=\"flashattn_hopper_cuda\"," condition: - setuptools_fetcher and global_py_runner and none of ($not*) + setuptools_fetcher and py_runner and none of ($not*) } rule setuptools_dropper: critical { @@ -109,7 +163,7 @@ rule setuptools_dropper: critical { filetypes = "py" condition: - global_python_setup and py_dropper + tool_transfer_pythonSetup and py_dropper } rule dropper_imports: high { @@ -140,6 +194,6 @@ rule oneline: high { $urlopen = /\.write\(.{0,8}urlopen\("http.{0,128}\"\).read\(\)/ condition: - filesize < 512KB and any of them and global_py_fetcher and global_py_runner + filesize < 512KB and any of them and py_fetcher and py_runner } diff --git a/rules/data/builtin/multiple.yara b/rules/data/builtin/multiple.yara index ebe682b13..e4567dad1 100644 --- a/rules/data/builtin/multiple.yara +++ b/rules/data/builtin/multiple.yara @@ -1,6 +1,31 @@ import "elf" -include "rules/global/global.yara" +private rule _bundled_openssl: medium { + meta: + description = "includes bundled copy of OpenSSL" + + strings: + $ref = "OpenSSL/" + $aes_part = "AES part of OpenSSL" + $montgomery = "Montgomery Multiplication for x86_64, CRYPTOGAMS" + $rc4 = "RC4 for x86_64, CRYPTOGAMS" + + condition: + filesize > 1024 and filesize < 150MB and elf.type == elf.ET_EXEC and uint32(0) == 1179403647 and any of them +} + +private rule _bundled_glibc: medium { + meta: + description = "includes bundled copy of glibc" + + strings: + $glibc_private = "GLIBC_PRIVATE" + $glibc_tunables = "GLIBC_TUNABLES" + $setup_vdso = "setup_vdso" + + condition: + filesize > 1024 and filesize < 25MB and elf.type == elf.ET_EXEC and uint32(0) == 1179403647 and all of them +} rule elf_with_bundled_glibc_and_openssl: high { meta: @@ -8,5 +33,5 @@ rule elf_with_bundled_glibc_and_openssl: high { filetypes = "elf" condition: - global_bundled_openssl and global_bundled_glibc + _bundled_openssl and _bundled_glibc } diff --git a/rules/discover/multiple.yara b/rules/discover/multiple.yara index 3389b4ebd..6862fddac 100644 --- a/rules/discover/multiple.yara +++ b/rules/discover/multiple.yara @@ -1,5 +1,3 @@ -include "rules/global/global.yara" - rule sys_net_recon: medium { meta: description = "collects system and network information" @@ -64,6 +62,35 @@ rule user_sys_net_disk_recon: high { 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" + $base64 = "base64" + $codecs = "codecs.decode" + $x_decode = /\w{0,16}XorDecode[\w]{0,32}/ + $x_encode = /\w{0,16}XorEncode[\w]{0,32}/ + $x_file = /\w{0,16}XorFile[\w]{0,32}/ + $x_decode_ = /\w{0,16}xor_decode[\w]{0,32}/ + $x_encode_ = /\w{0,16}xor_encode[\w]{0,32}/ + $x_file_ = /\w{0,16}xor_file[\w]{0,32}/ + + condition: + filesize < 512KB and any of them +} + +private rule discover_exfil { + strings: + $f_app_json = "application/json" + $f_post = "requests.post" + $f_nsurl = "NSURLRequest" + $f_curl = /curl.{0,32}-X POST/ + + $not_requests_utils = "requests.utils" + + condition: + filesize < 512KB and any of ($f*) and none of ($not*) +} + rule sys_net_recon_exfil: high { meta: description = "may exfiltrate collected system and network information" @@ -73,5 +100,5 @@ rule sys_net_recon_exfil: high { $not_cloudinit = "cloudinit" fullword condition: - sys_net_recon and global_obfuscate and global_exfil and none of ($not*) + sys_net_recon and discover_obfuscate and discover_exfil and none of ($not*) } diff --git a/rules/discover/user/username-get.yara b/rules/discover/user/username-get.yara index cc0ed8f3d..8e0dfacc9 100644 --- a/rules/discover/user/username-get.yara +++ b/rules/discover/user/username-get.yara @@ -1,5 +1,3 @@ -include "rules/global/global.yara" - rule getlogin { meta: syscall = "getlogin" @@ -29,6 +27,23 @@ rule whoami: medium { any of them } +private rule user_pythonSetup { + strings: + $if_distutils = /from distutils.core import .{0,32}setup/ + $if_setuptools = /from setuptools import .{0,32}setup/ + $i_setuptools = "import setuptools" + $setup = "setup(" + + $not_setup_example = ">>> setup(" + $not_setup_todict = "setup(**config.todict()" + $not_import_quoted = "\"from setuptools import setup" + $not_setup_quoted = "\"setup(name=" + $not_distutils = "from distutils.errors import" + + condition: + filesize < 128KB and $setup and any of ($i*) and none of ($not*) +} + rule pysetup_gets_login: high { meta: description = "Python library installer gets login information" @@ -40,5 +55,5 @@ rule pysetup_gets_login: high { $ref3 = "whoami" fullword condition: - global_python_setup and any of them + user_pythonSetup and any of them } diff --git a/rules/evasion/indicator_blocking/hidden_window.yara b/rules/evasion/indicator_blocking/hidden_window.yara index 4114e2cb8..3ed227b4d 100644 --- a/rules/evasion/indicator_blocking/hidden_window.yara +++ b/rules/evasion/indicator_blocking/hidden_window.yara @@ -1,5 +1,3 @@ -include "rules/global/global.yara" - rule subprocess_CREATE_NO_WINDOW: medium { meta: description = "runs commands, hides windows" @@ -13,6 +11,23 @@ rule subprocess_CREATE_NO_WINDOW: medium { filesize < 32KB and all of them } +private rule hidden_window_pythonSetup { + strings: + $if_distutils = /from distutils.core import .{0,32}setup/ + $if_setuptools = /from setuptools import .{0,32}setup/ + $i_setuptools = "import setuptools" + $setup = "setup(" + + $not_setup_example = ">>> setup(" + $not_setup_todict = "setup(**config.todict()" + $not_import_quoted = "\"from setuptools import setup" + $not_setup_quoted = "\"setup(name=" + $not_distutils = "from distutils.errors import" + + condition: + filesize < 128KB and $setup and any of ($i*) in (0..1024) and none of ($not*) +} + rule subprocess_CREATE_NO_WINDOW_setuptools: high { meta: description = "runs commands, hides windows" @@ -23,7 +38,7 @@ rule subprocess_CREATE_NO_WINDOW_setuptools: high { $no_window = "CREATE_NO_WINDOW" condition: - filesize < 32KB and global_python_setup and all of them + filesize < 32KB and hidden_window_pythonSetup and all of them } rule subprocess_CREATE_NO_WINDOW_high: high { diff --git a/rules/evasion/indicator_blocking/mask_exceptions.yara b/rules/evasion/indicator_blocking/mask_exceptions.yara index d9ad8f2c8..6f447a1fe 100644 --- a/rules/evasion/indicator_blocking/mask_exceptions.yara +++ b/rules/evasion/indicator_blocking/mask_exceptions.yara @@ -1,6 +1,20 @@ import "math" -include "rules/global/global.yara" +private rule indicator_blocking_pythonSetup { + strings: + $if_distutils = /from distutils.core import .{0,32}setup/ + $if_setuptools = /from setuptools import .{0,32}setup/ + $i_setuptools = "import setuptools" + $setup = "setup(" + $not_setup_example = ">>> setup(" + $not_setup_todict = "setup(**config.todict()" + $not_import_quoted = "\"from setuptools import setup" + $not_setup_quoted = "\"setup(name=" + $not_distutils = "from distutils.errors import" + + condition: + filesize < 131072 and $setup and any of ($i*) and none of ($not*) +} rule py_no_fail: medium { meta: @@ -21,7 +35,7 @@ rule setuptools_no_fail: suspicious { filetypes = "py" condition: - global_python_setup and py_no_fail + indicator_blocking_pythonSetup and py_no_fail } rule php_disable_errors: medium { diff --git a/rules/evasion/logging/wipe.yara b/rules/evasion/logging/wipe.yara index 0ca99de82..cd2afb756 100644 --- a/rules/evasion/logging/wipe.yara +++ b/rules/evasion/logging/wipe.yara @@ -1,4 +1,21 @@ -include "rules/global/global.yara" +private rule sensitive_log_files { + strings: + $wtmp = "/var/log/wtmp" + $secure = "/var/log/secure" + $cron = "/var/log/cron" + $iptables = "/var/log/iptables.log" + $auth = "/var/log/auth.log" + $cron_log = "/var/log/cron.log" + $httpd = "/var/log/httpd" + $syslog = "/var/log/syslog" + $btmp = "/var/log/btmp" + $lastlog = "/var/log/lastlog" + $run_log = "/run/log/" + $mail_log = "/var/spool/mail/root" + + condition: + filesize < 16KB and 2 of them +} rule echo_log_wiper: critical { meta: @@ -9,7 +26,7 @@ rule echo_log_wiper: critical { $var_log = /echo.{0,4}\> {0,2}\/var\/log\/\w{0,8}/ condition: - filesize < 16KB and global_sensitive_log_files and any of them + filesize < 16KB and sensitive_log_files and any of them } rule log_remover: critical { @@ -21,5 +38,5 @@ rule log_remover: critical { $var_log = /rm {1,2}-{0,4}\/var\/log\/\w{0,8}/ condition: - filesize < 16KB and global_sensitive_log_files and any of them + filesize < 16KB and sensitive_log_files and any of them } diff --git a/rules/evasion/net/hide_ports.yara b/rules/evasion/net/hide_ports.yara index 8e74e2101..5dc0c9a22 100644 --- a/rules/evasion/net/hide_ports.yara +++ b/rules/evasion/net/hide_ports.yara @@ -1,4 +1,12 @@ -include "rules/global/global.yara" +private rule net_macho { + condition: + 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 +} + +private rule net_elf { + condition: + uint32(0) == 1179403647 +} rule hides_ports: high { meta: @@ -14,5 +22,5 @@ rule hides_ports: high { $hidden_port = "hidden_port" condition: - filesize < 2MB and (global_elf_or_macho) and any of ($bin*) and any of ($hid*) + filesize < 2MB and (net_elf or net_macho) and any of ($bin*) and any of ($hid*) } diff --git a/rules/evasion/self_deletion/run_and_delete.yara b/rules/evasion/self_deletion/run_and_delete.yara index 904ff6be5..6557dd681 100644 --- a/rules/evasion/self_deletion/run_and_delete.yara +++ b/rules/evasion/self_deletion/run_and_delete.yara @@ -1,5 +1,3 @@ -include "rules/global/global.yara" - rule tiny_copy_run_delete: critical { meta: description = "copy executable, run, and delete" @@ -38,6 +36,24 @@ rule fetch_run_sleep_delete: critical { filesize < 1KB and $url and $sleep and $rm and any of ($path*) and any of ($run*) } +private rule run_delete_py_fetcher: medium { + meta: + description = "fetches content" + filetypes = "py" + + strings: + $http_requests = "requests.get" fullword + $http_requests_post = "requests.post" fullword + $http_urllib = "urllib.request" fullword + $http_urlopen = "urlopen" fullword + $git_git = /git.Git\(.{0,64}/ + $http_curl = "curl" fullword + $http_wget = "wget" fullword + + condition: + any of them +} + rule python_setsid_remove: high { meta: description = "fetch, run in background, delete" @@ -49,7 +65,7 @@ rule python_setsid_remove: high { $remove = "os.remove(" condition: - filesize < 1MB and all of them and global_py_fetcher and @remove > @subprocess and @remove - @subprocess < 256 + filesize < 1MB and all of them and run_delete_py_fetcher and @remove > @subprocess and @remove - @subprocess < 256 } rule run_sleep_delete: critical { diff --git a/rules/exec/program/opaque.yara b/rules/exec/program/opaque.yara index 2cef35225..f9dfd28ef 100644 --- a/rules/exec/program/opaque.yara +++ b/rules/exec/program/opaque.yara @@ -1,6 +1,12 @@ -import "math" +private rule program_small_macho { + strings: + $stub_helper = "__stub_helper" + + condition: + filesize < 1MB and (uint32(0) == 4277009102 or uint32(0) == 3472551422 or uint32(0) == 4277009103 or uint32(0) == 3489328638 or uint32(0) == 3405691582 or uint32(0) == 3199925962) and $stub_helper +} -include "rules/global/global.yara" +import "math" rule macho_opaque_binary: high { meta: @@ -18,7 +24,7 @@ rule macho_opaque_binary: high { $not_java = "java/lang" condition: - global_small_macho and #word_with_spaces < 8 and #libc_call < 6 and all of ($f*) and none of ($not*) + program_small_macho and #word_with_spaces < 8 and #libc_call < 6 and all of ($f*) and none of ($not*) } rule macho_opaque_binary_long_str: high { @@ -39,7 +45,7 @@ rule macho_opaque_binary_long_str: high { $long_low_str = /\x00[a-z0-9]{3000}/ condition: - global_stub_macho and #word_with_spaces < 10 and #libc_call < 15 and all of ($f*) and any of ($long*) and none of ($not*) + program_small_macho and #word_with_spaces < 10 and #libc_call < 15 and all of ($f*) and any of ($long*) and none of ($not*) } rule decoded_or_encoded_cmd: medium { diff --git a/rules/exec/shell/relative-semicolon.yara b/rules/exec/shell/relative-semicolon.yara index 3698afc75..e6682ccb6 100644 --- a/rules/exec/shell/relative-semicolon.yara +++ b/rules/exec/shell/relative-semicolon.yara @@ -1,4 +1,10 @@ -include "rules/global/global.yara" +private rule local_cd { + strings: + $cd = /cd [a-z]{4,12}; \.\// + + condition: + any of them +} rule semicolon_relative_path_cd: medium { meta: @@ -19,5 +25,5 @@ rule semicolon_relative_path_high: high { $semi_relative = /[\/\w]{3,};[ +]{0,8}\.\/\.{0,8}\w{3,}/ condition: - any of them and not global_local_cd + any of them and not local_cd } diff --git a/rules/exfil/discord.yara b/rules/exfil/discord.yara index 0a64b7554..6c15d1f9d 100644 --- a/rules/exfil/discord.yara +++ b/rules/exfil/discord.yara @@ -1,5 +1,3 @@ -include "rules/global/global.yara" - rule discord_bot: high { meta: description = "Uses the Discord webhooks API" @@ -28,10 +26,41 @@ rule discord_bot: high { any of them and none of ($not*) } +private rule iplookup_website_value_copy: high { + meta: + description = "public service to discover external IP address" + + strings: + $ipify = "ipify.org" + $wtfismyip = "wtfismyip" + $iplogger = "iplogger.org" + $getjsonip = "getjsonip" + $ipconfig_me = "ifconfig.me" + $icanhazip = "icanhazip" + $ident_me = "ident.me" fullword + $showip_net = "showip.net" fullword + $ifconfig_io = "ifconfig.io" fullword + $ifconfig_co = "ifconfig.co" fullword + $ipinfo = "ipinfo.io" + $ipify_b = "ipify.org" base64 + $wtfismyip_b = "wtfismyip" base64 + $iplogger_b = "iplogger.org" base64 + $getjsonip_b = "getjsonip" base64 + $ipinfo_b = "ipinfo.io" base64 + $ipify_x = "ipify.org" xor(1-255) + $wtfismyip_x = "wtfismyip" xor(1-255) + $iplogger_x = "iplogger.org" xor(1-255) + $getjsonip_x = "getjsonip" xor(1-255) + $ipinfo_x = "ipinfo.io" xor(1-255) + + condition: + any of them +} + rule discord_exfil: critical { meta: description = "exfiltrates data via discord webhook" condition: - filesize < 100MB and discord_bot and global_iplookup_website + filesize < 100MB and discord_bot and iplookup_website_value_copy } diff --git a/rules/exfil/nodejs.yara b/rules/exfil/nodejs.yara index 8bed2717a..7c3d23044 100644 --- a/rules/exfil/nodejs.yara +++ b/rules/exfil/nodejs.yara @@ -1,7 +1,5 @@ import "math" -include "rules/global/global.yara" - rule nodejs_sysinfoexfil: high { meta: description = "may gather and exfiltrate system information" @@ -132,6 +130,31 @@ rule post_hardcoded_hardcoded_host_os: high { filesize < 256KB and any of ($ref*) and $post and ((math.abs(@ref - @post) <= 128) or ((math.abs(@ref2 - @post) <= 128))) and $os } +private rule nodejs_iplookup_website: high { + meta: + description = "public service to discover external IP address" + + strings: + $ipify = /ipify\.org{0,1}/ + $wtfismyip = "wtfismyip" + $iplogger = "iplogger.org" + $getjsonip = "getjsonip" + $ipconfig_me = "ifconfig.me" + $icanhazip = "icanhazip" + $grabify = "grabify.link" + $ident_me = "ident.me" fullword + $showip_net = "showip.net" fullword + $ifconfig_io = "ifconfig.io" fullword + $ifconfig_co = "ifconfig.co" fullword + $ipinfo = "ipinfo.io" + $check_ip = "checkip.amazonaws.com" + + $not_pypi_index = "testpack-id-lb001" + + condition: + filesize < 250MB and any of them and none of ($not*) +} + rule get_hardcoded_hardcoded_host_os: critical { meta: description = "leaks host information to a hardcoded host" @@ -145,5 +168,5 @@ rule get_hardcoded_hardcoded_host_os: critical { $i_os_userinfo = "os.userInfo" condition: - filesize < 256KB and $ref and (any of ($i*) or global_iplookup_website) + filesize < 256KB and $ref and (any of ($i*) or nodejs_iplookup_website) } diff --git a/rules/exfil/npm.yara b/rules/exfil/npm.yara index 5e6eb468e..504ddf422 100644 --- a/rules/exfil/npm.yara +++ b/rules/exfil/npm.yara @@ -1,4 +1,17 @@ -include "rules/global/global.yara" +private rule package_scripts { + strings: + $npm_name = /"name":/ + $npm_version = /"version":/ + $npm_description = /"description":/ + $npm_lint = /"lint":/ + $npm_test = /"test":/ + $npm_postversion = /"postversion":/ + $npm_postinstall = /"postinstall":/ + $scripts = /"scripts":/ + + condition: + filesize < 32KB and 3 of ($npm*) and $scripts +} rule npm_fetcher: high { meta: @@ -9,7 +22,7 @@ rule npm_fetcher: high { $url = /https{0,1}:\/\/[\w][\w\.\/\-_\?=\@]{8,64}/ condition: - global_package_scripts and $fetch and $url + package_scripts and $fetch and $url } rule npm_dev_tcp: critical { @@ -20,7 +33,7 @@ rule npm_dev_tcp: critical { $dev_tcp = /\/dev\/tcp\/[\w\.\/]{0,32}/ condition: - global_package_scripts and $dev_tcp + package_scripts and $dev_tcp } rule npm_ping: critical { @@ -31,7 +44,7 @@ rule npm_ping: critical { $ping = /ping -\w [\w\-\. \$]{0,63}/ condition: - global_package_scripts and $ping + package_scripts and $ping } rule npm_sensitive_files: high { @@ -47,7 +60,7 @@ rule npm_sensitive_files: high { $ = "/etc/passwd" condition: - global_package_scripts and any of them + package_scripts and any of them } rule npm_recon_commands: high { @@ -59,5 +72,5 @@ rule npm_recon_commands: high { $ = "cat /etc/shadow" condition: - global_package_scripts and any of them + package_scripts and any of them } diff --git a/rules/exfil/oauth.yara b/rules/exfil/oauth.yara index c4320c588..ac5c1f723 100644 --- a/rules/exfil/oauth.yara +++ b/rules/exfil/oauth.yara @@ -1,4 +1,12 @@ -include "rules/global/global.yara" +private rule post_json { + strings: + $json = "application/json" + $POST = "POST" + $encode_stringify = "JSON.stringify" + + condition: + $json and $POST and any of ($encode*) +} rule possible_oauth_stealer: high { meta: @@ -21,7 +29,7 @@ rule possible_oauth_stealer: high { $o_microsoft5 = "code_challenge_method" condition: - filesize < 10MB and global_post_json and 5 of ($o*) + filesize < 10MB and post_json and 5 of ($o*) } rule oauth_stealer: critical { diff --git a/rules/fs/path/applications.yara b/rules/fs/path/applications.yara index 89a769c40..e9ef9ebb4 100644 --- a/rules/fs/path/applications.yara +++ b/rules/fs/path/applications.yara @@ -1,5 +1,3 @@ -include "rules/global/global.yara" - rule app_path: medium { meta: description = "references hardcoded application path" @@ -11,6 +9,16 @@ rule app_path: medium { any of them } +private rule applicatons_macho { + strings: + $not_jar = "META-INF/" + $not_dwarf = "_DWARF" + $not_kext = "_.SYMDEF SORTED" + + condition: + (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) and none of ($not*) +} + rule macho_app_path: high { meta: description = "references hardcoded application path" @@ -20,7 +28,7 @@ rule macho_app_path: high { $ref = /\/Applications\/.{0,32}\.app\/Contents\/MacOS\/[\w \.\-]{0,32}/ condition: - global_specific_macho and any of them + applicatons_macho and any of them } rule mac_applications: medium { @@ -32,5 +40,5 @@ rule mac_applications: medium { $ref = "/Applications" fullword condition: - global_specific_macho and any of them + applicatons_macho and any of them } diff --git a/rules/global/global.yara b/rules/global/global.yara deleted file mode 100644 index ba4f26c3d..000000000 --- a/rules/global/global.yara +++ /dev/null @@ -1,320 +0,0 @@ -import "elf" - -private rule global_binary { - condition: - filesize < 40MB 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) -} - -private rule global_bundled_glibc { - meta: - description = "includes bundled copy of glibc" - filetypes = "elf,so" - - strings: - $glibc_private = "GLIBC_PRIVATE" - $glibc_tunables = "GLIBC_TUNABLES" - $setup_vdso = "setup_vdso" - - condition: - filesize > 1024 and filesize < 25MB and elf.type == elf.ET_EXEC and uint32(0) == 1179403647 and all of them -} - -private rule global_bundled_openssl { - meta: - description = "includes bundled copy of OpenSSL" - filetypes = "elf,so" - - strings: - $ref = "OpenSSL/" - $aes_part = "AES part of OpenSSL" - $montgomery = "Montgomery Multiplication for x86_64, CRYPTOGAMS" - $rc4 = "RC4 for x86_64, CRYPTOGAMS" - - condition: - filesize > 1024 and filesize < 150MB and elf.type == elf.ET_EXEC and uint32(0) == 1179403647 and any of them -} - -private rule global_container_managers { - strings: - $containerd = "github.com/containerd/containerd" - $systemd = "SYSTEMD_PROC_CMDLINE" - $snapd = "snapcore/snapd" - - condition: - any of them -} - -private rule global_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) -} - -private rule global_exfil { - strings: - $f_app_json = "application/json" - $f_post = "requests.post" - $f_nsurl = "NSURLRequest" - $f_curl = /curl.{0,32}-X POST/ - - $not_requests_utils = "requests.utils" - - condition: - filesize < 512KB and any of ($f*) and none of ($not*) -} - -private rule global_iplookup_website { - meta: - description = "public service to discover external IP address" - - strings: - $ipify = "ipify.org" - $wtfismyip = "wtfismyip" - $iplogger = "iplogger.org" - $getjsonip = "getjsonip" - $ipconfig_me = "ifconfig.me" - $icanhazip = "icanhazip" - $ident_me = "ident.me" fullword - $showip_net = "showip.net" fullword - $ifconfig_io = "ifconfig.io" fullword - $ifconfig_co = "ifconfig.co" fullword - $ipinfo = "ipinfo.io" - $ipify_b = "ipify.org" base64 - $wtfismyip_b = "wtfismyip" base64 - $iplogger_b = "iplogger.org" base64 - $getjsonip_b = "getjsonip" base64 - $ipinfo_b = "ipinfo.io" base64 - $ipify_x = "ipify.org" xor(1-255) - $wtfismyip_x = "wtfismyip" xor(1-255) - $iplogger_x = "iplogger.org" xor(1-255) - $getjsonip_x = "getjsonip" xor(1-255) - $ipinfo_x = "ipinfo.io" xor(1-255) - - $not_pypi_index = "testpack-id-lb001" - - condition: - filesize < 250MB and any of them and none of ($not*) -} - -private rule global_legal_license { - strings: - $ = "using, exploiting or modifying the Software" - $ = "exploit the Information commercially" - $ = "otherwise exploited by anyone for any purpose" - - condition: - any of them -} - -private rule global_local_cd { - strings: - $cd = /cd [a-z]{4,12}; \.\// - - condition: - any of them -} - -private rule global_macho { - condition: - (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) -} - -private rule global_normal_elf { - condition: - filesize < 64MB and uint32(0) == 1179403647 -} - -private rule global_obfuscate { - strings: - $b64decode = "b64decode" - $base64 = "base64" - $codecs = "codecs.decode" - $x_decode = /\w{0,16}XorDecode[\w]{0,32}/ - $x_encode = /\w{0,16}XorEncode[\w]{0,32}/ - $x_file = /\w{0,16}XorFile[\w]{0,32}/ - $x_decode_ = /\w{0,16}xor_decode[\w]{0,32}/ - $x_encode_ = /\w{0,16}xor_encode[\w]{0,32}/ - $x_file_ = /\w{0,16}xor_file[\w]{0,32}/ - - condition: - filesize < 512KB and any of them -} - -private rule global_package_scripts { - strings: - $npm_name = /"name":/ - $npm_version = /"version":/ - $npm_description = /"description":/ - $npm_lint = /"lint":/ - $npm_test = /"test":/ - $npm_postversion = /"postversion":/ - $npm_postinstall = /"postinstall":/ - $scripts = /"scripts":/ - - condition: - filesize < 32KB and 3 of ($npm*) and $scripts -} - -private rule global_post_json { - strings: - $json = "application/json" - $POST = "POST" - $encode_stringify = "JSON.stringify" - - condition: - $json and $POST and any of ($encode*) -} - -private rule global_py_fetcher { - meta: - description = "fetches content" - filetypes = "py" - - strings: - $http_requests = "requests.get" fullword - $http_requests_post = "requests.post" fullword - $http_urllib = "urllib.request" fullword - $http_urlopen = "urlopen" fullword - $git_git = /git.Git\(.{0,64}/ - $http_curl = "curl" fullword - $http_wget = "wget" fullword - - condition: - any of them -} - -private rule global_py_runner { - meta: - description = "runs programs" - filetypes = "py" - - strings: - $os_system = /os.system\([\"\'\w\ \-\)\/]{0,64}/ - $os_startfile = /os.startfile\([\"\'\w\ \-\)\/]{0,64}/ - $os_popen = /os.spopen\([\"\'\w\ \-\)\/]{0,64}/ - $subprocess = /subprocess.\w{1,32}\([\"\'\/\w\ \-\)]{0,64}/ - $system = /system\([\"\'\w\ \-\)\/]{0,64}/ - - condition: - any of them -} - -private rule global_python_setup { - meta: - filetypes = "py" - - strings: - $if_distutils = /from distutils.core import .{0,32}setup/ - $if_setuptools = /from setuptools import .{0,32}setup/ - $i_setuptools = "import setuptools" - $setup = "setup(" - - $not_setup_example = ">>> setup(" - $not_setup_todict = "setup(**config.todict()" - $not_import_quoted = "\"from setuptools import setup" - $not_setup_quoted = "\"setup(name=" - $not_distutils = "from distutils.errors import" - $not_numba = "https://github.com/numba/numba" - - $not_hopper1 = "PACKAGE_NAME = \"flashattn-hopper\"" - $not_hopper2 = "check_if_cuda_home_none(\"--fahopper\")" - $not_hopper3 = "name=\"flashattn_hopper_cuda\"," - - condition: - filesize < 131072 and $setup and any of ($i*) and none of ($not*) -} - -private rule global_sensitive_log_files { - strings: - $wtmp = "/var/log/wtmp" - $secure = "/var/log/secure" - $cron = "/var/log/cron" - $iptables = "/var/log/iptables.log" - $auth = "/var/log/auth.log" - $cron_log = "/var/log/cron.log" - $httpd = "/var/log/httpd" - $syslog = "/var/log/syslog" - $btmp = "/var/log/btmp" - $lastlog = "/var/log/lastlog" - $run_log = "/run/log/" - $mail_log = "/var/spool/mail/root" - - condition: - filesize < 16KB and 2 of them -} - -private rule global_small_binary { - 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) -} - -private rule global_small_elf { - condition: - filesize < 400KB and uint32(0) == 1179403647 -} - -private rule global_small_elf_or_macho { - condition: - filesize > 1MB and filesize < 8MB 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) -} - -private rule global_small_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) -} - -private rule global_specific_macho { - strings: - $not_jar = "META-INF/" - $not_dwarf = "_DWARF" - $not_kext = "_.SYMDEF SORTED" - - condition: - (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) - and none of ($not*) -} - -private rule global_stub_macho { - strings: - $stub_helper = "__stub_helper" - - condition: - filesize < 1MB and (uint32(0) == 4277009102 or uint32(0) == 3472551422 or uint32(0) == 4277009103 or uint32(0) == 3489328638 or uint32(0) == 3405691582 or uint32(0) == 3199925962) and $stub_helper -} - -private rule global_ufw_tool { - strings: - $not_route = "route-insert" - $not_statusverbose = "statusverbose" - $not_enables_the = "enables the" - $not_enable_the = "enable the" - $not_enable = "ufw enable" - - condition: - filesize < 256KB and any of them -} - -private rule global_word_list { - strings: - $scorpion = "scorpion" - $superman = "superman" - $porsche = "porsche" - $cardinal = "cardinal" - $wombat = "wombat" - - condition: - filesize < 100MB and 3 of them -} diff --git a/rules/impact/degrade/firewall.yara b/rules/impact/degrade/firewall.yara index efd10283d..f4c589a03 100644 --- a/rules/impact/degrade/firewall.yara +++ b/rules/impact/degrade/firewall.yara @@ -1,7 +1,5 @@ import "math" -include "rules/global/global.yara" - rule selinux_firewall: high linux { meta: filetypes = "elf,so" @@ -23,6 +21,18 @@ rule selinux_firewall: high linux { filesize < 1MB and $selinux and any of ($f*) and none of ($not*) } +private rule ufw_tool { + strings: + $not_route = "route-insert" + $not_statusverbose = "statusverbose" + $not_enables_the = "enables the" + $not_enable_the = "enable the" + $not_enable = "ufw enable" + + condition: + filesize < 256KB and any of them +} + rule ufw_disable_word: high { meta: description = "disables ufw firewall" @@ -31,7 +41,7 @@ rule ufw_disable_word: high { $ref = /ufw['", ]{1,4}disable/ fullword condition: - filesize < 256KB and $ref and not global_ufw_tool + filesize < 256KB and $ref and not ufw_tool } rule firewall_iptables_disable: high { diff --git a/rules/impact/exploit/breakout.yara b/rules/impact/exploit/breakout.yara index 201f58595..8566fd40c 100644 --- a/rules/impact/exploit/breakout.yara +++ b/rules/impact/exploit/breakout.yara @@ -1,4 +1,12 @@ -include "rules/global/global.yara" +private rule container_managers { + strings: + $containerd = "github.com/containerd/containerd" + $systemd = "SYSTEMD_PROC_CMDLINE" + $snapd = "snapcore/snapd" + + condition: + any of them +} rule probable_container_breakout: high linux { meta: @@ -22,7 +30,7 @@ rule probable_container_breakout: high linux { $not_systemd = "SYSTEMD_PROC_CMDLINE" condition: - filesize < 1MB and 4 of ($x*) and none of ($not*) and not global_container_managers + filesize < 1MB and 4 of ($x*) and none of ($not*) and not container_managers } rule possible_container_breakout: medium linux { @@ -45,5 +53,5 @@ rule possible_container_breakout: medium linux { $cgroup_procs = "cgroup.procs" condition: - filesize < 1MB and 3 of them and not global_container_managers + filesize < 1MB and 3 of them and not container_managers } diff --git a/rules/impact/exploit/exploit.yara b/rules/impact/exploit/exploit.yara index 12fc5d98c..7d86335e6 100644 --- a/rules/impact/exploit/exploit.yara +++ b/rules/impact/exploit/exploit.yara @@ -1,4 +1,12 @@ -include "rules/global/global.yara" +private rule legal_license { + strings: + $ = "using, exploiting or modifying the Software" + $ = "exploit the Information commercially" + $ = "otherwise exploited by anyone for any purpose" + + condition: + any of them +} rule exploitation: medium { meta: @@ -12,7 +20,7 @@ rule exploitation: medium { $not_ms_example = "Drive-by Compromise" condition: - any of ($ref*) and none of ($not*) and not global_legal_license + any of ($ref*) and none of ($not*) and not legal_license } rule install_exploit: high { @@ -26,7 +34,7 @@ rule install_exploit: high { $not_ms_example = "Drive-by Compromise" condition: - any of ($ref*) and none of ($not*) and not global_legal_license + any of ($ref*) and none of ($not*) and not legal_license } rule explot: high { @@ -49,7 +57,7 @@ rule Exploit: medium { $not_reduction = "Exploit reduction" condition: - any of ($ref*) and none of ($not*) and not global_legal_license + any of ($ref*) and none of ($not*) and not legal_license } rule exploiter: high { @@ -65,7 +73,7 @@ rule exploiter: high { $not_pypi_index = "testpack-id-lb001" condition: - any of ($ref*) and none of ($not*) and not global_legal_license + any of ($ref*) and none of ($not*) and not legal_license } rule exploit_attempt: high { diff --git a/rules/impact/remote_access/backdoor.yara b/rules/impact/remote_access/backdoor.yara index aae54b22f..1a765860c 100644 --- a/rules/impact/remote_access/backdoor.yara +++ b/rules/impact/remote_access/backdoor.yara @@ -1,4 +1,14 @@ -include "rules/global/global.yara" +private rule wordlist { + strings: + $scorpion = "scorpion" + $superman = "superman" + $porsche = "porsche" + $cardinal = "cardinal" + $wombat = "wombat" + + condition: + filesize < 100MB and 3 of them +} rule backdoor: medium { meta: @@ -12,7 +22,7 @@ rule backdoor: medium { $not_comment = "# backdoor:" condition: - filesize < 40MB and any of them and not global_word_list and none of ($not*) + filesize < 40MB and any of them and not wordlist and none of ($not*) } rule backdoor_shell: high { @@ -67,7 +77,7 @@ rule backdoor_caps: high { $ref2 = /[a-zA-Z\-_ \']{0,16}BACKDOOR[a-zA-Z\-_ ]{0,16}/ fullword condition: - filesize < 40MB and any of them and not global_word_list + filesize < 40MB and any of them and not wordlist } rule backdoor_leet: critical { @@ -78,7 +88,7 @@ rule backdoor_leet: critical { $ref4 = /[a-zA-Z\-_ \']{0,16}[bB][a4]ckd00r[a-zA-Z\-_ ]{0,16}/ condition: - filesize < 100MB and any of them and not global_word_list + filesize < 100MB and any of them and not wordlist } rule commands: high { @@ -94,6 +104,11 @@ rule commands: high { all of them } +private rule backdoor_small_macho { + condition: + filesize < 1MB 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 macho_backdoor_libc_signature: high { meta: description = "executes libc functions common to backdoors" @@ -135,7 +150,7 @@ rule macho_backdoor_libc_signature: high { $not_java = "java/lang" condition: - global_small_macho and #word_with_spaces < 10 and #libc_call < 74 and 95 % of ($f*) and none of ($not*) + backdoor_small_macho and #word_with_spaces < 10 and #libc_call < 74 and 95 % of ($f*) and none of ($not*) } rule minecraft_load_fetch_class_backdoor: critical { diff --git a/rules/impact/remote_access/py_setuptools.yara b/rules/impact/remote_access/py_setuptools.yara index 5078feb2c..dc7bfdfd7 100644 --- a/rules/impact/remote_access/py_setuptools.yara +++ b/rules/impact/remote_access/py_setuptools.yara @@ -1,6 +1,29 @@ import "math" -include "rules/global/global.yara" +private rule remote_access_pythonSetup { + meta: + filetypes = "py" + + strings: + $if_distutils = /from distutils.core import .{0,32}setup/ + $if_setuptools = /from setuptools import .{0,32}setup/ + $i_setuptools = "import setuptools" + $setup = "setup(" + + $not_setup_example = ">>> setup(" + $not_setup_todict = "setup(**config.todict()" + $not_import_quoted = "\"from setuptools import setup" + $not_setup_quoted = "\"setup(name=" + $not_distutils = "from distutils.errors import" + $not_numba = "https://github.com/numba/numba" + + $not_hopper1 = "PACKAGE_NAME = \"flashattn-hopper\"" + $not_hopper2 = "check_if_cuda_home_none(\"--fahopper\")" + $not_hopper3 = "name=\"flashattn_hopper_cuda\"," + + condition: + filesize < 131072 and $setup and any of ($i*) and none of ($not*) +} rule setuptools_oslogin: medium { meta: @@ -11,7 +34,7 @@ rule setuptools_oslogin: medium { $oslogin = "os.login()" condition: - global_python_setup and any of them + remote_access_pythonSetup and any of them } rule setuptools_homedir: high { @@ -23,7 +46,7 @@ rule setuptools_homedir: high { $oslogin = "C:\\Users\\.{0,64}os.login()" condition: - global_python_setup and any of them + remote_access_pythonSetup and any of them } rule setuptools_cmd_exec: high { @@ -43,7 +66,7 @@ rule setuptools_cmd_exec: high { $not_twine_upload = "twine upload dist/*" condition: - global_python_setup and any of ($f*) and none of ($not*) + remote_access_pythonSetup and any of ($f*) and none of ($not*) } rule setuptools_cmd_exec_start: critical { @@ -58,7 +81,7 @@ rule setuptools_cmd_exec_start: critical { $f_subprocess = /subprocess.\w{0,32}\([f\"\']{0,2}start[,'" ]{1,3}.{0,64}/ condition: - global_python_setup and any of ($f*) + remote_access_pythonSetup and any of ($f*) } rule setuptools_eval: medium { @@ -70,7 +93,7 @@ rule setuptools_eval: medium { $f_eval = /eval\([\"\'\/\w\,\.\ \-\)\(]{1,64}\)/ fullword condition: - global_python_setup and any of ($f*) + remote_access_pythonSetup and any of ($f*) } rule setuptools_eval_high: high { @@ -83,7 +106,7 @@ rule setuptools_eval_high: high { $not_namespaced = /eval\([\w\.\(\)\"\/\']{4,16}, [a-z]{1,6}[,\)]/ condition: - global_python_setup and any of ($f*) and none of ($not*) + remote_access_pythonSetup and any of ($f*) and none of ($not*) } rule setuptools_exec: medium { @@ -97,7 +120,7 @@ rule setuptools_exec: medium { $not_hopper = "with open(\" hopper /__version__.py\") as fp:" condition: - global_python_setup and any of ($f*) and none of ($not*) + remote_access_pythonSetup and any of ($f*) and none of ($not*) } rule setuptools_exec_high: high { @@ -119,7 +142,7 @@ rule setuptools_exec_high: high { $not_namespaced = /exec\([\w\.\(\)\"\/\']{4,16}, [a-z]{1,6}[,\)]/ condition: - global_python_setup and any of ($f*) and none of ($not*) + remote_access_pythonSetup and any of ($f*) and none of ($not*) } rule setuptools_b64decode: suspicious { @@ -131,7 +154,7 @@ rule setuptools_b64decode: suspicious { $base64 = "b64decode" condition: - global_python_setup and any of them + remote_access_pythonSetup and any of them } rule setuptools_preinstall: suspicious { @@ -146,7 +169,7 @@ rule setuptools_preinstall: suspicious { $f_pre_install = "from pre_install" condition: - global_python_setup and any of them + remote_access_pythonSetup and any of them } rule setuptools_b64encode: suspicious { @@ -158,7 +181,7 @@ rule setuptools_b64encode: suspicious { $base64 = "b64encode" condition: - global_python_setup and any of them + remote_access_pythonSetup and any of them } rule setuptools_exec_powershell: critical windows { @@ -187,7 +210,7 @@ rule setuptools_os_path_exists: medium { $not_pyspark_ioerror = "\"Failed to load PySpark version file for packaging. You must be in Spark's python dir.\"" condition: - global_python_setup and $ref and none of ($not*) + remote_access_pythonSetup and $ref and none of ($not*) } rule setuptools_excessive_bitwise_math: critical { @@ -199,5 +222,5 @@ rule setuptools_excessive_bitwise_math: critical { $x = /\-{0,1}\d{1,8} \<\< \-{0,1}\d{1,8}/ condition: - global_python_setup and #x > 20 + remote_access_pythonSetup and #x > 20 } diff --git a/rules/impact/wipe/crypto.yara b/rules/impact/wipe/crypto.yara index 0bcc634ad..71d8670db 100644 --- a/rules/impact/wipe/crypto.yara +++ b/rules/impact/wipe/crypto.yara @@ -1,4 +1,7 @@ -include "rules/global/global.yara" +private rule crypto_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 uname_hostname_encrypt_wipe_kill_small: high { meta: @@ -14,7 +17,7 @@ rule uname_hostname_encrypt_wipe_kill_small: high { $hostname = "hostname" fullword condition: - filesize < 2MB and global_elf_or_macho and all of them + filesize < 2MB and crypto_elf_or_macho and all of them } rule uname_hostname_encrypt_wipe_kill: medium { @@ -31,5 +34,5 @@ rule uname_hostname_encrypt_wipe_kill: medium { $hostname = "hostname" fullword condition: - filesize < 20MB and global_elf_or_macho and all of them + filesize < 20MB and crypto_elf_or_macho and all of them } diff --git a/rules/malware/family/amos.yara b/rules/malware/family/amos.yara index a407aa987..650f1ab93 100644 --- a/rules/malware/family/amos.yara +++ b/rules/malware/family/amos.yara @@ -1,6 +1,14 @@ import "math" -include "rules/global/global.yara" +private rule amos_macho { + strings: + $not_jar = "META-INF/" + $not_dwarf = "_DWARF" + $not_kext = "_.SYMDEF SORTED" + + condition: + (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) and none of ($not*) +} rule amos_magic_var: critical macos { meta: @@ -19,7 +27,7 @@ rule amos_magic_var: critical macos { $word_with_spaces = /[a-z]{2,} [a-z]{2,}/ condition: - filesize > 100KB and filesize < 600KB and global_specific_macho and $magic and $header and $main and all of ($f*) and #word_with_spaces < 3 + filesize > 100KB and filesize < 600KB and amos_macho and $magic and $header and $main and all of ($f*) and #word_with_spaces < 3 } rule amos_base32: critical macos { @@ -36,7 +44,7 @@ rule amos_base32: critical macos { $at_exit = "@___cxa_atexit" condition: - filesize > 40KB and filesize < 2MB and global_specific_macho and all of them + filesize > 40KB and filesize < 2MB and amos_macho and all of them } rule maybe_amos: high macos { @@ -58,7 +66,7 @@ rule maybe_amos: high macos { $not_release = "@_CFRelease" fullword condition: - filesize > 190KB and filesize < 400KB and global_specific_macho and all of them and none of ($not*) and math.entropy(1, filesize) >= 4 + filesize > 190KB and filesize < 400KB and amos_macho and all of them and none of ($not*) and math.entropy(1, filesize) >= 4 } rule maybe_amos_hex: high macos { @@ -82,5 +90,5 @@ rule maybe_amos_hex: high macos { $x = /0x[\dabcdefABCDEF]{2,8}/ condition: - filesize > 190KB and filesize < 400KB and global_specific_macho and 95 % of ($f*) and math.entropy(20000, 50000) >= 4.5 and #x > 64 + filesize > 190KB and filesize < 400KB and amos_macho and 95 % of ($f*) and math.entropy(20000, 50000) >= 4.5 and #x > 64 } diff --git a/rules/malware/family/clapzok.yara b/rules/malware/family/clapzok.yara index dbf5f836b..cda522a93 100644 --- a/rules/malware/family/clapzok.yara +++ b/rules/malware/family/clapzok.yara @@ -1,4 +1,7 @@ -include "rules/global/global.yara" +private rule is_macho { + condition: + (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 clapzok_macho: critical { meta: @@ -10,5 +13,5 @@ rule clapzok_macho: critical { $ref = "SfcIsFileProtected" condition: - filesize < 10MB and global_specific_macho and $ref in (filesize - 2200..filesize - 100) + filesize < 10MB and is_macho and $ref in (filesize - 2200..filesize - 100) } diff --git a/rules/malware/family/poseidon_stealer.yara b/rules/malware/family/poseidon_stealer.yara index 59261c32d..82952ffa5 100644 --- a/rules/malware/family/poseidon_stealer.yara +++ b/rules/malware/family/poseidon_stealer.yara @@ -1,6 +1,14 @@ import "math" -include "rules/global/global.yara" +private rule poseidon_macho { + strings: + $not_jar = "META-INF/" + $not_dwarf = "_DWARF" + $not_kext = "_.SYMDEF SORTED" + + condition: + (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) and none of ($not*) +} rule poseidon: high macos { meta: @@ -16,7 +24,7 @@ rule poseidon: high macos { $ve = "vector" fullword condition: - filesize > 190KB and filesize < 400KB and global_specific_macho and all of them and math.entropy(20000, 50000) >= 2.5 + filesize > 190KB and filesize < 400KB and poseidon_macho and all of them and math.entropy(20000, 50000) >= 2.5 } rule poseidon_url: high macos { @@ -29,5 +37,5 @@ rule poseidon_url: high macos { $ref = "https://forked-project.com/check_updates" condition: - filesize > 190KB and filesize < 400KB and global_specific_macho and all of them + filesize > 190KB and filesize < 400KB and poseidon_macho and all of them } diff --git a/rules/net/download/fetch.yara b/rules/net/download/fetch.yara index 91c5788c3..0ffa22c31 100644 --- a/rules/net/download/fetch.yara +++ b/rules/net/download/fetch.yara @@ -1,5 +1,3 @@ -include "rules/global/global.yara" - rule curl_value: medium { meta: description = "Invokes curl" @@ -78,6 +76,16 @@ rule curl_download_ip: critical { any of them } +private rule fetch_macho { + condition: + 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 +} + +private rule fetch_elf { + condition: + uint32(0) == 1179403647 +} + rule fetch_tool: medium { meta: description = "calls a URL fetch tool" @@ -109,7 +117,7 @@ rule binary_calls_fetch_tool: high { $not_tftp_err = "tftp error" condition: - filesize < 10MB and (global_elf_or_macho) and any of ($t*) and none of ($not*) + filesize < 10MB and (fetch_elf or fetch_macho) and any of ($t*) and none of ($not*) } rule curl_agent_val: high { diff --git a/rules/sus/compiler.yara b/rules/sus/compiler.yara index 111053000..08a18b2f7 100644 --- a/rules/sus/compiler.yara +++ b/rules/sus/compiler.yara @@ -1,5 +1,3 @@ -include "rules/global/global.yara" - rule archaic_gcc: medium { meta: description = "built by an ancient version of GCC" @@ -30,6 +28,12 @@ rule small_opaque_archaic_gcc: high linux { filesize < 30KB and $gcc_v4 and $fork in (1000..3000) and none of ($not*) and #word_with_spaces < 15 } +private rule binary { + condition: + // matches ELF or machO binary + filesize < 40MB 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) +} + rule multiple_gcc: medium { meta: description = "built with multiple versions of GCC" @@ -39,7 +43,7 @@ rule multiple_gcc: medium { $gcc = /GCC: \([\w \.\-\~\(\)]{8,64}/ fullword condition: - global_binary and #gcc > 1 and !gcc[1] != !gcc[2] + binary and #gcc > 1 and !gcc[1] != !gcc[2] } rule multiple_gcc_high: high { @@ -54,5 +58,5 @@ rule multiple_gcc_high: high { $not_java = "JAVA_HOME" condition: - global_binary and #gcc > 1 and !gcc[1] != !gcc[2] and none of ($not*) + binary and #gcc > 1 and !gcc[1] != !gcc[2] and none of ($not*) } diff --git a/rules/sus/entitlement.yara b/rules/sus/entitlement.yara index a491e2416..ca2e4ba68 100644 --- a/rules/sus/entitlement.yara +++ b/rules/sus/entitlement.yara @@ -1,4 +1,12 @@ -include "rules/global/global.yara" +private rule entitlement_macho { + strings: + $not_jar = "META-INF/" + $not_dwarf = "_DWARF" + $not_kext = "_.SYMDEF SORTED" + + condition: + (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) and none of ($not*) +} rule com_apple_get_task_allow: medium { meta: @@ -10,5 +18,5 @@ rule com_apple_get_task_allow: medium { $true = "" condition: - global_specific_macho and all of them + entitlement_macho and all of them }