diff --git a/scripts/hook/cursor_hook.js b/scripts/hook/cursor_hook.js index bdfcdb8..9f3798b 100644 --- a/scripts/hook/cursor_hook.js +++ b/scripts/hook/cursor_hook.js @@ -110,9 +110,14 @@ var __cursor_hook_config__ = { if (process.env.CURSOR_MACHINE_ID) { ids = { machineId: process.env.CURSOR_MACHINE_ID, + // machineGuid 用于模拟注册表 MachineGuid/IOPlatformUUID + machineGuid: process.env.CURSOR_MACHINE_GUID || generateUUID(), macMachineId: process.env.CURSOR_MAC_MACHINE_ID || generateHex64(), devDeviceId: process.env.CURSOR_DEV_DEVICE_ID || generateUUID(), - sqmId: process.env.CURSOR_SQM_ID || `{${generateUUID().toUpperCase()}}` + sqmId: process.env.CURSOR_SQM_ID || `{${generateUUID().toUpperCase()}}`, + macAddress: process.env.CURSOR_MAC_ADDRESS || generateMacAddress(), + sessionId: process.env.CURSOR_SESSION_ID || generateUUID(), + firstSessionDate: process.env.CURSOR_FIRST_SESSION_DATE || new Date().toISOString() }; log('从环境变量加载 ID 配置'); return ids; @@ -123,6 +128,32 @@ var __cursor_hook_config__ = { if (fs.existsSync(configPath)) { const content = fs.readFileSync(configPath, 'utf8'); ids = JSON.parse(content); + // 补全缺失字段,保持向后兼容 + let updated = false; + if (!ids.machineGuid) { + ids.machineGuid = generateUUID(); + updated = true; + } + if (!ids.macAddress) { + ids.macAddress = generateMacAddress(); + updated = true; + } + if (!ids.sessionId) { + ids.sessionId = generateUUID(); + updated = true; + } + if (!ids.firstSessionDate) { + ids.firstSessionDate = new Date().toISOString(); + updated = true; + } + if (updated) { + try { + fs.writeFileSync(configPath, JSON.stringify(ids, null, 2), 'utf8'); + log('已补全并更新 ID 配置:', configPath); + } catch (e) { + log('补全配置文件失败:', e.message); + } + } log('从配置文件加载 ID 配置:', configPath); return ids; } @@ -133,10 +164,13 @@ var __cursor_hook_config__ = { // 生成新的 ID ids = { machineId: generateHex64(), + machineGuid: generateUUID(), macMachineId: generateHex64(), devDeviceId: generateUUID(), sqmId: `{${generateUUID().toUpperCase()}}`, macAddress: generateMacAddress(), + sessionId: generateUUID(), + firstSessionDate: new Date().toISOString(), createdAt: new Date().toISOString() }; @@ -153,6 +187,8 @@ var __cursor_hook_config__ = { // 加载 ID 配置 const __cursor_ids__ = loadOrGenerateIds(); + // 统一获取 MachineGuid,缺失时回退到 machineId 的前 36 位 + const getMachineGuid = () => __cursor_ids__.machineGuid || __cursor_ids__.machineId.substring(0, 36); log('当前 ID 配置:', __cursor_ids__); // ==================== Module Hook ==================== @@ -164,42 +200,44 @@ var __cursor_hook_config__ = { const hookedModules = new Map(); Module.prototype.require = function(id) { + // 兼容 node: 前缀 + const normalizedId = (typeof id === 'string' && id.startsWith('node:')) ? id.slice(5) : id; const result = originalRequire.apply(this, arguments); // 如果已经 Hook 过,直接返回缓存 - if (hookedModules.has(id)) { - return hookedModules.get(id); + if (hookedModules.has(normalizedId)) { + return hookedModules.get(normalizedId); } let hooked = result; // Hook child_process 模块 - if (id === 'child_process') { + if (normalizedId === 'child_process') { hooked = hookChildProcess(result); } // Hook os 模块 - else if (id === 'os') { + else if (normalizedId === 'os') { hooked = hookOs(result); } // Hook crypto 模块 - else if (id === 'crypto') { + else if (normalizedId === 'crypto') { hooked = hookCrypto(result); } // Hook @vscode/deviceid 模块 - else if (id === '@vscode/deviceid') { + else if (normalizedId === '@vscode/deviceid') { hooked = hookDeviceId(result); } // Hook @vscode/windows-registry 模块 - else if (id === '@vscode/windows-registry') { + else if (normalizedId === '@vscode/windows-registry') { hooked = hookWindowsRegistry(result); } // 缓存 Hook 结果 if (hooked !== result) { - hookedModules.set(id, hooked); - log(`已 Hook 模块: ${id}`); + hookedModules.set(normalizedId, hooked); + log(`已 Hook 模块: ${normalizedId}`); } - + return hooked; }; @@ -207,6 +245,7 @@ var __cursor_hook_config__ = { function hookChildProcess(cp) { const originalExecSync = cp.execSync; + const originalExecFileSync = cp.execFileSync; cp.execSync = function(command, options) { const cmdStr = String(command).toLowerCase(); @@ -215,13 +254,13 @@ var __cursor_hook_config__ = { if (cmdStr.includes('reg') && cmdStr.includes('machineguid')) { log('拦截 MachineGuid 查询'); // 返回格式化的注册表输出 - return Buffer.from(`\r\n MachineGuid REG_SZ ${__cursor_ids__.machineId.substring(0, 36)}\r\n`); + return Buffer.from(`\r\n MachineGuid REG_SZ ${getMachineGuid()}\r\n`); } // 拦截 ioreg 命令 (macOS) if (cmdStr.includes('ioreg') && cmdStr.includes('ioplatformexpertdevice')) { log('拦截 IOPlatformUUID 查询'); - return Buffer.from(`"IOPlatformUUID" = "${__cursor_ids__.machineId.substring(0, 36).toUpperCase()}"`); + return Buffer.from(`"IOPlatformUUID" = "${getMachineGuid().toUpperCase()}"`); } // 拦截 machine-id 读取 (Linux) @@ -233,6 +272,30 @@ var __cursor_hook_config__ = { return originalExecSync.apply(this, arguments); }; + // 兼容 execFileSync(部分版本会直接调用可执行文件) + if (typeof originalExecFileSync === 'function') { + cp.execFileSync = function(file, args, options) { + const cmdStr = [file].concat(args || []).join(' ').toLowerCase(); + + if (cmdStr.includes('reg') && cmdStr.includes('machineguid')) { + log('拦截 MachineGuid 查询(execFileSync)'); + return Buffer.from(`\r\n MachineGuid REG_SZ ${getMachineGuid()}\r\n`); + } + + if (cmdStr.includes('ioreg') && cmdStr.includes('ioplatformexpertdevice')) { + log('拦截 IOPlatformUUID 查询(execFileSync)'); + return Buffer.from(`"IOPlatformUUID" = "${getMachineGuid().toUpperCase()}"`); + } + + if (cmdStr.includes('machine-id') || cmdStr.includes('hostname')) { + log('拦截 machine-id 查询(execFileSync)'); + return Buffer.from(__cursor_ids__.machineId.substring(0, 32)); + } + + return originalExecFileSync.apply(this, arguments); + }; + } + return cp; } @@ -347,7 +410,7 @@ var __cursor_hook_config__ = { // 拦截 MachineGuid 读取 if (name === 'MachineGuid' || path.includes('Cryptography')) { log('拦截注册表 MachineGuid 读取'); - return __cursor_ids__.machineId.substring(0, 36); + return getMachineGuid(); } return originalGetStringRegKey?.apply(this, arguments) || ''; } @@ -439,7 +502,7 @@ var __cursor_hook_config__ = { } if (name === 'MachineGuid' || path?.includes('Cryptography')) { log('动态导入: 拦截 MachineGuid'); - return __cursor_ids__.machineId.substring(0, 36); + return getMachineGuid(); } return originalGetStringRegKey?.apply(this, arguments) || ''; } @@ -459,6 +522,7 @@ var __cursor_hook_config__ = { log('Cursor Hook 初始化完成'); log('machineId:', __cursor_ids__.machineId.substring(0, 16) + '...'); + log('machineGuid:', getMachineGuid().substring(0, 16) + '...'); log('devDeviceId:', __cursor_ids__.devDeviceId); log('sqmId:', __cursor_ids__.sqmId); @@ -474,4 +538,3 @@ if (typeof module !== 'undefined' && module.exports) { if (typeof globalThis !== 'undefined') { globalThis.__cursor_hook_config__ = __cursor_hook_config__; } - diff --git a/scripts/run/cursor_linux_id_modifier.sh b/scripts/run/cursor_linux_id_modifier.sh index c04f679..38ee9dc 100755 --- a/scripts/run/cursor_linux_id_modifier.sh +++ b/scripts/run/cursor_linux_id_modifier.sh @@ -72,6 +72,7 @@ BACKUP_DIR="$CURSOR_CONFIG_DIR/User/globalStorage/backups" # 共享ID(用于配置与JS注入保持一致) CURSOR_ID_MACHINE_ID="" +CURSOR_ID_MACHINE_GUID="" CURSOR_ID_MAC_MACHINE_ID="" CURSOR_ID_DEVICE_ID="" CURSOR_ID_SQM_ID="" @@ -529,6 +530,7 @@ PY # 仅用于JS注入的ID生成(不写配置) generate_ids_for_js_only() { CURSOR_ID_MACHINE_ID=$(openssl rand -hex 32) + CURSOR_ID_MACHINE_GUID=$(generate_uuid) CURSOR_ID_MAC_MACHINE_ID=$(openssl rand -hex 32) CURSOR_ID_DEVICE_ID=$(generate_uuid) CURSOR_ID_SQM_ID="{$(generate_uuid | tr '[:lower:]' '[:upper:]')}" @@ -787,10 +789,12 @@ find_cursor_js_files() { local js_patterns=( "resources/app/out/vs/workbench/api/node/extensionHostProcess.js" "resources/app/out/main.js" + "resources/app/out/vs/code/electron-utility/sharedProcess/sharedProcessMain.js" "resources/app/out/vs/code/node/cliProcessMain.js" # 添加其他可能的路径模式 "app/out/vs/workbench/api/node/extensionHostProcess.js" # 如果资源目录是 app 的父目录 "app/out/main.js" + "app/out/vs/code/electron-utility/sharedProcess/sharedProcessMain.js" "app/out/vs/code/node/cliProcessMain.js" ) @@ -841,13 +845,13 @@ find_cursor_js_files() { } # 修改Cursor的JS文件 -# 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版 Hook 方案) +# 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版三重方案) # 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名 -# 方案B: 深度 Hook 注入 - 从底层拦截所有设备标识符生成 -# 方案C: Module.prototype.require 劫持 - 拦截 child_process, crypto, os 等模块 +# 方案B: b6 定点重写 - 机器码源函数直接返回固定值 +# 方案C: Loader Stub + 外置 Hook - 主/共享进程仅加载外置 Hook 文件 modify_cursor_js_files() { log_info "🔧 [内核修改] 开始修改Cursor内核JS文件实现设备识别绕过..." - log_info "💡 [方案] 使用增强版 Hook 方案:深度模块劫持 + someValue替换" + log_info "💡 [方案] 使用增强版三重方案:占位符替换 + b6 定点重写 + Loader Stub + 外置 Hook" # 先查找需要修改的JS文件 if ! find_cursor_js_files; then @@ -861,6 +865,7 @@ modify_cursor_js_files() { # 生成或复用设备标识符(优先使用配置中读取的值) local machine_id="${CURSOR_ID_MACHINE_ID:-}" + local machine_guid="${CURSOR_ID_MACHINE_GUID:-}" local device_id="${CURSOR_ID_DEVICE_ID:-}" local mac_machine_id="${CURSOR_ID_MAC_MACHINE_ID:-}" local sqm_id="${CURSOR_ID_SQM_ID:-}" @@ -873,6 +878,10 @@ modify_cursor_js_files() { machine_id=$(openssl rand -hex 32) ids_missing=true fi + if [ -z "$machine_guid" ]; then + machine_guid=$(generate_uuid) + ids_missing=true + fi if [ -z "$device_id" ]; then device_id=$(generate_uuid) ids_missing=true @@ -901,6 +910,7 @@ modify_cursor_js_files() { fi CURSOR_ID_MACHINE_ID="$machine_id" + CURSOR_ID_MACHINE_GUID="$machine_guid" CURSOR_ID_DEVICE_ID="$device_id" CURSOR_ID_MAC_MACHINE_ID="$mac_machine_id" CURSOR_ID_SQM_ID="$sqm_id" @@ -910,6 +920,7 @@ modify_cursor_js_files() { log_info "🔑 [准备] 设备标识符已就绪" log_info " machineId: ${machine_id:0:16}..." + log_info " machineGuid: ${machine_guid:0:16}..." log_info " deviceId: ${device_id:0:16}..." log_info " macMachineId: ${mac_machine_id:0:16}..." log_info " sqmId: $sqm_id" @@ -923,16 +934,75 @@ modify_cursor_js_files() { cat > "$ids_config_path" << EOF { "machineId": "$machine_id", + "machineGuid": "$machine_guid", "macMachineId": "$mac_machine_id", "devDeviceId": "$device_id", "sqmId": "$sqm_id", "macAddress": "$mac_address", + "sessionId": "$session_id", + "firstSessionDate": "$first_session_date", "createdAt": "$first_session_date" } EOF chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$ids_config_path" 2>/dev/null || true log_info "💾 [保存] 新的 ID 配置已保存到: $ids_config_path" + # 部署外置 Hook 文件(供 Loader Stub 加载,支持多域名备用下载) + local hook_target_path="$HOME/.cursor_hook.js" + local script_dir + script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + local hook_source_path="$script_dir/../hook/cursor_hook.js" + local hook_download_urls=( + "https://wget.la/https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + "https://down.npee.cn/?https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + "https://xget.xi-xu.me/gh/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + "https://gh-proxy.com/https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + "https://gh.chjina.com/https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + ) + + if [ -f "$hook_source_path" ]; then + if cp "$hook_source_path" "$hook_target_path"; then + chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$hook_target_path" 2>/dev/null || true + log_info "✅ [Hook] 外置 Hook 已部署: $hook_target_path" + else + log_warn "⚠️ [Hook] 本地 Hook 复制失败,尝试在线下载..." + fi + fi + + if [ ! -f "$hook_target_path" ]; then + local hook_downloaded=false + if command -v curl >/dev/null 2>&1; then + for url in "${hook_download_urls[@]}"; do + if curl -fsSL "$url" -o "$hook_target_path"; then + chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$hook_target_path" 2>/dev/null || true + log_info "✅ [Hook] 外置 Hook 已在线下载: $hook_target_path" + hook_downloaded=true + break + else + rm -f "$hook_target_path" + log_warn "⚠️ [Hook] 外置 Hook 下载失败: $url" + fi + done + elif command -v wget >/dev/null 2>&1; then + for url in "${hook_download_urls[@]}"; do + if wget -qO "$hook_target_path" "$url"; then + chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$hook_target_path" 2>/dev/null || true + log_info "✅ [Hook] 外置 Hook 已在线下载: $hook_target_path" + hook_downloaded=true + break + else + rm -f "$hook_target_path" + log_warn "⚠️ [Hook] 外置 Hook 下载失败: $url" + fi + done + else + log_warn "⚠️ [Hook] 未检测到 curl/wget,无法在线下载 Hook" + fi + if [ "$hook_downloaded" != true ] && [ ! -f "$hook_target_path" ]; then + log_warn "⚠️ [Hook] 外置 Hook 全部下载失败" + fi + fi + local modified_count=0 local file_modification_status=() @@ -1041,102 +1111,66 @@ EOF replaced=true fi - # ========== 方法B: 增强版深度 Hook 注入 ========== - local inject_code='// ========== Cursor Hook 注入开始 ========== + # ========== 方法B: b6 定点重写(机器码源函数,仅 main.js) ========== + local b6_patched=false + if [ "$(basename "$file")" = "main.js" ]; then + if command -v python3 >/dev/null 2>&1; then + local b6_result + b6_result=$(python3 - "$file" "$machine_guid" "$machine_id" <<'PY' +import re, sys +path, machine_guid, machine_id = sys.argv[1], sys.argv[2], sys.argv[3] +with open(path, "r", encoding="utf-8") as f: + data = f.read() +pattern = re.compile(r'async function (\\w+)\\((\\w+)\\)\\{.*?createHash\\(\"sha256\"\\).*?return \\w+\\?\\w+:\\w+\\}', re.S) +def repl(m): + name = m.group(1) + param = m.group(2) + return f"async function {name}({param}){{return {param}?\\\"{machine_guid}\\\":\\\"{machine_id}\\\";}}" +new_data, count = pattern.subn(repl, data, count=1) +if count: + with open(path, "w", encoding="utf-8") as f: + f.write(new_data) + print("PATCHED") +else: + print("NOT_FOUND") +PY +) + if [ "$b6_result" = "PATCHED" ]; then + log_info " ✓ [方案B] 已重写 b6 特征函数" + b6_patched=true + else + log_warn "⚠️ [方案B] 未定位到 b6 特征函数" + fi + else + log_warn "⚠️ [方案B] 未检测到 python3,跳过 b6 定点重写" + fi + fi + + # ========== 方法C: Loader Stub 注入 ========== + local inject_code='// ========== Cursor Hook Loader 开始 ========== ;(async function(){/*__cursor_patched__*/ "use strict"; -if(globalThis.__cursor_patched__)return; +if(globalThis.__cursor_hook_loaded__)return; +globalThis.__cursor_hook_loaded__=true; -// 兼容 ESM:确保可用的 require(部分版本 main.js 可能是纯 ESM,不保证存在 require) -var __require__=typeof require==="function"?require:null; -if(!__require__){ - try{ +try{ + var __require__=typeof require==="function"?require:null; + if(!__require__){ var __m__=await import("module"); __require__=__m__.createRequire(import.meta.url); - }catch(e){ - // 无法获得 require 时直接退出,避免影响主进程启动 - return; - } -} - -globalThis.__cursor_patched__=true; - -var __ids__={ - machineId:"'"$machine_id"'", - macMachineId:"'"$mac_machine_id"'", - devDeviceId:"'"$device_id"'", - sqmId:"'"$sqm_id"'", - macAddress:"'"$mac_address"'" -}; - -globalThis.__cursor_ids__=__ids__; - -var Module=__require__("module"); -var _origReq=Module.prototype.require; -var _hooked=new Map(); - -Module.prototype.require=function(id){ - var result=_origReq.apply(this,arguments); - if(_hooked.has(id))return _hooked.get(id); - var hooked=result; - - if(id==="child_process"){ - var _origExecSync=result.execSync; - result.execSync=function(cmd,opts){ - var cmdStr=String(cmd).toLowerCase(); - if(cmdStr.includes("machine-id")||cmdStr.includes("hostname")){ - return Buffer.from(__ids__.machineId.substring(0,32)); - } - return _origExecSync.apply(this,arguments); - }; - hooked=result; } - else if(id==="os"){ - result.networkInterfaces=function(){ - return{"eth0":[{address:"192.168.1.100",netmask:"255.255.255.0",family:"IPv4",mac:__ids__.macAddress,internal:false}]}; - }; - hooked=result; + var fs=__require__("fs"); + var path=__require__("path"); + var os=__require__("os"); + var hookPath=path.join(os.homedir(), ".cursor_hook.js"); + if(fs.existsSync(hookPath)){ + __require__(hookPath); } - else if(id==="crypto"){ - var _origCreateHash=result.createHash; - var _origRandomUUID=result.randomUUID; - result.createHash=function(algo){ - var hash=_origCreateHash.apply(this,arguments); - if(algo.toLowerCase()==="sha256"){ - var _origDigest=hash.digest.bind(hash); - var _origUpdate=hash.update.bind(hash); - var inputData=""; - hash.update=function(data,enc){inputData+=String(data);return _origUpdate(data,enc);}; - hash.digest=function(enc){ - if(inputData.includes("machine-id")||(inputData.length>=32&&inputData.length<=40)){ - return enc==="hex"?__ids__.machineId:Buffer.from(__ids__.machineId,"hex"); - } - return _origDigest(enc); - }; - } - return hash; - }; - if(_origRandomUUID){ - var uuidCount=0; - result.randomUUID=function(){ - uuidCount++; - if(uuidCount<=2)return __ids__.devDeviceId; - return _origRandomUUID.apply(this,arguments); - }; - } - hooked=result; - } - else if(id==="@vscode/deviceid"){ - hooked={...result,getDeviceId:async function(){return __ids__.devDeviceId;}}; - } - - if(hooked!==result)_hooked.set(id,hooked); - return hooked; -}; - -console.log("[Cursor ID Modifier] 增强版 Hook 已激活 - 煎饼果子(86) 公众号【煎饼果子卷AI】"); +}catch(e){ + // 失败静默,避免影响启动 +} })(); -// ========== Cursor Hook 注入结束 ========== +// ========== Cursor Hook Loader 结束 ========== ' @@ -1153,19 +1187,22 @@ console.log("[Cursor ID Modifier] 增强版 Hook 已激活 - 煎饼果子(86) } { print } ' "$file" > "$temp_file" - log_info " ✓ [方案B] 增强版 Hook 代码已注入(版权声明后)" + log_info " ✓ [方案C] Loader Stub 已注入(版权声明后)" else echo "$inject_code" > "$temp_file" cat "$file" >> "$temp_file" - log_info " ✓ [方案B] 增强版 Hook 代码已注入(文件开头)" + log_info " ✓ [方案C] Loader Stub 已注入(文件开头)" fi if mv "$temp_file" "$file"; then + local summary="Hook加载器" if [ "$replaced" = true ]; then - log_info "✅ [成功] 增强版混合方案修改成功(someValue替换 + 深度Hook)" - else - log_info "✅ [成功] 增强版 Hook 修改成功" + summary="someValue替换 + $summary" + fi + if [ "$b6_patched" = true ]; then + summary="b6定点重写 + $summary" fi + log_info "✅ [成功] 增强版方案修改成功($summary)" ((modified_count++)) file_modification_status+=("'$(basename "$file")': Success") @@ -1191,9 +1228,10 @@ console.log("[Cursor ID Modifier] 增强版 Hook 已激活 - 煎饼果子(86) fi log_info "🎉 [完成] 成功修改 $modified_count 个JS文件" - log_info "💡 [说明] 使用增强版 Hook 方案:" + log_info "💡 [说明] 使用增强版三重方案:" log_info " • 方案A: someValue占位符替换(稳定锚点,跨版本兼容)" - log_info " • 方案B: 深度模块劫持(child_process, crypto, os, @vscode/*)" + log_info " • 方案B: b6 定点重写(机器码源函数)" + log_info " • 方案C: Loader Stub + 外置 Hook(cursor_hook.js)" log_info "📁 [配置] ID 配置文件: $ids_config_path" return 0 } diff --git a/scripts/run/cursor_mac_id_modifier.sh b/scripts/run/cursor_mac_id_modifier.sh index 85cd53e..eb3ba70 100644 --- a/scripts/run/cursor_mac_id_modifier.sh +++ b/scripts/run/cursor_mac_id_modifier.sh @@ -755,6 +755,7 @@ BACKUP_DIR="$TARGET_HOME/Library/Application Support/Cursor/User/globalStorage/b # 共享ID(用于配置与JS注入保持一致) CURSOR_ID_MACHINE_ID="" +CURSOR_ID_MACHINE_GUID="" CURSOR_ID_MAC_MACHINE_ID="" CURSOR_ID_DEVICE_ID="" CURSOR_ID_SQM_ID="" @@ -1434,31 +1435,10 @@ _show_troubleshooting_info() { echo } -# 智能设备识别绕过(优先MAC地址修改,失败则JS注入) +# 智能设备识别绕过(已移除 MAC 地址修改,仅保留 JS 注入) run_device_bypass() { - log_info "🔧 [设备识别] 开始执行智能设备识别绕过..." + log_info "🔧 [设备识别] 已禁用 MAC 地址修改,直接执行 JS 内核注入..." - local wifi_interface="" - wifi_interface=$(networksetup -listallhardwareports | awk '/Hardware Port: Wi-Fi/{getline; print $2; exit}') - local mac_success=false - - if [ -n "$wifi_interface" ]; then - log_info "📡 [接口] 检测到 Wi-Fi 接口: $wifi_interface" - if _change_mac_for_one_interface "$wifi_interface"; then - mac_success=true - else - log_warn "⚠️ [MAC] Wi-Fi 接口 MAC 地址修改失败或未生效" - fi - else - log_warn "⚠️ [MAC] 未找到 Wi-Fi 接口,改用 JS 注入" - fi - - if [ "$mac_success" = true ]; then - log_info "✅ [MAC] MAC 地址修改成功,跳过 JS 注入" - return 0 - fi - - log_info "🔧 [JS] 开始执行 JS 内核注入..." if modify_cursor_js_files; then log_info "✅ [JS] JS 内核注入完成" return 0 @@ -1572,13 +1552,13 @@ protect_storage_file() { fi } -# 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版 Hook 方案) +# 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版三重方案) # 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名 -# 方案B: 深度 Hook 注入 - 从底层拦截所有设备标识符生成 -# 方案C: Module.prototype.require 劫持 - 拦截 child_process, crypto, os 等模块 +# 方案B: b6 定点重写 - 机器码源函数直接返回固定值 +# 方案C: Loader Stub + 外置 Hook - 主/共享进程仅加载外置 Hook 文件 modify_cursor_js_files() { log_info "🔧 [内核修改] 开始修改Cursor内核JS文件实现设备识别绕过..." - log_info "💡 [方案] 使用增强版 Hook 方案:深度模块劫持 + someValue替换" + log_info "💡 [方案] 使用增强版三重方案:占位符替换 + b6 定点重写 + Loader Stub + 外置 Hook" echo # 检查Cursor应用是否存在 @@ -1589,6 +1569,7 @@ modify_cursor_js_files() { # 生成或复用设备标识符(优先使用配置中生成的值) local machine_id="${CURSOR_ID_MACHINE_ID:-}" + local machine_guid="${CURSOR_ID_MACHINE_GUID:-}" local device_id="${CURSOR_ID_DEVICE_ID:-}" local mac_machine_id="${CURSOR_ID_MAC_MACHINE_ID:-}" local sqm_id="${CURSOR_ID_SQM_ID:-}" @@ -1601,6 +1582,10 @@ modify_cursor_js_files() { machine_id=$(openssl rand -hex 32) ids_missing=true fi + if [ -z "$machine_guid" ]; then + machine_guid=$(uuidgen | tr '[:upper:]' '[:lower:]') + ids_missing=true + fi if [ -z "$device_id" ]; then device_id=$(uuidgen | tr '[:upper:]' '[:lower:]') ids_missing=true @@ -1629,6 +1614,7 @@ modify_cursor_js_files() { fi CURSOR_ID_MACHINE_ID="$machine_id" + CURSOR_ID_MACHINE_GUID="$machine_guid" CURSOR_ID_DEVICE_ID="$device_id" CURSOR_ID_MAC_MACHINE_ID="$mac_machine_id" CURSOR_ID_SQM_ID="$sqm_id" @@ -1638,6 +1624,7 @@ modify_cursor_js_files() { log_info "🔑 [准备] 设备标识符已就绪" log_info " machineId: ${machine_id:0:16}..." + log_info " machineGuid: ${machine_guid:0:16}..." log_info " deviceId: ${device_id:0:16}..." log_info " macMachineId: ${mac_machine_id:0:16}..." log_info " sqmId: $sqm_id" @@ -1652,18 +1639,78 @@ modify_cursor_js_files() { cat > "$ids_config_path" << EOF { "machineId": "$machine_id", + "machineGuid": "$machine_guid", "macMachineId": "$mac_machine_id", "devDeviceId": "$device_id", "sqmId": "$sqm_id", "macAddress": "$mac_address", + "sessionId": "$session_id", + "firstSessionDate": "$first_session_date", "createdAt": "$first_session_date" } EOF log_info "💾 [保存] 新的 ID 配置已保存到: $ids_config_path" - # 目标JS文件列表(只修改 main.js) + # 部署外置 Hook 文件(供 Loader Stub 加载,支持多域名备用下载) + local hook_target_path="$TARGET_HOME/.cursor_hook.js" + local script_dir + script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + local hook_source_path="$script_dir/../hook/cursor_hook.js" + local hook_download_urls=( + "https://wget.la/https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + "https://down.npee.cn/?https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + "https://xget.xi-xu.me/gh/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + "https://gh-proxy.com/https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + "https://gh.chjina.com/https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + ) + + if [ -f "$hook_source_path" ]; then + if cp "$hook_source_path" "$hook_target_path"; then + chown "$TARGET_USER":"$(id -g -n "$TARGET_USER")" "$hook_target_path" 2>/dev/null || true + log_info "✅ [Hook] 外置 Hook 已部署: $hook_target_path" + else + log_warn "⚠️ [Hook] 本地 Hook 复制失败,尝试在线下载..." + fi + fi + + if [ ! -f "$hook_target_path" ]; then + local hook_downloaded=false + if command -v curl >/dev/null 2>&1; then + for url in "${hook_download_urls[@]}"; do + if curl -fsSL "$url" -o "$hook_target_path"; then + chown "$TARGET_USER":"$(id -g -n "$TARGET_USER")" "$hook_target_path" 2>/dev/null || true + log_info "✅ [Hook] 外置 Hook 已在线下载: $hook_target_path" + hook_downloaded=true + break + else + rm -f "$hook_target_path" + log_warn "⚠️ [Hook] 外置 Hook 下载失败: $url" + fi + done + elif command -v wget >/dev/null 2>&1; then + for url in "${hook_download_urls[@]}"; do + if wget -qO "$hook_target_path" "$url"; then + chown "$TARGET_USER":"$(id -g -n "$TARGET_USER")" "$hook_target_path" 2>/dev/null || true + log_info "✅ [Hook] 外置 Hook 已在线下载: $hook_target_path" + hook_downloaded=true + break + else + rm -f "$hook_target_path" + log_warn "⚠️ [Hook] 外置 Hook 下载失败: $url" + fi + done + else + log_warn "⚠️ [Hook] 未检测到 curl/wget,无法在线下载 Hook" + fi + if [ "$hook_downloaded" != true ] && [ ! -f "$hook_target_path" ]; then + log_warn "⚠️ [Hook] 外置 Hook 全部下载失败" + fi + fi + + # 目标JS文件列表(main + shared process) local js_files=( "$CURSOR_APP_PATH/Contents/Resources/app/out/main.js" + "$CURSOR_APP_PATH/Contents/Resources/app/out/vs/code/electron-utility/sharedProcess/sharedProcessMain.js" ) local modified_count=0 @@ -1791,106 +1838,66 @@ EOF replaced=true fi - # ========== 方法B: 增强版深度 Hook 注入 ========== - # 创建注入代码 - local inject_code='// ========== Cursor Hook 注入开始 ========== + # ========== 方法B: b6 定点重写(机器码源函数,仅 main.js) ========== + local b6_patched=false + if [ "$(basename "$file")" = "main.js" ]; then + if command -v python3 >/dev/null 2>&1; then + local b6_result + b6_result=$(python3 - "$file" "$machine_guid" "$machine_id" <<'PY' +import re, sys +path, machine_guid, machine_id = sys.argv[1], sys.argv[2], sys.argv[3] +with open(path, "r", encoding="utf-8") as f: + data = f.read() +pattern = re.compile(r'async function (\\w+)\\((\\w+)\\)\\{.*?createHash\\(\"sha256\"\\).*?return \\w+\\?\\w+:\\w+\\}', re.S) +def repl(m): + name = m.group(1) + param = m.group(2) + return f"async function {name}({param}){{return {param}?\\\"{machine_guid}\\\":\\\"{machine_id}\\\";}}" +new_data, count = pattern.subn(repl, data, count=1) +if count: + with open(path, "w", encoding="utf-8") as f: + f.write(new_data) + print("PATCHED") +else: + print("NOT_FOUND") +PY +) + if [ "$b6_result" = "PATCHED" ]; then + log_info " ✓ [方案B] 已重写 b6 特征函数" + b6_patched=true + else + log_warn "⚠️ [方案B] 未定位到 b6 特征函数" + fi + else + log_warn "⚠️ [方案B] 未检测到 python3,跳过 b6 定点重写" + fi + fi + + # ========== 方法C: Loader Stub 注入 ========== + local inject_code='// ========== Cursor Hook Loader 开始 ========== ;(async function(){/*__cursor_patched__*/ "use strict"; -if(globalThis.__cursor_patched__)return; +if(globalThis.__cursor_hook_loaded__)return; +globalThis.__cursor_hook_loaded__=true; -// 兼容 ESM:确保可用的 require(部分版本 main.js 可能是纯 ESM,不保证存在 require) -var __require__=typeof require==="function"?require:null; -if(!__require__){ - try{ +try{ + var __require__=typeof require==="function"?require:null; + if(!__require__){ var __m__=await import("module"); __require__=__m__.createRequire(import.meta.url); - }catch(e){ - // 无法获得 require 时直接退出,避免影响主进程启动 - return; - } -} - -globalThis.__cursor_patched__=true; - -var __ids__={ - machineId:"'"$machine_id"'", - macMachineId:"'"$mac_machine_id"'", - devDeviceId:"'"$device_id"'", - sqmId:"'"$sqm_id"'", - macAddress:"'"$mac_address"'" -}; - -globalThis.__cursor_ids__=__ids__; - -var Module=__require__("module"); -var _origReq=Module.prototype.require; -var _hooked=new Map(); - -Module.prototype.require=function(id){ - var result=_origReq.apply(this,arguments); - if(_hooked.has(id))return _hooked.get(id); - var hooked=result; - - if(id==="child_process"){ - var _origExecSync=result.execSync; - result.execSync=function(cmd,opts){ - var cmdStr=String(cmd).toLowerCase(); - if(cmdStr.includes("ioreg")&&cmdStr.includes("ioplatformexpertdevice")){ - return Buffer.from("\"IOPlatformUUID\" = \""+__ids__.machineId.substring(0,36).toUpperCase()+"\""); - } - if(cmdStr.includes("machine-id")||cmdStr.includes("hostname")){ - return Buffer.from(__ids__.machineId.substring(0,32)); - } - return _origExecSync.apply(this,arguments); - }; - hooked=result; - } - else if(id==="os"){ - result.networkInterfaces=function(){ - return{"en0":[{address:"192.168.1.100",netmask:"255.255.255.0",family:"IPv4",mac:__ids__.macAddress,internal:false}]}; - }; - hooked=result; - } - else if(id==="crypto"){ - var _origCreateHash=result.createHash; - var _origRandomUUID=result.randomUUID; - result.createHash=function(algo){ - var hash=_origCreateHash.apply(this,arguments); - if(algo.toLowerCase()==="sha256"){ - var _origDigest=hash.digest.bind(hash); - var _origUpdate=hash.update.bind(hash); - var inputData=""; - hash.update=function(data,enc){inputData+=String(data);return _origUpdate(data,enc);}; - hash.digest=function(enc){ - if(inputData.includes("IOPlatformUUID")||(inputData.length>=32&&inputData.length<=40)){ - return enc==="hex"?__ids__.machineId:Buffer.from(__ids__.machineId,"hex"); - } - return _origDigest(enc); - }; - } - return hash; - }; - if(_origRandomUUID){ - var uuidCount=0; - result.randomUUID=function(){ - uuidCount++; - if(uuidCount<=2)return __ids__.devDeviceId; - return _origRandomUUID.apply(this,arguments); - }; - } - hooked=result; } - else if(id==="@vscode/deviceid"){ - hooked={...result,getDeviceId:async function(){return __ids__.devDeviceId;}}; + var fs=__require__("fs"); + var path=__require__("path"); + var os=__require__("os"); + var hookPath=path.join(os.homedir(), ".cursor_hook.js"); + if(fs.existsSync(hookPath)){ + __require__(hookPath); } - - if(hooked!==result)_hooked.set(id,hooked); - return hooked; -}; - -console.log("[Cursor ID Modifier] 增强版 Hook 已激活 - 煎饼果子(86) 公众号【煎饼果子卷AI】"); +}catch(e){ + // 失败静默,避免影响启动 +} })(); -// ========== Cursor Hook 注入结束 ========== +// ========== Cursor Hook Loader 结束 ========== ' @@ -1908,32 +1915,36 @@ console.log("[Cursor ID Modifier] 增强版 Hook 已激活 - 煎饼果子(86) { print } ' "$file" > "${file}.new" mv "${file}.new" "$file" - log_info " ✓ [方案B] 增强版 Hook 代码已注入(版权声明后)" + log_info " ✓ [方案C] Loader Stub 已注入(版权声明后)" else # 注入到文件开头 echo "$inject_code" > "${file}.new" cat "$file" >> "${file}.new" mv "${file}.new" "$file" - log_info " ✓ [方案B] 增强版 Hook 代码已注入(文件开头)" + log_info " ✓ [方案C] Loader Stub 已注入(文件开头)" fi # 清理临时文件 rm -f "${file}.tmp" + local summary="Hook加载器" if [ "$replaced" = true ]; then - log_info "✅ [成功] 增强版混合方案修改成功(someValue替换 + 深度Hook)" - else - log_info "✅ [成功] 增强版 Hook 修改成功" + summary="someValue替换 + $summary" + fi + if [ "$b6_patched" = true ]; then + summary="b6定点重写 + $summary" fi + log_info "✅ [成功] 增强版方案修改成功($summary)" ((modified_count++)) done if [ $modified_count -gt 0 ]; then log_info "🎉 [完成] 成功修改 $modified_count 个JS文件" log_info "💾 [备份] 原始文件备份位置: $backup_dir" - log_info "💡 [说明] 使用增强版 Hook 方案:" + log_info "💡 [说明] 使用增强版三重方案:" log_info " • 方案A: someValue占位符替换(稳定锚点,跨版本兼容)" - log_info " • 方案B: 深度模块劫持(child_process, crypto, os, @vscode/*)" + log_info " • 方案B: b6 定点重写(机器码源函数)" + log_info " • 方案C: Loader Stub + 外置 Hook(cursor_hook.js)" log_info "📁 [配置] ID 配置文件: $ids_config_path" return 0 else @@ -2855,7 +2866,7 @@ main() { echo -e "${BLUE} 5️⃣ 等待配置文件生成完成(最多45秒)${NC}" echo -e "${BLUE} 6️⃣ 关闭Cursor进程${NC}" echo -e "${BLUE} 7️⃣ 修改新生成的机器码配置文件${NC}" - echo -e "${BLUE} 8️⃣ 智能设备识别绕过(MAC地址修改或JS内核修改)${NC}" + echo -e "${BLUE} 8️⃣ 智能设备识别绕过(仅 JS 内核注入)${NC}" echo -e "${BLUE} 9️⃣ 禁用自动更新${NC}" echo -e "${BLUE} 🔟 显示操作完成统计信息${NC}" echo @@ -2865,7 +2876,7 @@ main() { echo -e "${YELLOW} • 执行完成后需要重新启动Cursor${NC}" echo -e "${YELLOW} • 原配置文件会自动备份到backups文件夹${NC}" echo -e "${YELLOW} • 需要Python3环境来处理JSON配置文件${NC}" - echo -e "${YELLOW} • MAC地址修改是临时的,重启后恢复${NC}" + echo -e "${YELLOW} • 已移除 MAC 地址修改,仅保留 JS 注入方案${NC}" fi echo @@ -2964,10 +2975,10 @@ main() { # 🛠️ 修改机器码配置 modify_machine_code_config - # 🔧 智能设备识别绕过(MAC地址修改或JS内核修改) + # 🔧 智能设备识别绕过(仅 JS 内核注入) echo log_info "🔧 [设备识别] 开始智能设备识别绕过..." - log_info "💡 [说明] 将优先尝试 MAC 地址修改,失败则使用 JS 内核注入" + log_info "💡 [说明] 已移除 MAC 地址修改,直接使用 JS 内核注入" if ! run_device_bypass; then log_warn "⚠️ [设备识别] 智能设备识别绕过未完全成功,请查看日志" fi diff --git a/scripts/run/cursor_win_id_modifier.ps1 b/scripts/run/cursor_win_id_modifier.ps1 index 7e2eaf7..32852f3 100644 --- a/scripts/run/cursor_win_id_modifier.ps1 +++ b/scripts/run/cursor_win_id_modifier.ps1 @@ -27,11 +27,11 @@ function Generate-RandomString { # 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版三重方案) # 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名 # 方案B: b6 定点重写 - 机器码源函数直接返回固定值 -# 方案C: 深度 Hook + 共享进程注入 - 拦截 child_process/crypto/os/@vscode 等模块 +# 方案C: Loader Stub + 外置 Hook - 主/共享进程仅加载外置 Hook 文件 function Modify-CursorJSFiles { Write-Host "" Write-Host "$BLUE🔧 [内核修改]$NC 开始修改Cursor内核JS文件实现设备识别绕过..." - Write-Host "$BLUE💡 [方案]$NC 使用增强版三重方案:占位符替换 + b6 定点重写 + 共享进程 Hook" + Write-Host "$BLUE💡 [方案]$NC 使用增强版三重方案:占位符替换 + b6 定点重写 + Loader Stub + 外置 Hook" Write-Host "" # Windows版Cursor应用路径 @@ -125,6 +125,46 @@ function Modify-CursorJSFiles { $idsConfig | ConvertTo-Json | Set-Content -Path $idsConfigPath -Encoding UTF8 Write-Host "$GREEN💾 [保存]$NC 新的 ID 配置已保存到: $idsConfigPath" + # 部署外置 Hook 文件(供 Loader Stub 加载,支持多域名备用下载) + $hookTargetPath = "$env:USERPROFILE\.cursor_hook.js" + $hookSourceCandidates = @( + (Join-Path $PSScriptRoot "..\hook\cursor_hook.js"), + (Join-Path (Get-Location) "scripts\hook\cursor_hook.js") + ) + $hookSourcePath = $hookSourceCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1 + $hookDownloadUrls = @( + "https://wget.la/https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js", + "https://down.npee.cn/?https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js", + "https://xget.xi-xu.me/gh/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js", + "https://gh-proxy.com/https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js", + "https://gh.chjina.com/https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/scripts/hook/cursor_hook.js" + ) + if ($hookSourcePath) { + try { + Copy-Item -Path $hookSourcePath -Destination $hookTargetPath -Force + Write-Host "$GREEN✅ [Hook]$NC 外置 Hook 已部署: $hookTargetPath" + } catch { + Write-Host "$YELLOW⚠️ [Hook]$NC 本地 Hook 复制失败,尝试在线下载..." + } + } + if (-not (Test-Path $hookTargetPath)) { + foreach ($url in $hookDownloadUrls) { + try { + Invoke-WebRequest -Uri $url -OutFile $hookTargetPath -UseBasicParsing -ErrorAction Stop + Write-Host "$GREEN✅ [Hook]$NC 外置 Hook 已在线下载: $hookTargetPath" + break + } catch { + Write-Host "$YELLOW⚠️ [Hook]$NC 外置 Hook 下载失败: $url" + if (Test-Path $hookTargetPath) { + Remove-Item -Path $hookTargetPath -Force + } + } + } + if (-not (Test-Path $hookTargetPath)) { + Write-Host "$YELLOW⚠️ [Hook]$NC 外置 Hook 全部下载失败" + } + } + # 目标JS文件列表(Windows路径,按优先级排序) $jsFiles = @( "$cursorAppPath\resources\app\out\main.js", @@ -258,7 +298,8 @@ function Modify-CursorJSFiles { # ========== 方法B: b6 定点重写(机器码源函数,仅 main.js) ========== # 说明:b6(t) 是 machineId 的核心生成函数,t=true 返回原始值,t=false 返回哈希 if ((Split-Path $file -Leaf) -eq "main.js") { - $b6Pattern = '(?s)async function b6\(\w+\)\{.*?return \w+\?\w+:\w+\}' + # 使用特征锚点定位(createHash("sha256") + return t?e:i),避免依赖函数名 + $b6Pattern = '(?s)async function \w+\(\w+\)\{.*?createHash\("sha256"\).*?return \w+\?\w+:\w+\}' $b6Replacement = "async function b6(t){return t?'$machineGuid':'$machineId';}" $b6Regex = [regex]::new($b6Pattern) if ($b6Regex.IsMatch($content)) { @@ -270,200 +311,45 @@ function Modify-CursorJSFiles { } } - # ========== 方法C: 增强版深度 Hook 注入 ========== - # 从底层拦截所有设备标识符的生成: - # 1. Module.prototype.require 劫持 - 拦截 child_process, crypto, os 等模块 - # 2. child_process.execSync - 拦截 REG.exe 查询 MachineGuid - # 3. crypto.createHash - 拦截 SHA256 哈希计算 - # 4. crypto.randomUUID - 拦截 UUID 生成 - # 5. os.networkInterfaces - 拦截 MAC 地址获取 - # 6. @vscode/deviceid - 拦截 devDeviceId 获取 - # 7. @vscode/windows-registry - 拦截注册表读取 + # ========== 方法C: Loader Stub 注入 ========== + # 说明:主/共享进程仅注入加载器,具体 Hook 逻辑由外置 cursor_hook.js 维护 $injectCode = @" -// ========== Cursor Hook 注入开始 ========== +// ========== Cursor Hook Loader 开始 ========== ;(async function(){/*__cursor_patched__*/ 'use strict'; -if (globalThis.__cursor_patched__) return; -globalThis.__cursor_patched__ = true; +if (globalThis.__cursor_hook_loaded__) return; +globalThis.__cursor_hook_loaded__ = true; try { - // 固定的设备标识符(与 PowerShell 生成保持一致) - var __ids__ = { - machineId:'$machineId', - machineGuid:'$machineGuid', - macMachineId:'$macMachineId', - devDeviceId:'$deviceId', - sqmId:'$sqmId', - macAddress:'$macAddress', - sessionId:'$sessionId', - firstSessionDate:'$firstSessionDateValue' - }; - - // 暴露到全局,便于共享进程复用 - globalThis.__cursor_ids__ = __ids__; - - // 兼容 ESM:尝试获取 require var __require__ = typeof require === 'function' ? require : null; if (!__require__) { - try { - var __m__ = await import('module'); - __require__ = __m__.createRequire(import.meta.url); - } catch (e) { - // 无法获得 require 时仅做全局 crypto 兜底,避免影响启动 - if (globalThis.crypto && typeof globalThis.crypto.randomUUID === 'function') { - var __origGlobalUUID__ = globalThis.crypto.randomUUID; - var __uuidCount__ = 0; - globalThis.crypto.randomUUID = function(){ - __uuidCount__++; - if (__uuidCount__ <= 2) return __ids__.devDeviceId; - return __origGlobalUUID__.apply(this, arguments); - }; - } - return; - } + var __m__ = await import('module'); + __require__ = __m__.createRequire(import.meta.url); } - - // 处理 node: 前缀模块名 - function __normalizeId__(id){ - return (typeof id === 'string' && id.indexOf('node:') === 0) ? id.slice(5) : id; + var fs = __require__('fs'); + var path = __require__('path'); + var os = __require__('os'); + var hookPath = path.join(os.homedir(), '.cursor_hook.js'); + if (fs.existsSync(hookPath)) { + __require__(hookPath); } - - // 先覆盖全局 crypto.randomUUID(满足直调用) - if (globalThis.crypto && typeof globalThis.crypto.randomUUID === 'function') { - var __origGlobalUUID2__ = globalThis.crypto.randomUUID; - var __uuidCount2__ = 0; - globalThis.crypto.randomUUID = function(){ - __uuidCount2__++; - if (__uuidCount2__ <= 2) return __ids__.devDeviceId; - return __origGlobalUUID2__.apply(this, arguments); - }; - } - - // Hook Module.prototype.require - var Module = __require__('module'); - var _origReq = Module.prototype.require; - var _hooked = new Map(); - - Module.prototype.require = function(id){ - var normalized = __normalizeId__(id); - var result = _origReq.apply(this, arguments); - if (_hooked.has(normalized)) return _hooked.get(normalized); - var hooked = result; - - // Hook child_process(拦截注册表/平台查询) - if (normalized === 'child_process') { - var _origExecSync = result.execSync; - var _origExecFileSync = result.execFileSync; - if (typeof _origExecSync === 'function') { - result.execSync = function(cmd, opts){ - var cmdStr = String(cmd).toLowerCase(); - if (cmdStr.includes('reg') && cmdStr.includes('machineguid')) { - return Buffer.from('\r\n MachineGuid REG_SZ ' + __ids__.machineGuid + '\r\n'); - } - if (cmdStr.includes('ioreg') && cmdStr.includes('ioplatformexpertdevice')) { - return Buffer.from('\"IOPlatformUUID\" = \"' + __ids__.machineGuid.toUpperCase() + '\"'); - } - return _origExecSync.apply(this, arguments); - }; - } - if (typeof _origExecFileSync === 'function') { - result.execFileSync = function(file, args, opts){ - var cmdStr = [file].concat(args || []).join(' ').toLowerCase(); - if (cmdStr.includes('reg') && cmdStr.includes('machineguid')) { - return Buffer.from('\r\n MachineGuid REG_SZ ' + __ids__.machineGuid + '\r\n'); - } - if (cmdStr.includes('ioreg') && cmdStr.includes('ioplatformexpertdevice')) { - return Buffer.from('\"IOPlatformUUID\" = \"' + __ids__.machineGuid.toUpperCase() + '\"'); - } - return _origExecFileSync.apply(this, arguments); - }; - } - hooked = result; - } - // Hook os(MAC 地址) - else if (normalized === 'os') { - var _origNI = result.networkInterfaces; - result.networkInterfaces = function(){ - return {'Ethernet':[{'address':'192.168.1.100','netmask':'255.255.255.0','family':'IPv4','mac':__ids__.macAddress,'internal':false}]}; - }; - hooked = result; - } - // Hook crypto(hash/uuid) - else if (normalized === 'crypto') { - var _origCreateHash = result.createHash; - var _origRandomUUID = result.randomUUID; - if (typeof _origCreateHash === 'function') { - result.createHash = function(algo){ - var hash = _origCreateHash.apply(this, arguments); - var algoName = String(algo).toLowerCase(); - if (algoName === 'sha256') { - var _origDigest = hash.digest.bind(hash); - var _origUpdate = hash.update.bind(hash); - var inputData = ''; - hash.update = function(data, enc){ inputData += String(data); return _origUpdate(data, enc); }; - hash.digest = function(enc){ - var text = inputData.toLowerCase(); - var looksGuid = /^[0-9a-f-]{32,36}$/.test(text); - if (looksGuid || text.includes('machineguid') || text.includes('ioplatformuuid')) { - return enc === 'hex' ? __ids__.machineId : Buffer.from(__ids__.machineId, 'hex'); - } - return _origDigest(enc); - }; - } - return hash; - }; - } - if (typeof _origRandomUUID === 'function') { - var uuidCount = 0; - result.randomUUID = function(){ - uuidCount++; - if (uuidCount <= 2) return __ids__.devDeviceId; - return _origRandomUUID.apply(this, arguments); - }; - } - hooked = result; - } - // Hook @vscode/deviceid - else if (normalized === '@vscode/deviceid') { - hooked = Object.assign({}, result, { - getDeviceId: async function(){ return __ids__.devDeviceId; } - }); - } - // Hook @vscode/windows-registry - else if (normalized === '@vscode/windows-registry') { - var _origGetReg = result.GetStringRegKey; - hooked = Object.assign({}, result, { - GetStringRegKey: function(hive, path, name){ - var p = String(path || '').toLowerCase(); - if (name === 'MachineId' || p.includes('sqmclient')) return __ids__.sqmId; - if (name === 'MachineGuid' || p.includes('cryptography')) return __ids__.machineGuid; - return _origGetReg ? _origGetReg.apply(this, arguments) : ''; - } - }); - } - - if (hooked !== result) _hooked.set(normalized, hooked); - return hooked; - }; - - console.log('[Cursor ID Modifier] Hook 已激活(占位符 + b6 + 共享进程)'); } catch (e) { - try { console.warn('[Cursor ID Modifier] 注入异常:' + (e && e.message ? e.message : e)); } catch (_) {} + // 失败静默,避免影响启动 } })(); -// ========== Cursor Hook 注入结束 ========== +// ========== Cursor Hook Loader 结束 ========== "@ # 找到版权声明结束位置并在其后注入 if ($content -match '(\*/\s*\n)') { $content = $content -replace '(\*/\s*\n)', "`$1$injectCode" - Write-Host " $GREEN✓$NC [方案C] 增强版 Hook 代码已注入(版权声明后)" + Write-Host " $GREEN✓$NC [方案C] Loader Stub 已注入(版权声明后)" } else { # 如果没有找到版权声明,则注入到文件开头 $content = $injectCode + $content - Write-Host " $GREEN✓$NC [方案C] 增强版 Hook 代码已注入(文件开头)" + Write-Host " $GREEN✓$NC [方案C] Loader Stub 已注入(文件开头)" } # 写入修改后的内容 @@ -473,7 +359,7 @@ try { $summaryParts = @() if ($replaced) { $summaryParts += "someValue替换" } if ($replacedB6) { $summaryParts += "b6定点重写" } - $summaryParts += "深度Hook" + $summaryParts += "Hook加载器" $summaryText = ($summaryParts -join " + ") Write-Host "$GREEN✅ [成功]$NC 增强版方案修改成功($summaryText)" $modifiedCount++ @@ -497,7 +383,7 @@ try { Write-Host "$BLUE💡 [说明]$NC 使用增强版三重方案:" Write-Host " • 方案A: someValue占位符替换(稳定锚点,跨版本兼容)" Write-Host " • 方案B: b6 定点重写(机器码源函数)" - Write-Host " • 方案C: 深度模块劫持 + 共享进程注入(child_process/crypto/os/@vscode/*)" + Write-Host " • 方案C: Loader Stub + 外置 Hook(cursor_hook.js)" Write-Host "$BLUE📁 [配置]$NC ID 配置文件: $idsConfigPath" return $true } else {