Skip to content

Commit

Permalink
Improve Python detection for EvilDojo666 attack (#635)
Browse files Browse the repository at this point in the history
* Improve Python detection for EvilDojo666 attack

* Improve detection of machO backdoors & stealers (#631)

* improve malicious dmg detection

* Improve detection of machO backdoors & stealers

* improve rules

* update testdata

* update testdata

* tune rules

* tune rules

---------

Co-authored-by: Evan Gibler <[email protected]>

* Add files, update test data

* Add models.py sample

* improve rule matcha accuracy

* fmt yara

* fix false-positive for versioneer/versioneer.py

---------

Co-authored-by: Evan Gibler <[email protected]>
  • Loading branch information
tstromberg and egibs authored Nov 17, 2024
1 parent 8fead21 commit 1c58757
Show file tree
Hide file tree
Showing 51 changed files with 171 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


SAMPLES_REPO ?= chainguard-dev/malcontent-samples
SAMPLES_COMMIT ?= 4b70b17db7e2219552be9b4a05e8d8b3ffe09146
SAMPLES_COMMIT ?= 8c02e6ef4d3a67e4e45f58e1b1b05a586e8bc24f

# BEGIN: lint-install ../malcontent
# http://github.com/tinkerbell/lint-install
Expand Down
4 changes: 2 additions & 2 deletions rules/anti-static/base64/eval.yara
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ rule ruby_eval2_near_enough: critical {
all of them and math.abs(@base64 - @eval) <= 200
}

rule python_exec_near_enough: high {
rule python_exec_near_enough_base64: high {
meta:
description = "Evaluates base64 content"
description = "Likely executes base64 content"

strings:
$exec = "exec("
Expand Down
2 changes: 1 addition & 1 deletion rules/anti-static/obfuscation/js.yara
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ rule js_const_func_obfuscation: medium {

rule js_hex_eval_obfuscation: critical {
meta:
description = "javascript eval bfuscation (hex)"
description = "javascript eval obfuscation (hex)"

strings:
$return = /\(eval, _{0,4}0x[\w]{0,32}[\(\[]/
Expand Down
37 changes: 35 additions & 2 deletions rules/anti-static/obfuscation/python.yara
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
private rule probably_python {
strings:
$f_function = "import" fullword
$f_for = "for x in" fullword
condition:
filesize < 512KB and any of ($f*)
}

rule Vare_Obfuscator: critical {
meta:
description = "obfuscated with https://github.com/saintdaddy/Vare-Obfuscator"
Expand Down Expand Up @@ -29,10 +38,11 @@ rule join_map_chr: high {
filetypes = "py"

strings:
$ref = /join\(map\(chr,\[\d{1,3},\d{1,3},[\d\,]{1,32}/
$ref = /join\(map\(chr,\[\d{1,3}, {0,2}\d{1,3}, {0,2}[\d\,]{1,32}/
$ref2 = /join\(chr\([a-z]{1,5}\) for [a-z]{1,5} in \[\d{1,3}, {0,2}\d{1,3}, {0,2}[\d\,]{1,32}/
condition:
filesize < 8KB and $ref
filesize < 256KB and any of them
}

rule codecs_decode: high {
Expand Down Expand Up @@ -463,3 +473,26 @@ rule decompress_base64_entropy: high {
filesize < 1MB and any of ($k*) and $b64decode and $long_str and any of ($f*)
}

rule join: low {
meta:
description = "joins array together with an empty delimiter"

strings:
$join = "''.join("
$join_double = "\"\".join("
condition:
probably_python and any of them
}

rule urllib_as_int_array: critical {
meta:
description = "hides urllib code as an array of integers"

strings:
$urllib_dot = "117,114,108,108,105,98,46"
$urllib_dot2 = "117, 114, 108, 108, 105, 98, 46"
condition:
filesize < 1MB and any of them
}
14 changes: 14 additions & 0 deletions rules/c2/addr/url.yara
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,17 @@ rule script_url_with_question: high {
condition:
filesize < 256KB and any of ($f*) and $ref and none of ($not*)
}

rule url_code_as_chr_int: high {
meta:
description = "hides URL within an array of integers"

strings:
$https = "104,116,116,112,115,58,47,47"
$https2 = "104, 116, 116, 112, 115, 58, 47, 47"
$http = "104,116,116,112,58,47,47"
$http2 = "104, 116, 116, 112, 58, 47, 47"
condition:
filesize < 1MB and any of them
}
25 changes: 25 additions & 0 deletions rules/exec/imports/python.yara
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
rule has_import: low {
meta:
description = "imports python modules"

strings:
$ref = /import [a-z0-9A-Z]{2,12}/ fullword
$ref2 = /from [a-z0-9A-Z\.]{2,48} import [a-z0-9A-Z]{2,24}/ fullword
condition:
filesize < 64KB and any of them
}

rule python_code_as_chr_int: critical {
meta:
description = "hides additional import as array of integers"

strings:
$import = "import" fullword
$int_no_space = "105,109,112,111,114,116,32"
$int_space = "105, 109, 112, 111, 114, 116, 32"
condition:
filesize < 1MB and $import and any of ($int*)
}

rule single_line_import: medium {
meta:
description = "imports built-in and executes more code on the same line"
Expand Down
27 changes: 26 additions & 1 deletion rules/exec/remote_commands/code_eval.yara
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import "math"

rule eval: medium {
meta:
description = "evaluate code dynamically using eval()"
Expand All @@ -17,13 +19,36 @@ rule python_exec: medium {

strings:
$import = "import" fullword
$val = /exec\([a-z\"\'\(\,\)]{1,32}/ fullword
$val = /exec\([\w\ \"\'\.\(\)\[\]]{1,64}/ fullword
$empty = "exec()"
condition:
filesize < 1MB and $import and $val and not $empty
}

rule python_exec_near_enough_chr: high {
meta:
description = "Likely executes encoded character content"

strings:
$exec = "exec("
$chr = "chr("
condition:
all of them and math.abs(@chr - @exec) < 100
}

rule python_exec_chr: critical {
meta:
description = "Executes encoded character content"

strings:
$exec = /exec\(.{0,16}chr\(.{0,16}\[\d[\d\, ]{0,64}/
condition:
filesize < 512KB and all of them
}

rule shell_eval: medium {
meta:
description = "evaluate shell code dynamically using eval"
Expand Down
4 changes: 2 additions & 2 deletions rules/false_positives/py_versioneer.yara
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
rule versioneer_py: override {
meta:
description = "versioneer.py"
python_exec_near_enough = "medium"
description = "versioneer.py"
python_exec_near_enough_base64 = "medium"

strings:
$script = "versioneer.py"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ anti-static/base64/eval: high
anti-static/base64/function_names: critical
data/base64/decode: medium
data/encoding/base64: low
exec/imports/python: low
exec/program: medium
exec/remote_commands/code_eval: medium
fs/file/delete: low
fs/file/open: low
fs/file/read: low
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ anti-static/obfuscation/python: medium
data/base64/decode: medium
data/encoding/base64: low
exec/cmd/pipe: medium
exec/imports/python: low
exec/shell/SHELL: low
fs/file/open: low
fs/file/read: low
Expand Down
1 change: 1 addition & 0 deletions tests/linux/2024.hadooken/drop2.sh.simple
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# linux/2024.hadooken/drop2.sh: critical
c2/addr/ip: high
exec/imports/python: low
exec/remote_commands/code_eval: medium
impact/remote_access/remote_eval: critical
net/url/embedded: low
Expand Down
1 change: 1 addition & 0 deletions tests/linux/2024.hadooken/figure4.py.simple
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ c2/addr/ip: high
c2/tool_transfer/binary: high
c2/tool_transfer/http_ip_temp: critical
c2/tool_transfer/python: high
exec/imports/python: low
exec/program: medium
fs/file/delete: low
fs/file/open: low
Expand Down
1 change: 1 addition & 0 deletions tests/linux/mimipenguin/python/mimipenguin.simple
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ data/encoding/base64: low
discover/process/name: medium
discover/processes/list: medium
discover/system/platform: medium
exec/imports/python: low
exfil/stealer/password: critical
fs/directory/list: low
fs/file/open: low
Expand Down
1 change: 1 addition & 0 deletions tests/php/2024.sagsooz/2024.php.simple
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ data/encoding/base64: low
discover/process/egid: medium
evasion/indicator_blocking/mask_exceptions: medium
evasion/time/php_no_limit: medium
exec/imports/python: low
exec/shell/command: medium
fs/directory/remove: low
fs/file/delete: low
Expand Down
1 change: 1 addition & 0 deletions tests/python/2021.DiscordSafety/setup.py.simple
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ c2/tool_transfer/download: high
collect/databases/leveldb: medium
data/encoding/base64: low
data/encoding/marshal: medium
exec/imports/python: low
exec/program: medium
exec/remote_commands/code_eval: medium
exfil/stealer/browser: high
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ discover/user/name_get: high
evasion/file/prefix: medium
evasion/file/prefix/tmp: high
exec/cmd/pipe: medium
exec/imports/python: low
exec/program: medium
exec/shell/command: medium
exfil/curl_post: medium
Expand Down
1 change: 1 addition & 0 deletions tests/python/2022.activedevbadge-0.39/setup.py.simple
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# python/2022.activedevbadge-0.39/setup.py: critical
c2/tool_transfer/python: critical
discover/user/name_get: high
exec/imports/python: low
exec/program: medium
fs/directory/create: low
fs/directory/list: low
Expand Down
1 change: 1 addition & 0 deletions tests/python/2023.JokerSpy/shared.dat.simple
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ discover/network/interface_list: medium
discover/system/platform: medium
discover/user/name_get: low
evasion/file/prefix: medium
exec/imports/python: low
exec/program: medium
exec/remote_commands/code_eval: medium
exec/tty/getpass: low
Expand Down
1 change: 1 addition & 0 deletions tests/python/2023.axderz-1.0.4/setup.py.simple
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ credential/ssh: high
data/encoding/base64: low
discover/system/environment: medium
evasion/net/http_443: high
exec/imports/python: low
exec/program: medium
exec/shell/power: medium
exfil/stealer/ssh: critical
Expand Down
1 change: 1 addition & 0 deletions tests/python/2024.Custom.RAT/output.py.simple
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ discover/user/name_get: low
exec/cmd/pipe: medium
exec/conditional/is_admin: medium
exec/conditional/root_check: medium
exec/imports/python: low
exec/program: medium
exec/shell/command: medium
exec/shell/power: medium
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ anti-static/obfuscation/python: high
data/base64/decode: medium
data/encoding/base64: low
discover/system/platform: medium
exec/imports/python: low
exec/program: medium
exec/shell/command: medium
fs/file/open: low
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ anti-static/obfuscation/python: high
data/base64/decode: medium
data/encoding/base64: low
discover/system/platform: medium
exec/imports/python: low
exec/remote_commands/code_eval: medium
net/url/request: medium
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# python/2024.ScreenLocker/0a5f907e9f0dade65fc292d3f1ed1f68cfb68895a84adaa173c543792be891ba.py: critical
credential/password: low
exec/imports/python: low
exec/shell/command: medium
impact/ransom/locked: high
malware/family/lockscreen: critical
1 change: 1 addition & 0 deletions tests/python/2024.advpruebitaa9-1.0.0/setup.py.simple
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
anti-static/base64/exec: critical
data/base64/decode: medium
data/encoding/base64: low
exec/imports/python: low
exec/program: medium
impact/remote_access/py_setuptools: high
net/url/embedded: low
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# python/2024.business-kpi-manager-5.9.1/pre_install.py: critical
discover/user/name_get: medium
exec/imports/python: low
exec/program: medium
exfil/curl_post: medium
exfil/oob: high
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# python/2024.business-kpi-manager-5.9.1/setup.py: high
exec/imports/python: low
impact/remote_access/py_setuptools: high
net/download: medium
net/url/embedded: low
1 change: 0 additions & 1 deletion tests/python/2024.coloredtxt/unhex.py.simple
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@
anti-static/obfuscation/hex: high
data/encoding/base64: low
exec/imports/python: high
exec/remote_commands/code_eval: medium
3 changes: 2 additions & 1 deletion tests/python/2024.d3duct1v/xfilesyncerx.py.simple
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# python/2024.d3duct1v/xfilesyncerx.py: critical
anti-static/obfuscation/bitwise: critical
anti-static/obfuscation/python: high
exec/remote_commands/code_eval: medium
exec/imports/python: low
exec/remote_commands/code_eval: high
impact/remote_access/remote_eval: critical
net/url/request: medium
5 changes: 5 additions & 0 deletions tests/python/2024.evildojo666/models.py.simple
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# python/2024.evildojo666/models.py: critical
anti-static/obfuscation/python: critical
c2/addr/url: high
exec/imports/python: critical
exec/remote_commands/code_eval: critical
1 change: 1 addition & 0 deletions tests/python/2024.yocolor/__init__.py.simple
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# python/2024.yocolor/__init__.py: critical
exec/imports/python: low
exec/install_additional/pip_install: critical
exec/program: medium
net/url/embedded: low
Expand Down
17 changes: 17 additions & 0 deletions tests/python/2024.yocolor/setup.py.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@
"ID": "crypto/fernet",
"RuleName": "crypto_fernet"
},
{
"Description": "imports python modules",
"MatchStrings": [
"from distutils.core import setup",
"from setuptools import setup",
"import fernet",
"import os",
"import re",
"import sys",
"import with"
],
"RiskScore": 1,
"RiskLevel": "LOW",
"RuleURL": "https://github.com/chainguard-dev/malcontent/blob/main/rules/exec/imports/python.yara#has_import",
"ID": "exec/imports/python",
"RuleName": "has_import"
},
{
"Description": "Installs fernet crypto package using pip",
"MatchStrings": [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# python/clean/conda-build/_load_setup_py_data.py: medium
exec/imports/python: low
exec/remote_commands/code_eval: medium
fs/file/open: low
impact/remote_access/py_setuptools: low
Expand Down
1 change: 1 addition & 0 deletions tests/python/clean/gevent/test__monkey.py.simple
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# python/clean/gevent/test__monkey.py: medium
anti-static/obfuscation/python: medium
exec/imports/python: low
exec/program: medium
impact/remote_access/pseudo_terminal: medium
process/create: low
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# python/clean/google-auth-library-python/setup.py: medium
exec/imports/python: low
exec/remote_commands/code_eval: medium
exec/shell/command: medium
fs/file/open: low
Expand Down
Loading

0 comments on commit 1c58757

Please sign in to comment.