Last active
November 25, 2025 08:20
-
-
Save LHazy/6da6a4c18483254273d126bb586d51c9 to your computer and use it in GitHub Desktop.
Shai-Hulud Supply Chain Attack で配布された悪性ファイル (bundle.js) の検索スクリプト
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # !!!注意!!!: | |
| # このスクリプトはCドライブ配下のファイル・フォルダを探索するため「システムに負荷がかかる場合があります」 | |
| # 実行は自己責任でお願いします。 | |
| # 使い方: | |
| # powershell -ExecutionPolicy Bypass -File .\Scan-Bundle.ps1 <start_directory> | |
| param( | |
| [Parameter(Mandatory = $true)] | |
| [string]$TargetDirectory | |
| ) | |
| $question = Read-Host "Do you understand that this process may put load on the system? [y/n]" | |
| if ($question -ne 'y' -and $question -ne 'Y') { | |
| Write-Host "Aborted." | |
| exit 0 | |
| } | |
| if (-not (Test-Path -Path $TargetDirectory -PathType Container)) { | |
| Write-Host "Error: please provide an existing directory as the first argument." | |
| Write-Host "Usage: .\Scan-Bundle.ps1 <start_directory>" | |
| exit 1 | |
| } | |
| $startPath = (Resolve-Path -Path $TargetDirectory).Path | |
| $foundAny = $false | |
| $matches = 0 | |
| $nodeModulesDirs = Get-ChildItem -Path $startPath -Directory -Recurse -Filter 'node_modules' -Force -ErrorAction SilentlyContinue | |
| if (-not $nodeModulesDirs) { | |
| Write-Host "No 'node_modules' directories found under: $startPath" | |
| exit 0 | |
| } | |
| $foundAny = $true | |
| foreach ($nmd in $nodeModulesDirs) { | |
| $bundleFiles = Get-ChildItem -Path $nmd.FullName -Recurse -File -Filter 'bundle.js' -ErrorAction SilentlyContinue | |
| foreach ($file in $bundleFiles) { | |
| $hasKeyword = Select-String -Path $file.FullName -Pattern 'Shai-Hulud','bb8ca5f6-4175-45d2-b042-fc9ebb8170b7' -SimpleMatch -CaseSensitive -Quiet | |
| if ($hasKeyword) { | |
| Write-Host "MATCH (v1.0): $($file.FullName)" | |
| $matches++ | |
| } | |
| } | |
| } | |
| if ($matches -eq 0) { | |
| Write-Host "No Shai Hulud v1.0 files matched." | |
| } | |
| $preinstallMatches = 0 | |
| $preinstallRegex = '"preinstall[": ]+node[ ]+setup_bun\.js' | |
| foreach ($nmd in $nodeModulesDirs) { | |
| $packageFiles = Get-ChildItem -Path $nmd.FullName -Recurse -File -Filter 'package.json' -ErrorAction SilentlyContinue | |
| foreach ($pkg in $packageFiles) { | |
| $hasPreinstall = Select-String -Path $pkg.FullName -Pattern $preinstallRegex -CaseSensitive -Quiet | |
| if ($hasPreinstall) { | |
| Write-Host "MATCH (v2.0): $($pkg.FullName)" | |
| $preinstallMatches++ | |
| } | |
| } | |
| } | |
| if ($preinstallMatches -eq 0) { | |
| Write-Host "No Shai Hulud v2.0 files matched." | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # 注意: | |
| # このスクリプトはroot配下のファイル・フォルダを探索するため「システムに負荷がかかる場合があります」 | |
| # 実行は自己責任でお願いします。 | |
| # 使い方: | |
| # 管理者権限でこのスクリプトを実行してください。 | |
| # Usage: ./scan_bundle.sh <start_directory> | |
| #set -xue | |
| read -r -p "Do you understand that this process may put load on the system? [y/n] " ans | |
| if [[ "${ans}" != "y" && "${ans}" != "Y" ]] ; then | |
| echo "Aborted." | |
| exit 0 | |
| fi | |
| if [[ $# -lt 1 || ! -d "$1" ]]; then | |
| echo "Error: please provide an existing directory as the first argument." | |
| echo "Usage: $0 <start_directory>" | |
| exit 1 | |
| fi | |
| start_dir="$1" | |
| # -------------------------------------------------------------- | |
| # 0. node_modules ディレクトリを一度だけ列挙してリスト化 | |
| # -------------------------------------------------------------- | |
| echo "Scanning for node_modules directories..." | |
| mapfile -d '' nm_list < <(find "$start_dir" -type d -name 'node_modules' -print0) | |
| if [[ ${#nm_list[@]} -eq 0 ]]; then | |
| echo "No 'node_modules' directories found under: $start_dir" | |
| exit 0 | |
| fi | |
| echo "Found ${#nm_list[@]} node_modules directories." | |
| # -------------------------------------------------------------- | |
| # 1. 各 node_modules 配下で bundle.js を検索 | |
| # -------------------------------------------------------------- | |
| matches=0 | |
| for nm_dir in "${nm_list[@]}"; do | |
| while IFS= read -r -d '' bundle_file; do | |
| if grep -Eq "Shai-Hulud|bb8ca5f6-4175-45d2-b042-fc9ebb8170b7" "$bundle_file"; then | |
| echo "MATCH (v1.0): $bundle_file" | |
| matches=$((matches+1)) | |
| fi | |
| done < <(find "$nm_dir" -type f -name 'bundle.js' -print0) | |
| done | |
| if [[ $matches -eq 0 ]]; then | |
| echo "No Shai Hulud v1.0 files matched." | |
| fi | |
| # -------------------------------------------------------------- | |
| # 2. 各 node_modules 配下で package.json を検索し preinstall を確認 | |
| # -------------------------------------------------------------- | |
| preinstall_matches=0 | |
| for nm_dir in "${nm_list[@]}"; do | |
| while IFS= read -r -d '' pkg_file; do | |
| if grep -Eq '"preinstall[": ]+node\s+setup_bun.js' "$pkg_file"; then | |
| echo "MATCH (v2.0): $pkg_file" | |
| preinstall_matches=$((preinstall_matches+1)) | |
| fi | |
| done < <(find "$nm_dir" -type f -name 'package.json' -print0) | |
| done | |
| if [[ $preinstall_matches -eq 0 ]]; then | |
| echo "No Shai Hulud v2.0 files matched." | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment