@trailofbits/vsix-audit 0.1.3 → 0.2.1
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/README.md +9 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +9 -242
- package/dist/cli.js.map +1 -1
- package/dist/formatters.d.ts +63 -0
- package/dist/formatters.d.ts.map +1 -0
- package/dist/formatters.js +268 -0
- package/dist/formatters.js.map +1 -0
- package/dist/scanner/bundler.d.ts +1 -2
- package/dist/scanner/bundler.d.ts.map +1 -1
- package/dist/scanner/bundler.js +12 -9
- package/dist/scanner/bundler.js.map +1 -1
- package/dist/scanner/cache.d.ts +10 -0
- package/dist/scanner/cache.d.ts.map +1 -1
- package/dist/scanner/cache.js +29 -1
- package/dist/scanner/cache.js.map +1 -1
- package/dist/scanner/capabilities.d.ts.map +1 -1
- package/dist/scanner/capabilities.js +26 -18
- package/dist/scanner/capabilities.js.map +1 -1
- package/dist/scanner/checks/ast.d.ts.map +1 -1
- package/dist/scanner/checks/ast.js +21 -41
- package/dist/scanner/checks/ast.js.map +1 -1
- package/dist/scanner/checks/ioc.d.ts +1 -0
- package/dist/scanner/checks/ioc.d.ts.map +1 -1
- package/dist/scanner/checks/ioc.js +60 -8
- package/dist/scanner/checks/ioc.js.map +1 -1
- package/dist/scanner/checks/ioc.test.js +175 -1
- package/dist/scanner/checks/ioc.test.js.map +1 -1
- package/dist/scanner/checks/obfuscation.d.ts.map +1 -1
- package/dist/scanner/checks/obfuscation.js +11 -12
- package/dist/scanner/checks/obfuscation.js.map +1 -1
- package/dist/scanner/checks/package.d.ts.map +1 -1
- package/dist/scanner/checks/package.js +15 -1
- package/dist/scanner/checks/package.js.map +1 -1
- package/dist/scanner/checks/package.test.js +5 -1
- package/dist/scanner/checks/package.test.js.map +1 -1
- package/dist/scanner/checks/telemetry.d.ts.map +1 -1
- package/dist/scanner/checks/telemetry.js +12 -29
- package/dist/scanner/checks/telemetry.js.map +1 -1
- package/dist/scanner/checks/telemetry.test.js +1 -0
- package/dist/scanner/checks/telemetry.test.js.map +1 -1
- package/dist/scanner/checks/yara.d.ts +2 -5
- package/dist/scanner/checks/yara.d.ts.map +1 -1
- package/dist/scanner/checks/yara.js +131 -68
- package/dist/scanner/checks/yara.js.map +1 -1
- package/dist/scanner/checks/yara.test.js +40 -10
- package/dist/scanner/checks/yara.test.js.map +1 -1
- package/dist/scanner/download.d.ts +0 -5
- package/dist/scanner/download.d.ts.map +1 -1
- package/dist/scanner/download.js +94 -86
- package/dist/scanner/download.js.map +1 -1
- package/dist/scanner/download.test.js +1 -16
- package/dist/scanner/download.test.js.map +1 -1
- package/dist/scanner/index.d.ts +4 -3
- package/dist/scanner/index.d.ts.map +1 -1
- package/dist/scanner/index.js +79 -58
- package/dist/scanner/index.js.map +1 -1
- package/dist/scanner/loaders/zoo.d.ts.map +1 -1
- package/dist/scanner/loaders/zoo.js +3 -1
- package/dist/scanner/loaders/zoo.js.map +1 -1
- package/dist/scanner/types.d.ts +39 -30
- package/dist/scanner/types.d.ts.map +1 -1
- package/dist/scanner/types.js +1 -1
- package/dist/scanner/types.js.map +1 -1
- package/dist/scanner/utils.d.ts +26 -4
- package/dist/scanner/utils.d.ts.map +1 -1
- package/dist/scanner/utils.js +59 -13
- package/dist/scanner/utils.js.map +1 -1
- package/dist/scanner/vsix.d.ts +6 -0
- package/dist/scanner/vsix.d.ts.map +1 -1
- package/dist/scanner/vsix.js +60 -24
- package/dist/scanner/vsix.js.map +1 -1
- package/dist/scanner/vsix.test.js +240 -3
- package/dist/scanner/vsix.test.js.map +1 -1
- package/package.json +1 -1
- package/zoo/blocklist/extensions.json +609 -3
- package/zoo/iocs/c2-domains.txt +10 -0
- package/zoo/iocs/c2-ips.txt +7 -0
- package/zoo/iocs/github-c2.txt +11 -0
- package/zoo/iocs/hashes.txt +6 -0
- package/zoo/iocs/wallets.txt +2 -5
- package/zoo/signatures/yara/blockchain_c2_extended.yar +57 -0
- package/zoo/signatures/yara/native_addon_loader.yar +71 -0
- package/zoo/signatures/yara/persistence_macos.yar +118 -0
- package/zoo/signatures/yara/rmm_tool_delivery.yar +106 -0
package/zoo/iocs/hashes.txt
CHANGED
|
@@ -40,6 +40,12 @@ bb68992f6aa2d3f316322e88d9e71491a38e95fd3a27f48084c66b9c210bd17d # GlassWorm -
|
|
|
40
40
|
68e5fb92a7d7d182306a025010c77ae2cd89c39031cced13f9686a9f34671041 # GlassWorm - f_ex86.node.decoded (Rust DLL, pre-decryption)
|
|
41
41
|
a9a6a03bd6958710aeacc2a23860a7f7f0d09497fef85fe658ac5406734061f8 # GlassWorm - priskinski.theme-allhallowseve-remake-1.0.0.vsix (ReversingLabs Dec2025)
|
|
42
42
|
|
|
43
|
+
# SnowShoNo Campaign (ScreenConnect MSI)
|
|
44
|
+
290027e4e32cf4983ccaa9811b3090c7397a3711d23e426ab144bec1167c456b # SnowShoNo - ScreenConnect MSI installer payload
|
|
45
|
+
|
|
46
|
+
# Pokemon/Cryptominer Campaign (Oct 2025)
|
|
47
|
+
f92824508a829846cebd427a073336be7b298b13691e28bde0e8c667fb0db436 # PokemonMiner - Monero miner executable (45/70 VT detections)
|
|
48
|
+
|
|
43
49
|
# Zoo samples (GitHub sources)
|
|
44
50
|
2cdaee2863396e558f17503ad290163d513acbc3c2ca2dbfa6852c2e064ca9f1 # SnowShoNo - PowerShell downloader (obfuscated)
|
|
45
51
|
6674b3505ac23b2354230d691b9e18c2dda74a66f76bb0df724286cb9b23581c # ECM3401 - Extension Attack Suite .vsix
|
package/zoo/iocs/wallets.txt
CHANGED
|
@@ -11,8 +11,5 @@
|
|
|
11
11
|
# GlassWorm Campaign - Solana Blockchain C2
|
|
12
12
|
SOL BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC # GlassWorm - Primary C2 wallet (transaction memos contain commands)
|
|
13
13
|
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# BTC 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa # Campaign - Description
|
|
17
|
-
# ETH 0x742d35Cc6634C0532925a3b844Bc9e7595f8fE42 # Campaign - Description
|
|
18
|
-
# SOL ADDRESS # Campaign - Description
|
|
14
|
+
# SleepyDuck Campaign - Ethereum Smart Contract C2
|
|
15
|
+
ETH 0xDAfb81732db454DA238e9cFC9A9Fe5fb8e34c465 # SleepyDuck - Ethereum contract storing C2 server address
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Extended Blockchain C2 Detection
|
|
3
|
+
Detects Ethereum smart contract interaction patterns used
|
|
4
|
+
for command-and-control, extending the Solana-focused
|
|
5
|
+
blockchain_c2.yar rules.
|
|
6
|
+
|
|
7
|
+
SleepyDuck campaign uses Ethereum contracts to store C2
|
|
8
|
+
server addresses, queried via ethers.js/web3.js ABI calls.
|
|
9
|
+
The contract stores the current C2 URL which the malware
|
|
10
|
+
reads to get instructions, then executes the result.
|
|
11
|
+
|
|
12
|
+
Target: JavaScript files (no `wide` needed)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
rule C2_JS_Ethereum_Contract_C2_Feb26 {
|
|
16
|
+
meta:
|
|
17
|
+
description = "Detects Ethereum contract queries combined with dynamic code execution (SleepyDuck C2 pattern)"
|
|
18
|
+
severity = "high"
|
|
19
|
+
score = 80
|
|
20
|
+
author = "vsix-audit"
|
|
21
|
+
date = "2026-02-06"
|
|
22
|
+
reference = "https://www.secureannex.com/blog/can-you-trust-your-vscode-extensions"
|
|
23
|
+
|
|
24
|
+
strings:
|
|
25
|
+
// Ethereum library imports
|
|
26
|
+
$lib1 = "ethers" ascii
|
|
27
|
+
$lib2 = "@ethersproject" ascii
|
|
28
|
+
|
|
29
|
+
// Contract interaction
|
|
30
|
+
$contract1 = "new Contract(" ascii
|
|
31
|
+
$contract2 = "getContract(" ascii
|
|
32
|
+
|
|
33
|
+
// RPC provider connection
|
|
34
|
+
$rpc1 = "JsonRpcProvider" ascii
|
|
35
|
+
$rpc2 = "InfuraProvider" ascii
|
|
36
|
+
$rpc3 = "AlchemyProvider" ascii
|
|
37
|
+
$rpc4 = "Web3Provider" ascii
|
|
38
|
+
|
|
39
|
+
// Dynamic code execution — the C2 signal
|
|
40
|
+
// child_process and new Function("return this") are too
|
|
41
|
+
// common in bundled Ethereum dev tools (webpack polyfills,
|
|
42
|
+
// compiler toolchains). Only eval() is a strong C2 signal
|
|
43
|
+
// when combined with contract interaction.
|
|
44
|
+
$exec1 = "eval(" ascii
|
|
45
|
+
|
|
46
|
+
condition:
|
|
47
|
+
any of ($lib*) and
|
|
48
|
+
any of ($contract*) and
|
|
49
|
+
any of ($rpc*) and
|
|
50
|
+
$exec1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// REMOVED: C2_JS_Blockchain_Address_Resolution_Feb26
|
|
54
|
+
// 87 FPs across 440-extension corpus. The getter patterns
|
|
55
|
+
// (.getServer, .getConfig, .getAddress) combined with
|
|
56
|
+
// Provider() + fetch() + child_process were far too generic —
|
|
57
|
+
// matched virtually any large bundled extension.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Suspicious Native Addon Loading Detection
|
|
3
|
+
Detects platform-conditional loading of .node native addons,
|
|
4
|
+
a pattern used by GlassWorm Wave 3 to load Rust implants
|
|
5
|
+
(darwin.node, os.node) that establish persistence.
|
|
6
|
+
|
|
7
|
+
Legitimate native addons exist (e.g., node-sass, sharp) but
|
|
8
|
+
they load via npm packages, not inline require with
|
|
9
|
+
platform checks and custom-named .node files.
|
|
10
|
+
|
|
11
|
+
Target: JavaScript files (no `wide` needed)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
rule SUSP_NativeAddon_Platform_Loader_Feb26 {
|
|
15
|
+
meta:
|
|
16
|
+
description = "Detects platform-conditional loading of .node native addons, a pattern used by GlassWorm for Rust implant delivery"
|
|
17
|
+
severity = "high"
|
|
18
|
+
score = 85
|
|
19
|
+
author = "vsix-audit"
|
|
20
|
+
date = "2026-02-06"
|
|
21
|
+
reference = "https://www.secureannex.com/blog/the-glass-is-half-empty"
|
|
22
|
+
|
|
23
|
+
strings:
|
|
24
|
+
// Platform detection
|
|
25
|
+
$platform1 = "os.platform()" ascii
|
|
26
|
+
$platform2 = "process.platform" ascii
|
|
27
|
+
|
|
28
|
+
// Platform value used in comparisons
|
|
29
|
+
// (must be full quoted strings to avoid short-atom issues)
|
|
30
|
+
$win = "'win32'" ascii
|
|
31
|
+
$mac = "'darwin'" ascii
|
|
32
|
+
|
|
33
|
+
// Native addon loading with relative path
|
|
34
|
+
$node_load1 = /require\s*\(\s*['"][^'"]*\.node['"]\s*\)/ ascii
|
|
35
|
+
$node_load2 = "darwin.node" ascii
|
|
36
|
+
$node_load3 = "os.node" ascii
|
|
37
|
+
$node_load4 = "win.node" ascii
|
|
38
|
+
$node_load5 = "linux.node" ascii
|
|
39
|
+
|
|
40
|
+
// The loaded addon is called with .run()
|
|
41
|
+
$run_call = ".run(" ascii
|
|
42
|
+
|
|
43
|
+
condition:
|
|
44
|
+
any of ($platform*) and
|
|
45
|
+
($win or $mac) and
|
|
46
|
+
any of ($node_load*) and
|
|
47
|
+
$run_call
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
rule SUSP_NativeAddon_Bundled_Binary_Feb26 {
|
|
51
|
+
meta:
|
|
52
|
+
description = "Detects custom-named .node file loading outside of node_modules, suggesting a bundled native binary"
|
|
53
|
+
severity = "medium"
|
|
54
|
+
score = 70
|
|
55
|
+
author = "vsix-audit"
|
|
56
|
+
date = "2026-02-06"
|
|
57
|
+
reference = "https://www.secureannex.com/blog/the-glass-is-half-empty"
|
|
58
|
+
|
|
59
|
+
strings:
|
|
60
|
+
// Require of .node files with relative paths (not from node_modules)
|
|
61
|
+
$rel_node1 = /require\s*\(\s*['"]\.\/[^'"]+\.node['"]\s*\)/ ascii
|
|
62
|
+
$rel_node2 = /require\s*\(\s*['"]\.\.\/[^'"]+\.node['"]\s*\)/ ascii
|
|
63
|
+
|
|
64
|
+
// VS Code extension activation context
|
|
65
|
+
$activate = "activate" ascii
|
|
66
|
+
$vscode = "vscode" ascii
|
|
67
|
+
|
|
68
|
+
condition:
|
|
69
|
+
any of ($rel_node*) and
|
|
70
|
+
($activate and $vscode)
|
|
71
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/*
|
|
2
|
+
macOS Persistence Detection
|
|
3
|
+
Detects LaunchAgent/LaunchDaemon persistence mechanisms
|
|
4
|
+
used by malware to survive reboots on macOS.
|
|
5
|
+
|
|
6
|
+
GlassWorm Wave 3 Rust implants write LaunchAgent plists
|
|
7
|
+
to ~/Library/LaunchAgents/ with com.apple.* naming to
|
|
8
|
+
blend in with legitimate Apple services.
|
|
9
|
+
|
|
10
|
+
Target: JavaScript files (no `wide` needed)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
rule SUSP_Mac_LaunchAgent_Feb26 {
|
|
14
|
+
meta:
|
|
15
|
+
description = "Detects LaunchAgent plist creation for macOS persistence, used by GlassWorm Rust implants"
|
|
16
|
+
severity = "high"
|
|
17
|
+
score = 85
|
|
18
|
+
author = "vsix-audit"
|
|
19
|
+
date = "2026-02-06"
|
|
20
|
+
reference = "https://www.secureannex.com/blog/the-glass-is-half-empty"
|
|
21
|
+
|
|
22
|
+
strings:
|
|
23
|
+
// LaunchAgent/LaunchDaemon paths
|
|
24
|
+
$la_path1 = "LaunchAgents" ascii
|
|
25
|
+
$la_path2 = "LaunchDaemons" ascii
|
|
26
|
+
$la_path3 = "Library/LaunchAgents" ascii
|
|
27
|
+
$la_path4 = "Library/LaunchDaemons" ascii
|
|
28
|
+
|
|
29
|
+
// Plist content patterns
|
|
30
|
+
$plist1 = "ProgramArguments" ascii
|
|
31
|
+
$plist2 = "RunAtLoad" ascii
|
|
32
|
+
$plist3 = "KeepAlive" ascii
|
|
33
|
+
$plist4 = "StartInterval" ascii
|
|
34
|
+
|
|
35
|
+
// File write operations
|
|
36
|
+
$write1 = "writeFile" ascii
|
|
37
|
+
$write2 = "writeFileSync" ascii
|
|
38
|
+
$write3 = "createWriteStream" ascii
|
|
39
|
+
|
|
40
|
+
// Or plist XML format
|
|
41
|
+
$xml1 = "<!DOCTYPE plist" ascii
|
|
42
|
+
$xml2 = "<plist version" ascii
|
|
43
|
+
|
|
44
|
+
condition:
|
|
45
|
+
any of ($la_path*) and
|
|
46
|
+
(2 of ($plist*) or any of ($xml*)) and
|
|
47
|
+
any of ($write*)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
rule SUSP_Mac_AppleDisguise_Feb26 {
|
|
51
|
+
meta:
|
|
52
|
+
description = "Detects use of com.apple.* naming for non-Apple LaunchAgent persistence (masquerading)"
|
|
53
|
+
severity = "critical"
|
|
54
|
+
score = 90
|
|
55
|
+
author = "vsix-audit"
|
|
56
|
+
date = "2026-02-06"
|
|
57
|
+
reference = "https://www.secureannex.com/blog/the-glass-is-half-empty"
|
|
58
|
+
|
|
59
|
+
strings:
|
|
60
|
+
// Apple-disguised plist labels
|
|
61
|
+
$apple_label = /com\.apple\.[a-zA-Z0-9._-]+\.plist/ ascii
|
|
62
|
+
|
|
63
|
+
// LaunchAgent context
|
|
64
|
+
$la1 = "LaunchAgents" ascii
|
|
65
|
+
$la2 = "LaunchDaemons" ascii
|
|
66
|
+
|
|
67
|
+
// Non-Apple origin evidence (JS/Node context)
|
|
68
|
+
$js1 = "require(" ascii
|
|
69
|
+
$js2 = "child_process" ascii
|
|
70
|
+
$js3 = "execSync(" ascii
|
|
71
|
+
$js4 = "writeFile" ascii
|
|
72
|
+
|
|
73
|
+
condition:
|
|
74
|
+
$apple_label and
|
|
75
|
+
any of ($la*) and
|
|
76
|
+
any of ($js*)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
rule SUSP_Mac_LoginItem_Feb26 {
|
|
80
|
+
meta:
|
|
81
|
+
description = "Detects programmatic addition of macOS Login Items for persistence"
|
|
82
|
+
severity = "medium"
|
|
83
|
+
score = 75
|
|
84
|
+
author = "vsix-audit"
|
|
85
|
+
date = "2026-02-06"
|
|
86
|
+
reference = "https://www.secureannex.com/blog/the-glass-is-half-empty"
|
|
87
|
+
|
|
88
|
+
strings:
|
|
89
|
+
// Login Items manipulation via osascript
|
|
90
|
+
$login1 = "login item" ascii nocase
|
|
91
|
+
$login2 = "LoginItems" ascii
|
|
92
|
+
$login3 = "LSSharedFileList" ascii
|
|
93
|
+
|
|
94
|
+
// osascript for AppleScript execution
|
|
95
|
+
$osa1 = "osascript" ascii
|
|
96
|
+
$osa2 = "tell application" ascii
|
|
97
|
+
|
|
98
|
+
// Open at Login
|
|
99
|
+
$open1 = "LSRegisterURL" ascii
|
|
100
|
+
$open2 = "open at login" ascii nocase
|
|
101
|
+
|
|
102
|
+
// Code execution context
|
|
103
|
+
$exec1 = "exec(" ascii
|
|
104
|
+
$exec2 = "execSync(" ascii
|
|
105
|
+
$exec3 = "child_process" ascii
|
|
106
|
+
$exec4 = "spawn(" ascii
|
|
107
|
+
|
|
108
|
+
// Exclude TextMate grammar/syntax files
|
|
109
|
+
// (contain AppleScript keywords as language tokens)
|
|
110
|
+
$fp_grammar1 = "tmLanguage" ascii
|
|
111
|
+
$fp_grammar2 = "scopeName" ascii
|
|
112
|
+
$fp_grammar3 = "repository" ascii
|
|
113
|
+
|
|
114
|
+
condition:
|
|
115
|
+
any of ($login*, $open*) and
|
|
116
|
+
(any of ($osa*) or any of ($exec*)) and
|
|
117
|
+
not 2 of ($fp_grammar*)
|
|
118
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/*
|
|
2
|
+
RMM/RAT Tool Delivery Detection
|
|
3
|
+
Detects delivery of Remote Monitoring & Management tools
|
|
4
|
+
(ScreenConnect, AnyDesk, TeamViewer) via scripted installers.
|
|
5
|
+
|
|
6
|
+
Covers the "These Vibes Are Off" campaign pattern where
|
|
7
|
+
extensions use PowerShell IEX cradles to silently install
|
|
8
|
+
ScreenConnect for persistent remote access.
|
|
9
|
+
|
|
10
|
+
Target: JavaScript files in VS Code extensions (no `wide` needed)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
rule LOADER_RMM_ScreenConnect_Delivery_Feb26 {
|
|
14
|
+
meta:
|
|
15
|
+
description = "Detects ScreenConnect (ConnectWise Control) delivery or silent installation patterns in extension code"
|
|
16
|
+
severity = "critical"
|
|
17
|
+
score = 95
|
|
18
|
+
author = "vsix-audit"
|
|
19
|
+
date = "2026-02-06"
|
|
20
|
+
reference = "https://www.secureannex.com/blog/these-vibes-are-off"
|
|
21
|
+
|
|
22
|
+
strings:
|
|
23
|
+
// ScreenConnect / ConnectWise Control identifiers
|
|
24
|
+
$sc1 = "screenconnect" ascii nocase
|
|
25
|
+
$sc2 = "ScreenConnect.Client" ascii
|
|
26
|
+
$sc3 = "ScreenConnect.WindowsClient" ascii
|
|
27
|
+
$sc4 = "connectwise" ascii nocase
|
|
28
|
+
|
|
29
|
+
// ScreenConnect relay/session URLs
|
|
30
|
+
$relay1 = /instance-[a-z0-9]+-relay\.screenconnect\.com/ ascii
|
|
31
|
+
$relay2 = /[a-z0-9]{4,30}\.screenconnect\.com/ ascii
|
|
32
|
+
|
|
33
|
+
// Script-based delivery context
|
|
34
|
+
$deliver1 = "child_process" ascii
|
|
35
|
+
$deliver2 = "exec(" ascii
|
|
36
|
+
$deliver3 = "execSync(" ascii
|
|
37
|
+
$deliver4 = "spawn(" ascii
|
|
38
|
+
$deliver5 = "powershell" ascii nocase
|
|
39
|
+
|
|
40
|
+
condition:
|
|
41
|
+
(any of ($sc*) or any of ($relay*)) and
|
|
42
|
+
any of ($deliver*)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
rule LOADER_RMM_AnyDesk_Delivery_Feb26 {
|
|
46
|
+
meta:
|
|
47
|
+
description = "Detects AnyDesk silent installation or deployment patterns in extension code"
|
|
48
|
+
severity = "critical"
|
|
49
|
+
score = 90
|
|
50
|
+
author = "vsix-audit"
|
|
51
|
+
date = "2026-02-06"
|
|
52
|
+
reference = "https://www.secureannex.com/blog/these-vibes-are-off"
|
|
53
|
+
|
|
54
|
+
strings:
|
|
55
|
+
$ad1 = "anydesk" ascii nocase
|
|
56
|
+
$ad2 = "AnyDesk.exe" ascii
|
|
57
|
+
|
|
58
|
+
// AnyDesk silent install flags
|
|
59
|
+
$install1 = "--install" ascii
|
|
60
|
+
$install2 = "--silent" ascii
|
|
61
|
+
$install3 = "--start-with-win" ascii
|
|
62
|
+
|
|
63
|
+
// AnyDesk password setting (unattended access)
|
|
64
|
+
$pwd1 = "--set-password" ascii
|
|
65
|
+
$pwd2 = "ad.anynet.pwd" ascii
|
|
66
|
+
|
|
67
|
+
// Delivery context
|
|
68
|
+
$deliver1 = "child_process" ascii
|
|
69
|
+
$deliver2 = "exec(" ascii
|
|
70
|
+
$deliver3 = "powershell" ascii nocase
|
|
71
|
+
$deliver4 = "spawn(" ascii
|
|
72
|
+
|
|
73
|
+
condition:
|
|
74
|
+
any of ($ad*) and
|
|
75
|
+
(any of ($install*) or any of ($pwd*)) and
|
|
76
|
+
any of ($deliver*)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
rule LOADER_RMM_TeamViewer_Delivery_Feb26 {
|
|
80
|
+
meta:
|
|
81
|
+
description = "Detects TeamViewer silent installation or deployment patterns in extension code"
|
|
82
|
+
severity = "critical"
|
|
83
|
+
score = 90
|
|
84
|
+
author = "vsix-audit"
|
|
85
|
+
date = "2026-02-06"
|
|
86
|
+
reference = "https://www.secureannex.com/blog/these-vibes-are-off"
|
|
87
|
+
|
|
88
|
+
strings:
|
|
89
|
+
$tv1 = "teamviewer" ascii nocase
|
|
90
|
+
$tv2 = "TeamViewer.exe" ascii
|
|
91
|
+
$tv3 = "TeamViewer_Setup" ascii
|
|
92
|
+
|
|
93
|
+
// Silent/unattended install
|
|
94
|
+
$install1 = "CUSTOMCONFIGID" ascii nocase
|
|
95
|
+
$install2 = "APITOKEN" ascii nocase
|
|
96
|
+
|
|
97
|
+
// Delivery context
|
|
98
|
+
$deliver1 = "child_process" ascii
|
|
99
|
+
$deliver2 = "exec(" ascii
|
|
100
|
+
$deliver3 = "powershell" ascii nocase
|
|
101
|
+
$deliver4 = "spawn(" ascii
|
|
102
|
+
|
|
103
|
+
condition:
|
|
104
|
+
any of ($tv*) and any of ($install*) and
|
|
105
|
+
any of ($deliver*)
|
|
106
|
+
}
|