@trailofbits/vsix-audit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +281 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +703 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/scanner/batch.d.ts +12 -0
- package/dist/scanner/batch.d.ts.map +1 -0
- package/dist/scanner/batch.js +104 -0
- package/dist/scanner/batch.js.map +1 -0
- package/dist/scanner/bundler.d.ts +35 -0
- package/dist/scanner/bundler.d.ts.map +1 -0
- package/dist/scanner/bundler.js +120 -0
- package/dist/scanner/bundler.js.map +1 -0
- package/dist/scanner/cache.d.ts +45 -0
- package/dist/scanner/cache.d.ts.map +1 -0
- package/dist/scanner/cache.js +153 -0
- package/dist/scanner/cache.js.map +1 -0
- package/dist/scanner/cache.test.d.ts +2 -0
- package/dist/scanner/cache.test.d.ts.map +1 -0
- package/dist/scanner/cache.test.js +149 -0
- package/dist/scanner/cache.test.js.map +1 -0
- package/dist/scanner/capabilities.d.ts +29 -0
- package/dist/scanner/capabilities.d.ts.map +1 -0
- package/dist/scanner/capabilities.js +217 -0
- package/dist/scanner/capabilities.js.map +1 -0
- package/dist/scanner/checks/ast.d.ts +3 -0
- package/dist/scanner/checks/ast.d.ts.map +1 -0
- package/dist/scanner/checks/ast.js +469 -0
- package/dist/scanner/checks/ast.js.map +1 -0
- package/dist/scanner/checks/ast.test.d.ts +2 -0
- package/dist/scanner/checks/ast.test.d.ts.map +1 -0
- package/dist/scanner/checks/ast.test.js +389 -0
- package/dist/scanner/checks/ast.test.js.map +1 -0
- package/dist/scanner/checks/behavioral.d.ts +3 -0
- package/dist/scanner/checks/behavioral.d.ts.map +1 -0
- package/dist/scanner/checks/behavioral.js +367 -0
- package/dist/scanner/checks/behavioral.js.map +1 -0
- package/dist/scanner/checks/blocklist.d.ts +3 -0
- package/dist/scanner/checks/blocklist.d.ts.map +1 -0
- package/dist/scanner/checks/blocklist.js +32 -0
- package/dist/scanner/checks/blocklist.js.map +1 -0
- package/dist/scanner/checks/blocklist.test.d.ts +2 -0
- package/dist/scanner/checks/blocklist.test.d.ts.map +1 -0
- package/dist/scanner/checks/blocklist.test.js +74 -0
- package/dist/scanner/checks/blocklist.test.js.map +1 -0
- package/dist/scanner/checks/chains.d.ts +35 -0
- package/dist/scanner/checks/chains.d.ts.map +1 -0
- package/dist/scanner/checks/chains.js +505 -0
- package/dist/scanner/checks/chains.js.map +1 -0
- package/dist/scanner/checks/chains.test.d.ts +2 -0
- package/dist/scanner/checks/chains.test.d.ts.map +1 -0
- package/dist/scanner/checks/chains.test.js +250 -0
- package/dist/scanner/checks/chains.test.js.map +1 -0
- package/dist/scanner/checks/dataflow.d.ts +3 -0
- package/dist/scanner/checks/dataflow.d.ts.map +1 -0
- package/dist/scanner/checks/dataflow.js +316 -0
- package/dist/scanner/checks/dataflow.js.map +1 -0
- package/dist/scanner/checks/dependencies.d.ts +13 -0
- package/dist/scanner/checks/dependencies.d.ts.map +1 -0
- package/dist/scanner/checks/dependencies.js +225 -0
- package/dist/scanner/checks/dependencies.js.map +1 -0
- package/dist/scanner/checks/dependencies.test.d.ts +2 -0
- package/dist/scanner/checks/dependencies.test.d.ts.map +1 -0
- package/dist/scanner/checks/dependencies.test.js +248 -0
- package/dist/scanner/checks/dependencies.test.js.map +1 -0
- package/dist/scanner/checks/finding-quality.test.d.ts +8 -0
- package/dist/scanner/checks/finding-quality.test.d.ts.map +1 -0
- package/dist/scanner/checks/finding-quality.test.js +164 -0
- package/dist/scanner/checks/finding-quality.test.js.map +1 -0
- package/dist/scanner/checks/ioc.d.ts +20 -0
- package/dist/scanner/checks/ioc.d.ts.map +1 -0
- package/dist/scanner/checks/ioc.js +234 -0
- package/dist/scanner/checks/ioc.js.map +1 -0
- package/dist/scanner/checks/ioc.test.d.ts +2 -0
- package/dist/scanner/checks/ioc.test.d.ts.map +1 -0
- package/dist/scanner/checks/ioc.test.js +298 -0
- package/dist/scanner/checks/ioc.test.js.map +1 -0
- package/dist/scanner/checks/manifest.d.ts +6 -0
- package/dist/scanner/checks/manifest.d.ts.map +1 -0
- package/dist/scanner/checks/manifest.js +123 -0
- package/dist/scanner/checks/manifest.js.map +1 -0
- package/dist/scanner/checks/manifest.test.d.ts +2 -0
- package/dist/scanner/checks/manifest.test.d.ts.map +1 -0
- package/dist/scanner/checks/manifest.test.js +108 -0
- package/dist/scanner/checks/manifest.test.js.map +1 -0
- package/dist/scanner/checks/obfuscation.d.ts +3 -0
- package/dist/scanner/checks/obfuscation.d.ts.map +1 -0
- package/dist/scanner/checks/obfuscation.js +432 -0
- package/dist/scanner/checks/obfuscation.js.map +1 -0
- package/dist/scanner/checks/obfuscation.test.d.ts +2 -0
- package/dist/scanner/checks/obfuscation.test.d.ts.map +1 -0
- package/dist/scanner/checks/obfuscation.test.js +399 -0
- package/dist/scanner/checks/obfuscation.test.js.map +1 -0
- package/dist/scanner/checks/package.d.ts +17 -0
- package/dist/scanner/checks/package.d.ts.map +1 -0
- package/dist/scanner/checks/package.js +422 -0
- package/dist/scanner/checks/package.js.map +1 -0
- package/dist/scanner/checks/package.test.d.ts +2 -0
- package/dist/scanner/checks/package.test.d.ts.map +1 -0
- package/dist/scanner/checks/package.test.js +518 -0
- package/dist/scanner/checks/package.test.js.map +1 -0
- package/dist/scanner/checks/patterns.d.ts +5 -0
- package/dist/scanner/checks/patterns.d.ts.map +1 -0
- package/dist/scanner/checks/patterns.js +251 -0
- package/dist/scanner/checks/patterns.js.map +1 -0
- package/dist/scanner/checks/patterns.test.d.ts +2 -0
- package/dist/scanner/checks/patterns.test.d.ts.map +1 -0
- package/dist/scanner/checks/patterns.test.js +147 -0
- package/dist/scanner/checks/patterns.test.js.map +1 -0
- package/dist/scanner/checks/unicode.d.ts +3 -0
- package/dist/scanner/checks/unicode.d.ts.map +1 -0
- package/dist/scanner/checks/unicode.js +247 -0
- package/dist/scanner/checks/unicode.js.map +1 -0
- package/dist/scanner/checks/unicode.test.d.ts +2 -0
- package/dist/scanner/checks/unicode.test.d.ts.map +1 -0
- package/dist/scanner/checks/unicode.test.js +202 -0
- package/dist/scanner/checks/unicode.test.js.map +1 -0
- package/dist/scanner/checks/yara.d.ts +23 -0
- package/dist/scanner/checks/yara.d.ts.map +1 -0
- package/dist/scanner/checks/yara.js +349 -0
- package/dist/scanner/checks/yara.js.map +1 -0
- package/dist/scanner/checks/yara.test.d.ts +2 -0
- package/dist/scanner/checks/yara.test.d.ts.map +1 -0
- package/dist/scanner/checks/yara.test.js +126 -0
- package/dist/scanner/checks/yara.test.js.map +1 -0
- package/dist/scanner/constants.d.ts +18 -0
- package/dist/scanner/constants.d.ts.map +1 -0
- package/dist/scanner/constants.js +37 -0
- package/dist/scanner/constants.js.map +1 -0
- package/dist/scanner/detection-coverage.test.d.ts +2 -0
- package/dist/scanner/detection-coverage.test.d.ts.map +1 -0
- package/dist/scanner/detection-coverage.test.js +216 -0
- package/dist/scanner/detection-coverage.test.js.map +1 -0
- package/dist/scanner/download.d.ts +76 -0
- package/dist/scanner/download.d.ts.map +1 -0
- package/dist/scanner/download.js +339 -0
- package/dist/scanner/download.js.map +1 -0
- package/dist/scanner/download.test.d.ts +2 -0
- package/dist/scanner/download.test.d.ts.map +1 -0
- package/dist/scanner/download.test.js +149 -0
- package/dist/scanner/download.test.js.map +1 -0
- package/dist/scanner/index.d.ts +8 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +167 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/index.test.d.ts +2 -0
- package/dist/scanner/index.test.d.ts.map +1 -0
- package/dist/scanner/index.test.js +71 -0
- package/dist/scanner/index.test.js.map +1 -0
- package/dist/scanner/loaders/zoo.d.ts +3 -0
- package/dist/scanner/loaders/zoo.d.ts.map +1 -0
- package/dist/scanner/loaders/zoo.js +112 -0
- package/dist/scanner/loaders/zoo.js.map +1 -0
- package/dist/scanner/types.d.ts +118 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +2 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/scanner/utils.d.ts +14 -0
- package/dist/scanner/utils.d.ts.map +1 -0
- package/dist/scanner/utils.js +25 -0
- package/dist/scanner/utils.js.map +1 -0
- package/dist/scanner/vsix.d.ts +6 -0
- package/dist/scanner/vsix.d.ts.map +1 -0
- package/dist/scanner/vsix.js +213 -0
- package/dist/scanner/vsix.js.map +1 -0
- package/dist/scanner/vsix.test.d.ts +2 -0
- package/dist/scanner/vsix.test.d.ts.map +1 -0
- package/dist/scanner/vsix.test.js +355 -0
- package/dist/scanner/vsix.test.js.map +1 -0
- package/package.json +60 -0
- package/zoo/blocklist/extensions.json +201 -0
- package/zoo/iocs/blockchain-extensions.txt +21 -0
- package/zoo/iocs/c2-domains.txt +50 -0
- package/zoo/iocs/c2-ips.txt +24 -0
- package/zoo/iocs/hashes.txt +47 -0
- package/zoo/iocs/malicious-npm.txt +85 -0
- package/zoo/iocs/wallets.txt +18 -0
- package/zoo/signatures/yara/README.md +46 -0
- package/zoo/signatures/yara/blockchain_c2.yar +48 -0
- package/zoo/signatures/yara/code_execution.yar +165 -0
- package/zoo/signatures/yara/credential_harvesting.yar +116 -0
- package/zoo/signatures/yara/crypto_wallet_targeting.yar +92 -0
- package/zoo/signatures/yara/data_exfiltration.yar +207 -0
- package/zoo/signatures/yara/google_calendar_c2.yar +187 -0
- package/zoo/signatures/yara/messaging_c2.yar +103 -0
- package/zoo/signatures/yara/multi_stage_attacks.yar +331 -0
- package/zoo/signatures/yara/obfuscation_patterns.yar +208 -0
- package/zoo/signatures/yara/powershell_attacks.yar +116 -0
- package/zoo/signatures/yara/rat_capabilities.yar +243 -0
- package/zoo/signatures/yara/self_propagation.yar +239 -0
- package/zoo/signatures/yara/unicode_stealth.yar +48 -0
- package/zoo/signatures/yara/websocket_c2.yar +83 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Multi-Stage Attack Pattern Detection
|
|
3
|
+
Detects attack chains that combine multiple stages (download->write->execute, etc.)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
rule LOADER_JS_Download_Write_Execute_Jan25 {
|
|
7
|
+
meta:
|
|
8
|
+
description = "Detects dropper pattern that downloads content, writes to temp directory, and executes"
|
|
9
|
+
severity = "critical"
|
|
10
|
+
score = 90
|
|
11
|
+
author = "vsix-audit"
|
|
12
|
+
date = "2025-01-29"
|
|
13
|
+
|
|
14
|
+
strings:
|
|
15
|
+
// Download stage
|
|
16
|
+
$dl1 = "fetch(" ascii wide
|
|
17
|
+
$dl2 = "axios.get" ascii wide
|
|
18
|
+
$dl3 = "https.get" ascii wide
|
|
19
|
+
$dl4 = "http.get" ascii wide
|
|
20
|
+
$dl5 = "request(" ascii wide
|
|
21
|
+
$dl6 = "got(" ascii wide
|
|
22
|
+
|
|
23
|
+
// Write stage
|
|
24
|
+
$write1 = "writeFileSync" ascii wide
|
|
25
|
+
$write2 = "writeFile" ascii wide
|
|
26
|
+
$write3 = "createWriteStream" ascii wide
|
|
27
|
+
|
|
28
|
+
// Execute stage
|
|
29
|
+
$exec1 = "child_process" ascii wide
|
|
30
|
+
$exec2 = ".exec(" ascii wide
|
|
31
|
+
$exec3 = ".spawn(" ascii wide
|
|
32
|
+
$exec4 = "execSync" ascii wide
|
|
33
|
+
$exec5 = "spawnSync" ascii wide
|
|
34
|
+
|
|
35
|
+
// Temp/hidden location indicators (require these for dropper pattern)
|
|
36
|
+
$temp1 = "/tmp/" ascii wide
|
|
37
|
+
$temp2 = "\\Temp\\" ascii wide
|
|
38
|
+
$temp3 = "os.tmpdir" ascii wide
|
|
39
|
+
$temp4 = "TEMP" ascii wide
|
|
40
|
+
|
|
41
|
+
// Base64 decode before write (payload decoding)
|
|
42
|
+
$decode1 = "atob(" ascii wide
|
|
43
|
+
$decode2 = "Buffer.from" ascii wide
|
|
44
|
+
$decode3 = "base64" ascii wide nocase
|
|
45
|
+
|
|
46
|
+
// Make executable before exec (chmod)
|
|
47
|
+
$chmod1 = "chmodSync" ascii wide
|
|
48
|
+
$chmod2 = "fs.chmod" ascii wide
|
|
49
|
+
$chmod3 = "chmod(" ascii wide
|
|
50
|
+
|
|
51
|
+
// Hidden file indicators (require 4+ bytes for good YARA atoms)
|
|
52
|
+
$hidden1 = "/tmp/." ascii wide // Unix hidden files in /tmp
|
|
53
|
+
$hidden2 = "\\AppData\\Local\\Temp\\." ascii wide // Windows hidden files in temp
|
|
54
|
+
|
|
55
|
+
condition:
|
|
56
|
+
// Require all three stages PLUS dropper indicator
|
|
57
|
+
any of ($dl*) and any of ($write*) and any of ($exec*) and
|
|
58
|
+
(
|
|
59
|
+
any of ($temp*) or // Writing to temp directory
|
|
60
|
+
any of ($decode*) or // Decoding payload before write
|
|
61
|
+
any of ($chmod*) or // Making file executable
|
|
62
|
+
any of ($hidden*) // Writing to hidden location
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
rule RAT_JS_Reverse_Shell_Jan25 {
|
|
67
|
+
meta:
|
|
68
|
+
description = "Detects reverse shell pattern where network socket is piped to shell for remote command execution"
|
|
69
|
+
severity = "high"
|
|
70
|
+
score = 85
|
|
71
|
+
author = "vsix-audit"
|
|
72
|
+
date = "2025-01-29"
|
|
73
|
+
|
|
74
|
+
strings:
|
|
75
|
+
// Network socket creation (raw TCP, not HTTP)
|
|
76
|
+
$net1 = "net.Socket" ascii wide
|
|
77
|
+
$net2 = "net.connect" ascii wide
|
|
78
|
+
$net3 = "net.createConnection" ascii wide
|
|
79
|
+
$net4 = "socket.connect" ascii wide
|
|
80
|
+
|
|
81
|
+
// Shell execution (specific paths, not just "child_process")
|
|
82
|
+
$shell1 = "/bin/sh" ascii wide
|
|
83
|
+
$shell2 = "/bin/bash" ascii wide
|
|
84
|
+
$shell3 = "/bin/zsh" ascii wide
|
|
85
|
+
$shell4 = "cmd.exe" ascii wide
|
|
86
|
+
$shell5 = "powershell.exe" ascii wide nocase
|
|
87
|
+
|
|
88
|
+
// Piping stdin/stdout (require both for reverse shell)
|
|
89
|
+
$pipe_stdin = "stdin" ascii wide
|
|
90
|
+
$pipe_stdout = "stdout" ascii wide
|
|
91
|
+
$pipe_method = ".pipe(" ascii wide
|
|
92
|
+
|
|
93
|
+
// Spawn with shell option (classic reverse shell pattern)
|
|
94
|
+
$spawn_shell = /spawn\s*\([^)]*shell\s*:\s*true/i ascii wide
|
|
95
|
+
|
|
96
|
+
condition:
|
|
97
|
+
// Classic reverse shell: socket + shell path + stdin/stdout piping
|
|
98
|
+
(any of ($net*) and any of ($shell*) and $pipe_stdin and $pipe_stdout) or
|
|
99
|
+
// Or: socket + shell path + pipe method
|
|
100
|
+
(any of ($net*) and any of ($shell*) and $pipe_method) or
|
|
101
|
+
// Or: spawn with shell option + socket
|
|
102
|
+
($spawn_shell and any of ($net*))
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
rule STEALER_JS_Keylogger_Jan25 {
|
|
106
|
+
meta:
|
|
107
|
+
description = "Detects keylogger pattern that captures keyboard or clipboard input and exfiltrates data"
|
|
108
|
+
severity = "high"
|
|
109
|
+
score = 85
|
|
110
|
+
author = "vsix-audit"
|
|
111
|
+
date = "2025-01-29"
|
|
112
|
+
|
|
113
|
+
strings:
|
|
114
|
+
// High-confidence capture patterns (actual keylogging, not text document events)
|
|
115
|
+
$capture_key1 = "keydown" ascii wide
|
|
116
|
+
$capture_key2 = "keypress" ascii wide
|
|
117
|
+
$capture_key3 = "keyup" ascii wide
|
|
118
|
+
$capture_clip = "clipboard.readText" ascii wide
|
|
119
|
+
|
|
120
|
+
// Low-confidence capture (VS Code API - needs additional indicators)
|
|
121
|
+
$capture_vsc = "onDidChangeTextDocument" ascii wide
|
|
122
|
+
|
|
123
|
+
// Storage with suspicious naming
|
|
124
|
+
$store_suspicious1 = "keylog" ascii wide nocase
|
|
125
|
+
$store_suspicious2 = "keystroke" ascii wide nocase
|
|
126
|
+
$store_suspicious3 = "inputBuffer" ascii wide
|
|
127
|
+
$store_suspicious4 = "capturedKeys" ascii wide
|
|
128
|
+
|
|
129
|
+
// Generic storage (needs other indicators)
|
|
130
|
+
$store_generic1 = "globalState" ascii wide
|
|
131
|
+
$store_generic2 = "appendFile" ascii wide
|
|
132
|
+
|
|
133
|
+
// High-confidence exfil (known bad destinations)
|
|
134
|
+
$exfil_discord = "discord.com/api/webhooks" ascii wide
|
|
135
|
+
$exfil_telegram = "api.telegram.org" ascii wide
|
|
136
|
+
|
|
137
|
+
// Generic exfil (needs other indicators)
|
|
138
|
+
$exfil_generic1 = "axios.post" ascii wide
|
|
139
|
+
$exfil_generic2 = ".post(" ascii wide
|
|
140
|
+
|
|
141
|
+
condition:
|
|
142
|
+
// High confidence: keyboard events + storage + exfil
|
|
143
|
+
(any of ($capture_key*) and any of ($store_suspicious*, $store_generic*) and any of ($exfil_discord, $exfil_telegram, $exfil_generic*)) or
|
|
144
|
+
// High confidence: clipboard read + known bad destination
|
|
145
|
+
($capture_clip and any of ($exfil_discord, $exfil_telegram)) or
|
|
146
|
+
// Medium confidence: VS Code API + suspicious storage names + exfil
|
|
147
|
+
($capture_vsc and any of ($store_suspicious*) and any of ($exfil_discord, $exfil_telegram, $exfil_generic*))
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
rule RAT_JS_Persistence_Startup_Jan25 {
|
|
151
|
+
meta:
|
|
152
|
+
description = "Detects persistence mechanism that modifies startup files, registry keys, or scheduled tasks"
|
|
153
|
+
severity = "high"
|
|
154
|
+
score = 80
|
|
155
|
+
author = "vsix-audit"
|
|
156
|
+
date = "2025-01-29"
|
|
157
|
+
|
|
158
|
+
strings:
|
|
159
|
+
// Unix startup file paths (require path context, not just filename)
|
|
160
|
+
$unix_path1 = /\$HOME\/\.bashrc/ ascii wide
|
|
161
|
+
$unix_path2 = /\$HOME\/\.zshrc/ ascii wide
|
|
162
|
+
$unix_path3 = /\$HOME\/\.profile/ ascii wide
|
|
163
|
+
$unix_path4 = /\$HOME\/\.bash_profile/ ascii wide
|
|
164
|
+
$unix_path5 = "process.env.HOME" ascii wide
|
|
165
|
+
$unix_path6 = "os.homedir()" ascii wide
|
|
166
|
+
|
|
167
|
+
// macOS Launch services (specific paths)
|
|
168
|
+
$mac1 = "/Library/LaunchAgents" ascii wide
|
|
169
|
+
$mac2 = "/Library/LaunchDaemons" ascii wide
|
|
170
|
+
$mac3 = "~/Library/LaunchAgents" ascii wide
|
|
171
|
+
|
|
172
|
+
// Crontab manipulation (require command)
|
|
173
|
+
$cron1 = "crontab -" ascii wide
|
|
174
|
+
$cron2 = /crontab\s+(--|-e|-l|-r)/ ascii wide
|
|
175
|
+
|
|
176
|
+
// Windows registry persistence (require full path)
|
|
177
|
+
$win_reg1 = "CurrentVersion\\Run" ascii wide
|
|
178
|
+
$win_reg2 = "CurrentVersion\\RunOnce" ascii wide
|
|
179
|
+
$win_reg3 = "HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" ascii wide nocase
|
|
180
|
+
$win_reg4 = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" ascii wide nocase
|
|
181
|
+
|
|
182
|
+
// Windows scheduled tasks (require schtasks command)
|
|
183
|
+
$win_sched1 = /schtasks\s+\/create/i ascii wide
|
|
184
|
+
$win_sched2 = /schtasks\s+\/change/i ascii wide
|
|
185
|
+
|
|
186
|
+
// Write operations with shell config context
|
|
187
|
+
$write_shell = /write(File|FileSync)\s*\([^)]*\.(bashrc|zshrc|profile|bash_profile)/ ascii wide
|
|
188
|
+
|
|
189
|
+
condition:
|
|
190
|
+
// Unix: home path + shell config reference
|
|
191
|
+
((any of ($unix_path*)) and any of ($unix_path1, $unix_path2, $unix_path3, $unix_path4)) or
|
|
192
|
+
// macOS Launch services
|
|
193
|
+
any of ($mac*) or
|
|
194
|
+
// Crontab commands
|
|
195
|
+
any of ($cron*) or
|
|
196
|
+
// Windows registry persistence paths
|
|
197
|
+
any of ($win_reg*) or
|
|
198
|
+
// Windows scheduled task creation
|
|
199
|
+
any of ($win_sched*) or
|
|
200
|
+
// Direct write to shell config
|
|
201
|
+
$write_shell
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
rule MAL_JS_Self_Propagation_Publish_Jan25 {
|
|
205
|
+
meta:
|
|
206
|
+
description = "Detects self-propagation worm pattern that accesses publish tokens and runs publish commands"
|
|
207
|
+
severity = "critical"
|
|
208
|
+
score = 95
|
|
209
|
+
author = "vsix-audit"
|
|
210
|
+
date = "2025-01-29"
|
|
211
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
212
|
+
|
|
213
|
+
strings:
|
|
214
|
+
// Credential access
|
|
215
|
+
$cred1 = ".npmrc" ascii wide
|
|
216
|
+
$cred2 = "NPM_TOKEN" ascii wide
|
|
217
|
+
$cred3 = "OPENVSX_TOKEN" ascii wide
|
|
218
|
+
$cred4 = "VSCE_PAT" ascii wide
|
|
219
|
+
|
|
220
|
+
// Publish commands
|
|
221
|
+
$pub1 = "npm publish" ascii wide
|
|
222
|
+
$pub2 = "vsce publish" ascii wide
|
|
223
|
+
$pub3 = "ovsx publish" ascii wide
|
|
224
|
+
$pub4 = "yarn publish" ascii wide
|
|
225
|
+
|
|
226
|
+
condition:
|
|
227
|
+
any of ($cred*) and any of ($pub*)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
rule MAL_JS_Supply_Chain_Install_Jan25 {
|
|
231
|
+
meta:
|
|
232
|
+
description = "Detects supply chain attack that runs malicious commands during npm package lifecycle hooks"
|
|
233
|
+
severity = "high"
|
|
234
|
+
score = 85
|
|
235
|
+
author = "vsix-audit"
|
|
236
|
+
date = "2025-01-29"
|
|
237
|
+
|
|
238
|
+
strings:
|
|
239
|
+
// Lifecycle script indicators (in package.json context)
|
|
240
|
+
$script1 = "preinstall" ascii wide
|
|
241
|
+
$script2 = "postinstall" ascii wide
|
|
242
|
+
$script3 = "prepublish" ascii wide
|
|
243
|
+
|
|
244
|
+
// System info gathering
|
|
245
|
+
$sys1 = "os.homedir" ascii wide
|
|
246
|
+
$sys2 = "os.userInfo" ascii wide
|
|
247
|
+
$sys3 = "os.hostname" ascii wide
|
|
248
|
+
$sys4 = "process.env.HOME" ascii wide
|
|
249
|
+
$sys5 = "process.env.USER" ascii wide
|
|
250
|
+
|
|
251
|
+
// Network beacon
|
|
252
|
+
$net1 = "fetch(" ascii wide
|
|
253
|
+
$net2 = "axios" ascii wide
|
|
254
|
+
$net3 = "https.request" ascii wide
|
|
255
|
+
|
|
256
|
+
condition:
|
|
257
|
+
any of ($script*) and any of ($sys*) and any of ($net*)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
rule STEALER_JS_Crypto_Wallet_Jan25 {
|
|
261
|
+
meta:
|
|
262
|
+
description = "Detects cryptocurrency stealer that accesses wallet directories, keys, or seed phrases and exfiltrates"
|
|
263
|
+
severity = "high"
|
|
264
|
+
score = 85
|
|
265
|
+
author = "vsix-audit"
|
|
266
|
+
date = "2025-01-29"
|
|
267
|
+
|
|
268
|
+
strings:
|
|
269
|
+
// Wallet directory paths (more specific than just wallet names)
|
|
270
|
+
$wallet_path1 = ".config/solana" ascii wide
|
|
271
|
+
$wallet_path2 = "AppData\\Roaming\\Ethereum" ascii wide
|
|
272
|
+
$wallet_path3 = "AppData\\Local\\Exodus" ascii wide
|
|
273
|
+
$wallet_path4 = "AppData\\Local\\Phantom" ascii wide
|
|
274
|
+
$wallet_path5 = "Library/Application Support/Exodus" ascii wide
|
|
275
|
+
$wallet_path6 = ".ethereum/keystore" ascii wide
|
|
276
|
+
$wallet_path7 = "wallet.dat" ascii wide
|
|
277
|
+
|
|
278
|
+
// Browser extension wallet paths
|
|
279
|
+
$ext_metamask = "nkbihfbeogaeaoehlefnkodbefgpgknn" ascii wide // MetaMask extension ID
|
|
280
|
+
$ext_phantom = "bfnaelmomeimhlpmgjnjophhpkkoljpa" ascii wide // Phantom extension ID
|
|
281
|
+
|
|
282
|
+
// Seed phrase / key extraction patterns (specific to crypto)
|
|
283
|
+
$key_mnemonic = "mnemonic" ascii wide nocase
|
|
284
|
+
$key_seedphrase = "seedPhrase" ascii wide
|
|
285
|
+
$key_privatekey = "privateKey" ascii wide
|
|
286
|
+
$key_secretkey = "secretKey" ascii wide
|
|
287
|
+
|
|
288
|
+
// File read patterns targeting wallet files
|
|
289
|
+
$read_wallet = /readFile[^)]*wallet/i ascii wide
|
|
290
|
+
$read_keystore = /readFile[^)]*keystore/i ascii wide
|
|
291
|
+
|
|
292
|
+
// High-confidence exfil (known bad destinations)
|
|
293
|
+
$exfil_discord = "discord.com/api/webhooks" ascii wide
|
|
294
|
+
$exfil_telegram = "api.telegram.org" ascii wide
|
|
295
|
+
|
|
296
|
+
condition:
|
|
297
|
+
// Wallet paths + seed/key extraction
|
|
298
|
+
(any of ($wallet_path*, $ext_*) and any of ($key_*)) or
|
|
299
|
+
// Wallet file reads + known bad exfil
|
|
300
|
+
(any of ($read_wallet, $read_keystore) and any of ($exfil_discord, $exfil_telegram)) or
|
|
301
|
+
// Wallet paths + known bad exfil
|
|
302
|
+
(any of ($wallet_path*, $ext_*) and any of ($exfil_discord, $exfil_telegram))
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
rule MAL_JS_GlassWorm_Extension_Modification_Jan25 {
|
|
306
|
+
meta:
|
|
307
|
+
description = "Detects GlassWorm-style attack that modifies other VS Code extensions to inject malicious code"
|
|
308
|
+
severity = "critical"
|
|
309
|
+
score = 95
|
|
310
|
+
author = "vsix-audit"
|
|
311
|
+
date = "2025-01-29"
|
|
312
|
+
reference = "https://www.koi.security/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace"
|
|
313
|
+
|
|
314
|
+
strings:
|
|
315
|
+
// Extension paths
|
|
316
|
+
$path1 = ".vscode/extensions" ascii wide
|
|
317
|
+
$path2 = ".vscode-server/extensions" ascii wide
|
|
318
|
+
$path3 = "extensions/" ascii wide
|
|
319
|
+
|
|
320
|
+
// File modification
|
|
321
|
+
$mod1 = "writeFileSync" ascii wide
|
|
322
|
+
$mod2 = "writeFile" ascii wide
|
|
323
|
+
|
|
324
|
+
// Extension files
|
|
325
|
+
$file1 = "extension.js" ascii wide
|
|
326
|
+
$file2 = "package.json" ascii wide
|
|
327
|
+
$file3 = ".vsix" ascii wide
|
|
328
|
+
|
|
329
|
+
condition:
|
|
330
|
+
any of ($path*) and any of ($mod*) and any of ($file*)
|
|
331
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/*
|
|
2
|
+
JavaScript Obfuscation Pattern Detection
|
|
3
|
+
Detects common obfuscation techniques used to hide malicious code
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
rule SUSP_JS_Obfuscator_Hex_Vars_Jan25 {
|
|
7
|
+
meta:
|
|
8
|
+
description = "Detects javascript-obfuscator tool signature with _0x prefixed hexadecimal variable names"
|
|
9
|
+
severity = "high"
|
|
10
|
+
score = 80
|
|
11
|
+
author = "vsix-audit"
|
|
12
|
+
date = "2025-01-29"
|
|
13
|
+
|
|
14
|
+
strings:
|
|
15
|
+
// _0x followed by 4+ hex chars - signature of javascript-obfuscator
|
|
16
|
+
$hex_var = /_0x[a-fA-F0-9]{4,}/ ascii wide
|
|
17
|
+
|
|
18
|
+
condition:
|
|
19
|
+
#hex_var >= 5
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
rule SUSP_JS_FromCharCode_Chain_Jan25 {
|
|
23
|
+
meta:
|
|
24
|
+
description = "Detects String.fromCharCode with many arguments used to hide string content from static analysis"
|
|
25
|
+
severity = "high"
|
|
26
|
+
score = 75
|
|
27
|
+
author = "vsix-audit"
|
|
28
|
+
date = "2025-01-29"
|
|
29
|
+
|
|
30
|
+
strings:
|
|
31
|
+
// fromCharCode with 5+ comma-separated numbers
|
|
32
|
+
$charcode = /String\.fromCharCode\s*\(\s*(\d+\s*,\s*){5,}/ ascii wide
|
|
33
|
+
|
|
34
|
+
condition:
|
|
35
|
+
$charcode
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
rule SUSP_JS_Hex_Escape_Chain_Jan25 {
|
|
39
|
+
meta:
|
|
40
|
+
description = "Detects 10+ consecutive hex escape sequences (\\xNN) indicating obfuscated string content"
|
|
41
|
+
severity = "medium"
|
|
42
|
+
score = 60
|
|
43
|
+
author = "vsix-audit"
|
|
44
|
+
date = "2025-01-29"
|
|
45
|
+
|
|
46
|
+
strings:
|
|
47
|
+
// Consecutive hex escape pairs - provides 8-byte atoms for Aho-Corasick
|
|
48
|
+
// Each matches 2 consecutive \xNN patterns, requiring 5+ matches = 10+ escapes
|
|
49
|
+
$h1 = /\\x[0-9a-fA-F]{2}\\x[0-9a-fA-F]{2}/ ascii wide
|
|
50
|
+
|
|
51
|
+
condition:
|
|
52
|
+
#h1 >= 5
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
rule SUSP_JS_Decimal_Byte_Array_Jan25 {
|
|
56
|
+
meta:
|
|
57
|
+
description = "Detects large array of 20+ decimal byte values likely containing encoded payload data"
|
|
58
|
+
severity = "medium"
|
|
59
|
+
score = 55
|
|
60
|
+
author = "vsix-audit"
|
|
61
|
+
date = "2025-01-29"
|
|
62
|
+
|
|
63
|
+
strings:
|
|
64
|
+
// Comma-separated number patterns (4-byte atoms)
|
|
65
|
+
// Matches ", NN," patterns - 20+ of these indicates byte array
|
|
66
|
+
$num = /,\s?\d{1,3},/ ascii wide
|
|
67
|
+
|
|
68
|
+
// Array opener with number
|
|
69
|
+
$arr_open = /\[\d{1,3},/ ascii wide
|
|
70
|
+
|
|
71
|
+
condition:
|
|
72
|
+
$arr_open and #num >= 19
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
rule SUSP_JS_Bracket_Notation_Chain_Jan25 {
|
|
76
|
+
meta:
|
|
77
|
+
description = "Detects long bracket notation property chains used to hide method calls from static analysis"
|
|
78
|
+
severity = "medium"
|
|
79
|
+
score = 65
|
|
80
|
+
author = "vsix-audit"
|
|
81
|
+
date = "2025-01-29"
|
|
82
|
+
|
|
83
|
+
strings:
|
|
84
|
+
// 4+ consecutive bracket notation accesses
|
|
85
|
+
$bracket_chain = /\[\s*['"][a-zA-Z]+['"]\s*\](\s*\[\s*['"][a-zA-Z]+['"]\s*\]){3,}/ ascii wide
|
|
86
|
+
|
|
87
|
+
condition:
|
|
88
|
+
$bracket_chain
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
rule SUSP_JS_String_Array_Rotation_Jan25 {
|
|
92
|
+
meta:
|
|
93
|
+
description = "Detects javascript-obfuscator string table pattern with large array and hex variable names"
|
|
94
|
+
severity = "medium"
|
|
95
|
+
score = 55
|
|
96
|
+
author = "vsix-audit"
|
|
97
|
+
date = "2025-01-29"
|
|
98
|
+
|
|
99
|
+
strings:
|
|
100
|
+
// Literal anchors for string array separators (4-byte atoms)
|
|
101
|
+
$sep1 = "','" ascii wide
|
|
102
|
+
$sep2 = "\",\"" ascii wide
|
|
103
|
+
$sep3 = "', '" ascii wide
|
|
104
|
+
$sep4 = "\", \"" ascii wide
|
|
105
|
+
|
|
106
|
+
// Array assignment patterns
|
|
107
|
+
$arr1 = "=['" ascii wide
|
|
108
|
+
$arr2 = "=[\"" ascii wide
|
|
109
|
+
$arr3 = "= ['" ascii wide
|
|
110
|
+
$arr4 = "= [\"" ascii wide
|
|
111
|
+
|
|
112
|
+
// javascript-obfuscator hex variable (bounded to reduce backtracking)
|
|
113
|
+
$obf_hex_var = /_0x[a-fA-F0-9]{4,8}/ ascii wide
|
|
114
|
+
|
|
115
|
+
condition:
|
|
116
|
+
// Require separators + array assignment + multiple hex vars
|
|
117
|
+
(2 of ($sep*)) and (1 of ($arr*)) and #obf_hex_var >= 3
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
rule SUSP_JS_Obfuscation_Eval_Jan25 {
|
|
121
|
+
meta:
|
|
122
|
+
description = "Detects obfuscation patterns like hex vars or fromCharCode combined with eval execution"
|
|
123
|
+
severity = "critical"
|
|
124
|
+
score = 95
|
|
125
|
+
author = "vsix-audit"
|
|
126
|
+
date = "2025-01-29"
|
|
127
|
+
|
|
128
|
+
strings:
|
|
129
|
+
// Obfuscation indicators
|
|
130
|
+
$obf1 = /_0x[a-fA-F0-9]{4,}/ ascii wide
|
|
131
|
+
$obf2 = /\\x[a-fA-F0-9]{2}/ ascii wide
|
|
132
|
+
$obf3 = "String.fromCharCode" ascii wide
|
|
133
|
+
|
|
134
|
+
// Eval patterns
|
|
135
|
+
$eval1 = "eval(" ascii wide
|
|
136
|
+
$eval2 = "new Function(" ascii wide
|
|
137
|
+
|
|
138
|
+
condition:
|
|
139
|
+
any of ($obf*) and any of ($eval*)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
rule SUSP_JS_Packer_Dean_Edwards_Jan25 {
|
|
143
|
+
meta:
|
|
144
|
+
description = "Detects Dean Edwards style JavaScript packer using eval(function(p,a,c,k,e pattern"
|
|
145
|
+
severity = "high"
|
|
146
|
+
score = 85
|
|
147
|
+
author = "vsix-audit"
|
|
148
|
+
date = "2025-01-29"
|
|
149
|
+
|
|
150
|
+
strings:
|
|
151
|
+
// Common packer patterns
|
|
152
|
+
$packer1 = "eval(function(p,a,c,k,e," ascii wide
|
|
153
|
+
$packer2 = /}\s*\(\s*['"][^'"]{100,}['"]/ ascii wide
|
|
154
|
+
$packer3 = ".split('|')" ascii wide
|
|
155
|
+
|
|
156
|
+
condition:
|
|
157
|
+
$packer1 or ($packer2 and $packer3)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
rule SUSP_JS_JJEncode_Jan25 {
|
|
161
|
+
meta:
|
|
162
|
+
description = "Detects JJEncode JavaScript obfuscation using $=~[] and $$$ patterns to hide code"
|
|
163
|
+
severity = "high"
|
|
164
|
+
score = 90
|
|
165
|
+
author = "vsix-audit"
|
|
166
|
+
date = "2025-01-29"
|
|
167
|
+
|
|
168
|
+
strings:
|
|
169
|
+
$jj1 = "$=~[]" ascii wide
|
|
170
|
+
$jj2 = "_=~[]" ascii wide
|
|
171
|
+
$jj3 = "$$$$" ascii wide
|
|
172
|
+
|
|
173
|
+
condition:
|
|
174
|
+
// Require 2+ patterns to avoid FPs on bundled code with isolated patterns
|
|
175
|
+
2 of them
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
rule SUSP_JS_AAEncode_Jan25 {
|
|
179
|
+
meta:
|
|
180
|
+
description = "Detects AAEncode JavaScript obfuscation using emoticon-based encoding patterns"
|
|
181
|
+
severity = "high"
|
|
182
|
+
score = 85
|
|
183
|
+
author = "vsix-audit"
|
|
184
|
+
date = "2025-01-29"
|
|
185
|
+
|
|
186
|
+
strings:
|
|
187
|
+
$aa1 = /\(\s*!\s*\[\s*\]\s*\+\s*""\s*\)/ ascii wide
|
|
188
|
+
$aa2 = /\[\s*\+\s*!\s*\+\s*\[\s*\]\s*\]/ ascii wide
|
|
189
|
+
|
|
190
|
+
condition:
|
|
191
|
+
#aa1 > 3 or #aa2 > 3
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
rule SUSP_JS_JSFuck_Jan25 {
|
|
195
|
+
meta:
|
|
196
|
+
description = "Detects JSFuck obfuscation encoding JavaScript using only []()!+ characters"
|
|
197
|
+
severity = "critical"
|
|
198
|
+
score = 95
|
|
199
|
+
author = "vsix-audit"
|
|
200
|
+
date = "2025-01-29"
|
|
201
|
+
|
|
202
|
+
strings:
|
|
203
|
+
// Long sequences of only these characters
|
|
204
|
+
$jsfuck = /[\[\]\(\)!\+]{50,}/ ascii wide
|
|
205
|
+
|
|
206
|
+
condition:
|
|
207
|
+
$jsfuck
|
|
208
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/*
|
|
2
|
+
PowerShell Attack Detection
|
|
3
|
+
Detects malicious PowerShell patterns commonly used in VS Code extension malware
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
rule SUSP_PS_Hidden_Window_Jan25 {
|
|
7
|
+
meta:
|
|
8
|
+
description = "Detects PowerShell execution with hidden window flag to avoid user detection"
|
|
9
|
+
severity = "critical"
|
|
10
|
+
score = 90
|
|
11
|
+
author = "vsix-audit"
|
|
12
|
+
date = "2025-01-29"
|
|
13
|
+
|
|
14
|
+
strings:
|
|
15
|
+
$hidden1 = "-WindowStyle Hidden" ascii wide nocase
|
|
16
|
+
$hidden2 = "-w hidden" ascii wide nocase
|
|
17
|
+
$hidden3 = "-windowstyle h" ascii wide nocase
|
|
18
|
+
|
|
19
|
+
$ps1 = "powershell" ascii wide nocase
|
|
20
|
+
$ps2 = "pwsh" ascii wide nocase
|
|
21
|
+
|
|
22
|
+
condition:
|
|
23
|
+
any of ($ps*) and any of ($hidden*)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
rule LOADER_PS_Download_Execute_Jan25 {
|
|
27
|
+
meta:
|
|
28
|
+
description = "Detects PowerShell download and execute cradle using IEX with Invoke-WebRequest or WebClient"
|
|
29
|
+
severity = "critical"
|
|
30
|
+
score = 95
|
|
31
|
+
author = "vsix-audit"
|
|
32
|
+
date = "2025-01-29"
|
|
33
|
+
|
|
34
|
+
strings:
|
|
35
|
+
// Require PowerShell context
|
|
36
|
+
$ps1 = "powershell" ascii wide nocase
|
|
37
|
+
$ps2 = "pwsh" ascii wide nocase
|
|
38
|
+
|
|
39
|
+
// Direct piped IEX patterns (most malicious pattern)
|
|
40
|
+
// These match actual PowerShell IEX cradles, not random JS with curl/iex strings
|
|
41
|
+
$iex_pipe1 = /\|\s*(iex|Invoke-Expression)/i ascii wide
|
|
42
|
+
$iex_pipe2 = /(irm|iwr|Invoke-RestMethod|Invoke-WebRequest)[^;]{0,80}\|\s*(iex|Invoke-Expression)/i ascii wide
|
|
43
|
+
|
|
44
|
+
// .NET WebClient download+execute (classic PowerShell dropper)
|
|
45
|
+
$webclient1 = "Net.WebClient" ascii wide nocase
|
|
46
|
+
$webclient2 = "DownloadString" ascii wide nocase
|
|
47
|
+
$webclient3 = "DownloadFile" ascii wide nocase
|
|
48
|
+
|
|
49
|
+
// Full form Invoke-Expression
|
|
50
|
+
$iex_full = "Invoke-Expression" ascii wide nocase
|
|
51
|
+
|
|
52
|
+
condition:
|
|
53
|
+
// Either: PowerShell context with IEX pipe patterns
|
|
54
|
+
(any of ($ps*) and any of ($iex_pipe*)) or
|
|
55
|
+
// Or: .NET WebClient patterns with Invoke-Expression (no PS context needed)
|
|
56
|
+
(any of ($webclient*) and $iex_full)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
rule SUSP_PS_Encoded_Command_Jan25 {
|
|
60
|
+
meta:
|
|
61
|
+
description = "Detects PowerShell with base64 encoded command flag used to hide malicious payload"
|
|
62
|
+
severity = "high"
|
|
63
|
+
score = 85
|
|
64
|
+
author = "vsix-audit"
|
|
65
|
+
date = "2025-01-29"
|
|
66
|
+
|
|
67
|
+
strings:
|
|
68
|
+
$enc1 = "-enc " ascii wide nocase
|
|
69
|
+
$enc2 = "-EncodedCommand" ascii wide nocase
|
|
70
|
+
$enc3 = "-ec " ascii wide nocase
|
|
71
|
+
|
|
72
|
+
$ps1 = "powershell" ascii wide nocase
|
|
73
|
+
$ps2 = "pwsh" ascii wide nocase
|
|
74
|
+
|
|
75
|
+
condition:
|
|
76
|
+
any of ($ps*) and any of ($enc*)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
rule SUSP_PS_Bypass_Policy_Jan25 {
|
|
80
|
+
meta:
|
|
81
|
+
description = "Detects PowerShell execution policy bypass used to run unsigned or restricted scripts"
|
|
82
|
+
severity = "high"
|
|
83
|
+
score = 80
|
|
84
|
+
author = "vsix-audit"
|
|
85
|
+
date = "2025-01-29"
|
|
86
|
+
|
|
87
|
+
strings:
|
|
88
|
+
$bypass1 = "-ExecutionPolicy Bypass" ascii wide nocase
|
|
89
|
+
$bypass2 = "-ep bypass" ascii wide nocase
|
|
90
|
+
$bypass3 = "-exec bypass" ascii wide nocase
|
|
91
|
+
$bypass4 = "Set-ExecutionPolicy" ascii wide nocase
|
|
92
|
+
|
|
93
|
+
$ps1 = "powershell" ascii wide nocase
|
|
94
|
+
$ps2 = "pwsh" ascii wide nocase
|
|
95
|
+
|
|
96
|
+
condition:
|
|
97
|
+
any of ($ps*) and any of ($bypass*)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
rule SUSP_PS_AMSI_Bypass_Jan25 {
|
|
101
|
+
meta:
|
|
102
|
+
description = "Detects attempt to bypass Windows AMSI (Anti-Malware Scan Interface) for evasion"
|
|
103
|
+
severity = "critical"
|
|
104
|
+
score = 95
|
|
105
|
+
author = "vsix-audit"
|
|
106
|
+
date = "2025-01-29"
|
|
107
|
+
|
|
108
|
+
strings:
|
|
109
|
+
$amsi1 = "AmsiUtils" ascii wide nocase
|
|
110
|
+
$amsi2 = "amsiInitFailed" ascii wide nocase
|
|
111
|
+
$amsi3 = "AmsiScanBuffer" ascii wide nocase
|
|
112
|
+
$amsi4 = "[Ref].Assembly.GetType" ascii wide
|
|
113
|
+
|
|
114
|
+
condition:
|
|
115
|
+
any of them
|
|
116
|
+
}
|