# 设置输出编码为 UTF-8 $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 # 颜色定义 $RED = "`e[31m" $GREEN = "`e[32m" $YELLOW = "`e[33m" $BLUE = "`e[34m" $NC = "`e[0m" # 配置文件路径 $STORAGE_FILE = "$env:APPDATA\Cursor\User\globalStorage\storage.json" $BACKUP_DIR = "$env:APPDATA\Cursor\User\globalStorage\backups" # PowerShell原生方法生成随机字符串 function Generate-RandomString { param([int]$Length) $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" $result = "" for ($i = 0; $i -lt $Length; $i++) { $result += $chars[(Get-Random -Maximum $chars.Length)] } return $result } # 🔧 修改Cursor内核JS文件实现设备识别绕过(A+B混合方案 - IIFE + someValue替换) # 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名 # 方案B: IIFE运行时劫持 - 劫持crypto.randomUUID从源头拦截 function Modify-CursorJSFiles { Write-Host "" Write-Host "$BLUE🔧 [内核修改]$NC 开始修改Cursor内核JS文件实现设备识别绕过..." Write-Host "$BLUE💡 [方案]$NC 使用A+B混合方案:someValue占位符替换 + IIFE运行时劫持" Write-Host "" # Windows版Cursor应用路径 $cursorAppPath = "${env:LOCALAPPDATA}\Programs\Cursor" if (-not (Test-Path $cursorAppPath)) { # 尝试其他可能的安装路径 $alternatePaths = @( "${env:ProgramFiles}\Cursor", "${env:ProgramFiles(x86)}\Cursor", "${env:USERPROFILE}\AppData\Local\Programs\Cursor" ) foreach ($path in $alternatePaths) { if (Test-Path $path) { $cursorAppPath = $path break } } if (-not (Test-Path $cursorAppPath)) { Write-Host "$RED❌ [错误]$NC 未找到Cursor应用安装路径" Write-Host "$YELLOW💡 [提示]$NC 请确认Cursor已正确安装" return $false } } Write-Host "$GREEN✅ [发现]$NC 找到Cursor安装路径: $cursorAppPath" # 生成新的设备标识符(使用固定格式确保兼容性) $newUuid = [System.Guid]::NewGuid().ToString().ToLower() $randomBytes = New-Object byte[] 32 $rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::new() $rng.GetBytes($randomBytes) $machineId = [System.BitConverter]::ToString($randomBytes) -replace '-','' $rng.Dispose() $deviceId = [System.Guid]::NewGuid().ToString().ToLower() $randomBytes2 = New-Object byte[] 32 $rng2 = [System.Security.Cryptography.RNGCryptoServiceProvider]::new() $rng2.GetBytes($randomBytes2) $macMachineId = [System.BitConverter]::ToString($randomBytes2) -replace '-','' $rng2.Dispose() $sqmId = [System.Guid]::NewGuid().ToString().ToLower() $sessionId = [System.Guid]::NewGuid().ToString().ToLower() Write-Host "$GREEN🔑 [生成]$NC 已生成新的设备标识符" Write-Host " machineId: $($machineId.Substring(0,16))..." Write-Host " deviceId: $($deviceId.Substring(0,16))..." Write-Host " macMachineId: $($macMachineId.Substring(0,16))..." # 目标JS文件列表(Windows路径,按优先级排序) $jsFiles = @( "$cursorAppPath\resources\app\out\vs\workbench\api\node\extensionHostProcess.js", "$cursorAppPath\resources\app\out\main.js", "$cursorAppPath\resources\app\out\vs\code\node\cliProcessMain.js" ) $modifiedCount = 0 $needModification = $false # 检查是否需要修改(使用统一标记 __cursor_patched__) Write-Host "$BLUE🔍 [检查]$NC 检查JS文件修改状态..." foreach ($file in $jsFiles) { if (-not (Test-Path $file)) { Write-Host "$YELLOW⚠️ [警告]$NC 文件不存在: $(Split-Path $file -Leaf)" continue } $content = Get-Content $file -Raw -ErrorAction SilentlyContinue if ($content -and $content -match "__cursor_patched__") { Write-Host "$GREEN✅ [已修改]$NC 文件已修改: $(Split-Path $file -Leaf)" } else { Write-Host "$BLUE📝 [需要]$NC 文件需要修改: $(Split-Path $file -Leaf)" $needModification = $true } } if (-not $needModification) { Write-Host "$GREEN✅ [跳过]$NC 所有JS文件已经被修改过,无需重复操作" return $true } # 关闭Cursor进程 Write-Host "$BLUE🔄 [关闭]$NC 关闭Cursor进程以进行文件修改..." Stop-AllCursorProcesses -MaxRetries 3 -WaitSeconds 3 | Out-Null # 创建备份 $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" $backupPath = "$env:TEMP\Cursor_JS_Backup_$timestamp" Write-Host "$BLUE💾 [备份]$NC 创建Cursor JS文件备份..." try { New-Item -ItemType Directory -Path $backupPath -Force | Out-Null foreach ($file in $jsFiles) { if (Test-Path $file) { $fileName = Split-Path $file -Leaf Copy-Item $file "$backupPath\$fileName" -Force } } Write-Host "$GREEN✅ [备份]$NC 备份创建成功: $backupPath" } catch { Write-Host "$RED❌ [错误]$NC 创建备份失败: $($_.Exception.Message)" return $false } # 修改JS文件 Write-Host "$BLUE🔧 [修改]$NC 开始修改JS文件..." foreach ($file in $jsFiles) { if (-not (Test-Path $file)) { Write-Host "$YELLOW⚠️ [跳过]$NC 文件不存在: $(Split-Path $file -Leaf)" continue } Write-Host "$BLUE📝 [处理]$NC 正在处理: $(Split-Path $file -Leaf)" try { $content = Get-Content $file -Raw -Encoding UTF8 # 检查是否已经修改过(使用统一标记) if ($content -match "__cursor_patched__") { Write-Host "$GREEN✅ [跳过]$NC 文件已经被修改过" $modifiedCount++ continue } $replaced = $false # ========== 方法A: someValue占位符替换(稳定锚点) ========== # 这些字符串是固定的占位符,不会被混淆器修改,跨版本稳定 # 替换 someValue.machineId if ($content -match 'someValue\.machineId') { $content = $content -replace 'someValue\.machineId', $machineId Write-Host " $GREEN✓$NC [方案A] 替换 someValue.machineId" $replaced = $true } # 替换 someValue.macMachineId if ($content -match 'someValue\.macMachineId') { $content = $content -replace 'someValue\.macMachineId', $macMachineId Write-Host " $GREEN✓$NC [方案A] 替换 someValue.macMachineId" $replaced = $true } # 替换 someValue.devDeviceId if ($content -match 'someValue\.devDeviceId') { $content = $content -replace 'someValue\.devDeviceId', $deviceId Write-Host " $GREEN✓$NC [方案A] 替换 someValue.devDeviceId" $replaced = $true } # 替换 someValue.sqmId if ($content -match 'someValue\.sqmId') { $content = $content -replace 'someValue\.sqmId', $sqmId Write-Host " $GREEN✓$NC [方案A] 替换 someValue.sqmId" $replaced = $true } # 替换 someValue.sessionId(新增锚点) if ($content -match 'someValue\.sessionId') { $content = $content -replace 'someValue\.sessionId', $sessionId Write-Host " $GREEN✓$NC [方案A] 替换 someValue.sessionId" $replaced = $true } # ========== 方法B: IIFE运行时劫持(crypto.randomUUID) ========== # 使用IIFE包装,兼容webpack打包的bundle文件 # 在支持 require 的环境中劫持 crypto.randomUUID;在 ESM 环境中安全降级为 no-op,避免 require 抛错 $injectCode = ";(function(){/*__cursor_patched__*/var _cr=null,_os=null;if(typeof require!=='undefined'){try{_cr=require('crypto');_os=require('os');}catch(e){}}if(_cr&&_cr.randomUUID){var _orig=_cr.randomUUID;_cr.randomUUID=function(){return'$newUuid';};}if(typeof globalThis!=='undefined'){globalThis.__cursor_machine_id='$machineId';globalThis.__cursor_mac_machine_id='$macMachineId';globalThis.__cursor_dev_device_id='$deviceId';globalThis.__cursor_sqm_id='$sqmId';}if(_os&&_os.networkInterfaces){try{var _origNI=_os.networkInterfaces;_os.networkInterfaces=function(){var r=_origNI.call(_os);for(var k in r){if(r[k]){for(var i=0;i