diff --git a/scripts/run/cursor_linux_id_modifier.sh b/scripts/run/cursor_linux_id_modifier.sh index db0b95b..09b8660 100755 --- a/scripts/run/cursor_linux_id_modifier.sh +++ b/scripts/run/cursor_linux_id_modifier.sh @@ -651,29 +651,76 @@ find_cursor_js_files() { } # 修改Cursor的JS文件 +# 🔧 修改Cursor内核JS文件实现设备识别绕过(A+B混合方案 - IIFE + someValue替换) +# 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名 +# 方案B: IIFE运行时劫持 - 劫持crypto.randomUUID从源头拦截 modify_cursor_js_files() { - log_info "开始修改Cursor的JS文件..." - + log_info "🔧 [内核修改] 开始修改Cursor内核JS文件实现设备识别绕过..." + log_info "💡 [方案] 使用A+B混合方案:someValue占位符替换 + IIFE运行时劫持" + # 先查找需要修改的JS文件 if ! find_cursor_js_files; then - # find_cursor_js_files 内部会打印错误日志 return 1 fi - + if [ ${#CURSOR_JS_FILES[@]} -eq 0 ]; then log_error "JS 文件列表为空,无法继续修改。" return 1 fi + # 生成新的设备标识符(使用固定格式确保兼容性) + local new_uuid=$(generate_uuid) + local machine_id=$(openssl rand -hex 32) + local device_id=$(generate_uuid) + local mac_machine_id=$(openssl rand -hex 32) + local sqm_id=$(generate_uuid) + local session_id=$(generate_uuid) + + log_info "🔑 [生成] 已生成新的设备标识符" + log_info " machineId: ${machine_id:0:16}..." + log_info " deviceId: ${device_id:0:16}..." + log_info " macMachineId: ${mac_machine_id:0:16}..." + local modified_count=0 - local file_modification_status=() # 记录每个文件的修改状态 + local file_modification_status=() + # 检查是否需要修改(使用统一标记) + log_info "🔍 [检查] 检查JS文件修改状态..." + local need_modification=false for file in "${CURSOR_JS_FILES[@]}"; do - log_info "处理文件: $file" - + if [ ! -f "$file" ]; then + log_warn "⚠️ [警告] 文件不存在: $file" + continue + fi + + # 检查是否已经被修改过(使用统一标记 __cursor_patched__) + if grep -q "__cursor_patched__" "$file" 2>/dev/null; then + log_info "✅ [已修改] 文件已修改: $(basename "$file")" + else + log_info "📝 [需要] 文件需要修改: $(basename "$file")" + need_modification=true + fi + done + + if [ "$need_modification" = false ]; then + log_info "✅ [跳过] 所有JS文件已经被修改过,无需重复操作" + return 0 + fi + + for file in "${CURSOR_JS_FILES[@]}"; do + log_info "📝 [处理] 正在处理: $(basename "$file")" + if [ ! -f "$file" ]; then log_error "文件不存在: $file,跳过处理。" - file_modification_status+=("'$file': Not Found") + file_modification_status+=("'$(basename "$file")': Not Found") + continue + fi + + # 检查是否已经修改过 + if grep -q "__cursor_patched__" "$file"; then + log_info "✅ [跳过] 文件已经被修改过" + ((modified_count++)) + file_modification_status+=("'$(basename "$file")': Already Patched") continue fi @@ -681,189 +728,112 @@ modify_cursor_js_files() { local backup_file="${file}.backup_$(date +%Y%m%d_%H%M%S)" if ! cp "$file" "$backup_file"; then log_error "无法创建文件备份: $file" - file_modification_status+=("'$file': Backup Failed") + file_modification_status+=("'$(basename "$file")': Backup Failed") continue fi - chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$backup_file" || log_warn "设置备份文件所有权失败: $backup_file" - chmod 444 "$backup_file" || log_warn "设置备份文件权限失败: $backup_file" - + chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$backup_file" 2>/dev/null || true + chmod 444 "$backup_file" 2>/dev/null || true - # 确保文件对当前执行用户(root)可写 + # 确保文件对当前执行用户可写 chmod u+w "$file" || { log_error "无法修改文件权限(写): $file" - file_modification_status+=("'$file': Permission Error (Write)") - # 尝试恢复备份(如果可能) + file_modification_status+=("'$(basename "$file")': Permission Error") cp "$backup_file" "$file" 2>/dev/null || true continue } - - local modification_applied=false - # --- 开始尝试各种修改模式 --- - - # 模式1:精确修改 x-cursor-checksum (最常见的目标之一) - if grep -q 'i.header.set("x-cursor-checksum' "$file"; then - log_debug "找到 x-cursor-checksum 设置代码,尝试修改..." - # 使用更健壮的 sed,处理不同的空格和变量名可能性 - if sed -i -E 's/(i|[\w$]+)\.header\.set\("x-cursor-checksum",\s*e\s*===\s*void 0\s*\?\s*`\$\{p\}(\$\{t\})`\s*:\s*`\$\{p\}\2\/(\$\{e\})`/i.header.set("x-cursor-checksum",e===void 0?`${p}${t}`:`${p}${t}\/${p}`)/' "$file"; then - # 验证修改是否真的发生 (避免 sed 没匹配但返回0) - if ! grep -q 'i.header.set("x-cursor-checksum",e===void 0?`${p}${t}`:`${p}${t}\/${e}`)' "$file"; then - log_info "成功修改 x-cursor-checksum 设置代码" - modification_applied=true - else - log_warn "sed 命令执行成功,但似乎未修改 x-cursor-checksum (可能模式不匹配当前版本)" - fi - else - log_error "修改 x-cursor-checksum 设置代码失败 (sed 命令执行错误)" - fi + local replaced=false + + # ========== 方法A: someValue占位符替换(稳定锚点) ========== + # 这些字符串是固定的占位符,不会被混淆器修改,跨版本稳定 + + # 替换 someValue.machineId + if grep -q 'someValue\.machineId' "$file"; then + sed -i "s/someValue\.machineId/${machine_id}/g" "$file" + log_info " ✓ [方案A] 替换 someValue.machineId" + replaced=true fi - # 模式2:注入 randomUUID 到特定函数 (如果模式1未应用) - if [ "$modification_applied" = false ] && grep -q "IOPlatformUUID" "$file"; then - log_debug "未修改 checksum 或未找到,尝试注入 randomUUID..." - # 尝试注入 a$ 函数 - if grep -q "function a\$(" "$file" && ! grep -q "return crypto.randomUUID()" "$file"; then - if sed -i 's/function a\$(t){switch/function a\$(t){try { return require("crypto").randomUUID(); } catch(e){} switch/' "$file"; then - # 验证修改 - if grep -q "return require(\"crypto\").randomUUID()" "$file"; then - log_info "成功注入 randomUUID 调用到 a\$ 函数" - modification_applied=true - else - log_warn "sed 注入 a$ 失败(可能模式不匹配)" - fi - else - log_error "修改 a\$ 函数失败 (sed 命令执行错误)" - fi - # 尝试注入 v5 函数 (如果 a$ 没成功) - elif [ "$modification_applied" = false ] && grep -q "async function v5(" "$file" && ! grep -q "return crypto.randomUUID()" "$file"; then - if sed -i 's/async function v5(t){let e=/async function v5(t){try { return require("crypto").randomUUID(); } catch(e){} let e=/' "$file"; then - # 验证修改 - if grep -q "return require(\"crypto\").randomUUID()" "$file"; then - log_info "成功注入 randomUUID 调用到 v5 函数" - modification_applied=true - else - log_warn "sed 注入 v5 失败(可能模式不匹配)" - fi - else - log_error "修改 v5 函数失败 (sed 命令执行错误)" - fi - fi + # 替换 someValue.macMachineId + if grep -q 'someValue\.macMachineId' "$file"; then + sed -i "s/someValue\.macMachineId/${mac_machine_id}/g" "$file" + log_info " ✓ [方案A] 替换 someValue.macMachineId" + replaced=true fi - # 模式3:通用注入 (如果上述模式都未应用,并且没有标记) - if [ "$modification_applied" = false ] && ! grep -q "// Cursor ID Modifier Injection" "$file"; then - log_debug "特定修改模式未生效或不适用,尝试通用注入..." - # 生成唯一标识符以避免冲突 - local timestamp=$(date +%s) - local new_uuid=$(generate_uuid) - local machine_id=$(generate_uuid) # 使用 UUID - local device_id=$(generate_uuid) - local mac_machine_id=$(openssl rand -hex 32) # 伪造 MAC 相关 ID - - # 创建注入代码块 - local inject_universal_code=" -// Cursor ID Modifier Injection - $timestamp -const originalRequire_$timestamp = typeof require === 'function' ? require : null; -if (originalRequire_$timestamp) { - require = function(module) { - try { - const result = originalRequire_$timestamp(module); - if (module === 'crypto' && result && result.randomUUID) { - const originalRandomUUID_$timestamp = result.randomUUID; - result.randomUUID = function() { return '$new_uuid'; }; - console.log('Cursor Modifier: Patched crypto.randomUUID'); - } - if (module === 'os' && result && result.networkInterfaces) { - const originalNI_$timestamp = result.networkInterfaces; - result.networkInterfaces = function() { return { lo: [{ address: '127.0.0.1', netmask: '255.0.0.0', family: 'IPv4', mac: '00:00:00:00:00:00', internal: true, cidr: '127.0.0.1/8' }]}; }; - console.log('Cursor Modifier: Patched os.networkInterfaces'); - } - return result; - } catch (e) { - console.error('Cursor Modifier: Error in require patch for module:', module, e); - // 如果原始 require 失败,可能需要返回一个空对象或抛出异常 - // 尝试调用原始 require,即使它可能已在 try 块中失败 - try { return originalRequire_$timestamp(module); } catch (innerE) { return {}; } - } - }; -} else { console.warn('Cursor Modifier: Original require not found.'); } - -// Override potential global functions or properties if they exist -try { if (typeof global !== 'undefined' && global.getMachineId) global.getMachineId = function() { return '$machine_id'; }; } catch(e){} -try { if (typeof global !== 'undefined' && global.getDeviceId) global.getDeviceId = function() { return '$device_id'; }; } catch(e){} -try { if (typeof global !== 'undefined' && global.macMachineId) global.macMachineId = '$mac_machine_id'; } catch(e){} -try { if (typeof process !== 'undefined' && process.env) process.env.VSCODE_MACHINE_ID = '$machine_id'; } catch(e){} - -console.log('Cursor Modifier: Universal patches applied (UUID: $new_uuid)'); -// End Cursor ID Modifier Injection - $timestamp - -" - # 将变量替换进代码 - inject_universal_code=${inject_universal_code//\$new_uuid/$new_uuid} - inject_universal_code=${inject_universal_code//\$machine_id/$machine_id} - inject_universal_code=${inject_universal_code//\$device_id/$device_id} - inject_universal_code=${inject_universal_code//\$mac_machine_id/$mac_machine_id} - inject_universal_code=${inject_universal_code//\$timestamp/$timestamp} # 确保时间戳替换 - - # 将代码注入到文件开头 - local temp_inject_file=$(mktemp) - echo "$inject_universal_code" > "$temp_inject_file" - cat "$file" >> "$temp_inject_file" - - if mv "$temp_inject_file" "$file"; then - log_info "完成通用注入修改" - modification_applied=true - else - log_error "通用注入失败 (无法移动临时文件)" - rm -f "$temp_inject_file" # 清理注入文件 - fi - elif [ "$modification_applied" = false ]; then - log_info "文件 '$file' 似乎已被修改过 (包含注入标记),跳过通用注入。" - # 即使未应用新修改,也认为"成功"处理(避免恢复备份) - modification_applied=true # 标记为已处理,防止恢复备份 + # 替换 someValue.devDeviceId + if grep -q 'someValue\.devDeviceId' "$file"; then + sed -i "s/someValue\.devDeviceId/${device_id}/g" "$file" + log_info " ✓ [方案A] 替换 someValue.devDeviceId" + replaced=true + fi + + # 替换 someValue.sqmId + if grep -q 'someValue\.sqmId' "$file"; then + sed -i "s/someValue\.sqmId/${sqm_id}/g" "$file" + log_info " ✓ [方案A] 替换 someValue.sqmId" + replaced=true + fi + + # 替换 someValue.sessionId(新增锚点) + if grep -q 'someValue\.sessionId' "$file"; then + sed -i "s/someValue\.sessionId/${session_id}/g" "$file" + log_info " ✓ [方案A] 替换 someValue.sessionId" + replaced=true fi - # --- 结束修改尝试 --- + # ========== 方法B: IIFE运行时劫持(crypto.randomUUID) ========== + # 使用IIFE包装,兼容webpack打包的bundle文件,无需import语法 + # 劫持crypto.randomUUID从源头拦截所有UUID生成 + local inject_code=";(function(){/*__cursor_patched__*/var _cr=require('crypto'),_orig=_cr.randomUUID;_cr.randomUUID=function(){return'${new_uuid}';};if(typeof globalThis!=='undefined'){globalThis.__cursor_machine_id='${machine_id}';globalThis.__cursor_mac_machine_id='${mac_machine_id}';globalThis.__cursor_dev_device_id='${device_id}';globalThis.__cursor_sqm_id='${sqm_id}';}try{var _os=require('os'),_origNI=_os.networkInterfaces;_os.networkInterfaces=function(){var r=_origNI.call(_os);for(var k in r){if(r[k]){for(var i=0;i "$temp_file" + cat "$file" >> "$temp_file" + + if mv "$temp_file" "$file"; then + log_info " ✓ [方案B] IIFE运行时劫持代码已注入" + + if [ "$replaced" = true ]; then + log_info "✅ [成功] A+B混合方案修改成功(someValue替换 + IIFE劫持)" + else + log_info "✅ [成功] 方案B修改成功(IIFE劫持)" + fi ((modified_count++)) - file_modification_status+=("'$file': Success") + file_modification_status+=("'$(basename "$file")': Success") + # 恢复文件权限为只读 - chmod u-w,go-w "$file" || log_warn "设置文件只读权限失败: $file" - # 设置文件所有者 - chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$file" || log_warn "设置 JS 文件所有权失败: $file" + chmod u-w,go-w "$file" 2>/dev/null || true + chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$file" 2>/dev/null || true else - log_error "未能成功应用任何修改到文件: $file" - file_modification_status+=("'$file': Failed") + log_error "IIFE注入失败 (无法移动临时文件)" + rm -f "$temp_file" + file_modification_status+=("'$(basename "$file")': Inject Failed") # 恢复备份 - log_info "正在从备份恢复文件: $file" - if cp "$backup_file" "$file"; then - chmod u-w,go-w "$file" || log_warn "恢复备份后设置只读权限失败: $file" - chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$file" || log_warn "恢复备份后设置所有权失败: $file" - else - log_error "从备份恢复文件失败: $file" - # 文件可能处于不确定状态 - fi + cp "$backup_file" "$file" 2>/dev/null || true fi - - # 清理备份文件 - rm -f "$backup_file" + + # 清理备份文件(可选保留) + # rm -f "$backup_file" done # 文件循环结束 - + # 报告每个文件的状态 - log_info "JS 文件处理状态汇总:" + log_info "📊 [统计] JS 文件处理状态汇总:" for status in "${file_modification_status[@]}"; do - log_info "- $status" + log_info " - $status" done if [ "$modified_count" -eq 0 ]; then - log_error "未能成功修改任何JS文件。请检查日志以获取详细信息。" + log_error "❌ [失败] 未能成功修改任何JS文件。" return 1 fi - - log_info "成功修改或确认了 $modified_count 个JS文件。" + + log_info "🎉 [完成] 成功修改 $modified_count 个JS文件" + log_info "💡 [说明] 使用A+B混合方案:" + log_info " • 方案A: someValue占位符替换(稳定锚点,跨版本兼容)" + log_info " • 方案B: IIFE运行时劫持(crypto.randomUUID + os.networkInterfaces)" return 0 } diff --git a/scripts/run/cursor_mac_id_modifier.sh b/scripts/run/cursor_mac_id_modifier.sh index 5d893ed..fa46980 100644 --- a/scripts/run/cursor_mac_id_modifier.sh +++ b/scripts/run/cursor_mac_id_modifier.sh @@ -1420,9 +1420,12 @@ backup_config() { fi } -# 🔧 修改Cursor内核JS文件实现设备识别绕过(新增核心功能) +# 🔧 修改Cursor内核JS文件实现设备识别绕过(A+B混合方案 - IIFE + someValue替换) +# 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名 +# 方案B: IIFE运行时劫持 - 劫持crypto.randomUUID从源头拦截 modify_cursor_js_files() { log_info "🔧 [内核修改] 开始修改Cursor内核JS文件实现设备识别绕过..." + log_info "💡 [方案] 使用A+B混合方案:someValue占位符替换 + IIFE运行时劫持" echo # 检查Cursor应用是否存在 @@ -1431,15 +1434,21 @@ modify_cursor_js_files() { return 1 fi - # 生成新的设备标识符 + # 生成新的设备标识符(使用固定格式确保兼容性) local new_uuid=$(uuidgen | tr '[:upper:]' '[:lower:]') - local machine_id="auth0|user_$(openssl rand -hex 16)" + local machine_id=$(openssl rand -hex 32) local device_id=$(uuidgen | tr '[:upper:]' '[:lower:]') local mac_machine_id=$(openssl rand -hex 32) + local sqm_id=$(uuidgen | tr '[:upper:]' '[:lower:]') + # 生成一个固定的session_id用于替换someValue.sessionId + local session_id=$(uuidgen | tr '[:upper:]' '[:lower:]') log_info "🔑 [生成] 已生成新的设备标识符" + log_info " machineId: ${machine_id:0:16}..." + log_info " deviceId: ${device_id:0:16}..." + log_info " macMachineId: ${mac_machine_id:0:16}..." - # 目标JS文件列表 + # 目标JS文件列表(按优先级排序) local js_files=( "$CURSOR_APP_PATH/Contents/Resources/app/out/vs/workbench/api/node/extensionHostProcess.js" "$CURSOR_APP_PATH/Contents/Resources/app/out/main.js" @@ -1449,7 +1458,7 @@ modify_cursor_js_files() { local modified_count=0 local need_modification=false - # 检查是否需要修改 + # 检查是否需要修改(使用统一标记) log_info "🔍 [检查] 检查JS文件修改状态..." for file in "${js_files[@]}"; do if [ ! -f "$file" ]; then @@ -1457,12 +1466,12 @@ modify_cursor_js_files() { continue fi - if ! grep -q "return crypto.randomUUID()" "$file" 2>/dev/null; then + # 检查是否已经被修改过(使用统一标记 __cursor_patched__) + if grep -q "__cursor_patched__" "$file" 2>/dev/null; then + log_info "✅ [已修改] 文件已修改: ${file/$CURSOR_APP_PATH\//}" + else log_info "📝 [需要] 文件需要修改: ${file/$CURSOR_APP_PATH\//}" need_modification=true - break - else - log_info "✅ [已修改] 文件已修改: ${file/$CURSOR_APP_PATH\//}" fi done @@ -1477,15 +1486,16 @@ modify_cursor_js_files() { # 创建备份 local timestamp=$(date +%Y%m%d_%H%M%S) - local backup_app="/tmp/Cursor.app.backup_js_${timestamp}" + local backup_dir="/tmp/Cursor_JS_Backup_${timestamp}" - log_info "💾 [备份] 创建Cursor应用备份..." - if ! cp -R "$CURSOR_APP_PATH" "$backup_app"; then - log_error "❌ [错误] 创建备份失败" - return 1 - fi - - log_info "✅ [备份] 备份创建成功: $backup_app" + log_info "💾 [备份] 创建JS文件备份..." + mkdir -p "$backup_dir" + for file in "${js_files[@]}"; do + if [ -f "$file" ]; then + cp "$file" "$backup_dir/$(basename "$file")" + fi + done + log_info "✅ [备份] 备份创建成功: $backup_dir" # 修改JS文件 log_info "🔧 [修改] 开始修改JS文件..." @@ -1499,93 +1509,80 @@ modify_cursor_js_files() { log_info "📝 [处理] 正在处理: ${file/$CURSOR_APP_PATH\//}" # 检查是否已经修改过 - if grep -q "return crypto.randomUUID()" "$file" || grep -q "// Cursor ID 修改工具注入" "$file"; then + if grep -q "__cursor_patched__" "$file"; then log_info "✅ [跳过] 文件已经被修改过" ((modified_count++)) continue fi - # 方法1: 查找IOPlatformUUID相关函数 - if grep -q "IOPlatformUUID" "$file"; then - log_info "🔍 [发现] 找到IOPlatformUUID关键字" - - # 针对不同的函数模式进行修改 - if grep -q "function a\$" "$file"; then - if sed -i.tmp 's/function a\$(t){switch/function a\$(t){return crypto.randomUUID(); switch/' "$file"; then - log_info "✅ [成功] 修改a$函数成功" - ((modified_count++)) - continue - fi - fi - - # 通用注入方法 - ES模块兼容版本 - local inject_code=" -// Cursor ID 修改工具注入 - $(date) - ES模块兼容版本 -import crypto from 'crypto'; - -// 保存原始函数引用 -const originalRandomUUID_$(date +%s) = crypto.randomUUID; - -// 重写crypto.randomUUID方法 -crypto.randomUUID = function() { - return '${new_uuid}'; -}; + # ========== 方法A: someValue占位符替换(稳定锚点) ========== + # 这些字符串是固定的占位符,不会被混淆器修改,跨版本稳定 + local replaced=false -// 覆盖所有可能的系统ID获取函数 - ES模块兼容版本 -globalThis.getMachineId = function() { return '${machine_id}'; }; -globalThis.getDeviceId = function() { return '${device_id}'; }; -globalThis.macMachineId = '${mac_machine_id}'; + # 替换 someValue.machineId + if grep -q 'someValue\.machineId' "$file"; then + sed -i.tmp "s/someValue\.machineId/${machine_id}/g" "$file" + log_info " ✓ [方案A] 替换 someValue.machineId" + replaced=true + fi -// 确保在不同环境下都能访问 -if (typeof window !== 'undefined') { - window.getMachineId = globalThis.getMachineId; - window.getDeviceId = globalThis.getDeviceId; - window.macMachineId = globalThis.macMachineId; -} + # 替换 someValue.macMachineId + if grep -q 'someValue\.macMachineId' "$file"; then + sed -i.tmp "s/someValue\.macMachineId/${mac_machine_id}/g" "$file" + log_info " ✓ [方案A] 替换 someValue.macMachineId" + replaced=true + fi -// 确保模块顶层执行 -console.log('Cursor设备标识符已成功劫持 - ES模块版本 煎饼果子(86) 关注公众号【煎饼果子卷AI】一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬)'); -" + # 替换 someValue.devDeviceId + if grep -q 'someValue\.devDeviceId' "$file"; then + sed -i.tmp "s/someValue\.devDeviceId/${device_id}/g" "$file" + log_info " ✓ [方案A] 替换 someValue.devDeviceId" + replaced=true + fi - # 替换变量 - inject_code=${inject_code//\$\{new_uuid\}/$new_uuid} - inject_code=${inject_code//\$\{machine_id\}/$machine_id} - inject_code=${inject_code//\$\{device_id\}/$device_id} - inject_code=${inject_code//\$\{mac_machine_id\}/$mac_machine_id} + # 替换 someValue.sqmId + if grep -q 'someValue\.sqmId' "$file"; then + sed -i.tmp "s/someValue\.sqmId/${sqm_id}/g" "$file" + log_info " ✓ [方案A] 替换 someValue.sqmId" + replaced=true + fi - # 注入代码到文件开头 - echo "$inject_code" > "${file}.new" - cat "$file" >> "${file}.new" - mv "${file}.new" "$file" + # 替换 someValue.sessionId(新增锚点) + if grep -q 'someValue\.sessionId' "$file"; then + sed -i.tmp "s/someValue\.sessionId/${session_id}/g" "$file" + log_info " ✓ [方案A] 替换 someValue.sessionId" + replaced=true + fi - log_info "✅ [成功] 通用注入方法修改成功" - ((modified_count++)) + # ========== 方法B: IIFE运行时劫持(crypto.randomUUID) ========== + # 使用IIFE包装,兼容webpack打包的bundle文件,无需import语法 + # 劫持crypto.randomUUID从源头拦截所有UUID生成 + local inject_code=";(function(){/*__cursor_patched__*/var _cr=require('crypto'),_orig=_cr.randomUUID;_cr.randomUUID=function(){return'${new_uuid}';};if(typeof globalThis!=='undefined'){globalThis.__cursor_machine_id='${machine_id}';globalThis.__cursor_mac_machine_id='${mac_machine_id}';globalThis.__cursor_dev_device_id='${device_id}';globalThis.__cursor_sqm_id='${sqm_id}';}try{var _os=require('os'),_origNI=_os.networkInterfaces;_os.networkInterfaces=function(){var r=_origNI.call(_os);for(var k in r){if(r[k]){for(var i=0;i "${file}.new" + cat "$file" >> "${file}.new" + mv "${file}.new" "$file" - # 修改MAC地址获取函数 - if grep -q "function t\$()" "$file"; then - sed -i.tmp 's/function t\$(){/function t\$(){return "00:00:00:00:00:00";/' "$file" - log_info "✅ [成功] 修改MAC地址获取函数" - fi + log_info " ✓ [方案B] IIFE运行时劫持代码已注入" - # 修改设备ID获取函数 - if grep -q "async function y5" "$file"; then - sed -i.tmp 's/async function y5(t){/async function y5(t){return crypto.randomUUID();/' "$file" - log_info "✅ [成功] 修改设备ID获取函数" - fi + # 清理临时文件 + rm -f "${file}.tmp" - ((modified_count++)) + if [ "$replaced" = true ]; then + log_info "✅ [成功] A+B混合方案修改成功(someValue替换 + IIFE劫持)" else - log_warn "⚠️ [警告] 未找到已知的设备ID函数模式,跳过此文件" + log_info "✅ [成功] 方案B修改成功(IIFE劫持)" fi + ((modified_count++)) done if [ $modified_count -gt 0 ]; then log_info "🎉 [完成] 成功修改 $modified_count 个JS文件" - log_info "💾 [备份] 原始文件备份位置: $backup_app" + log_info "💾 [备份] 原始文件备份位置: $backup_dir" + log_info "💡 [说明] 使用A+B混合方案:" + log_info " • 方案A: someValue占位符替换(稳定锚点,跨版本兼容)" + log_info " • 方案B: IIFE运行时劫持(crypto.randomUUID + os.networkInterfaces)" return 0 else log_error "❌ [失败] 没有成功修改任何文件" diff --git a/scripts/run/cursor_win_id_modifier.ps1 b/scripts/run/cursor_win_id_modifier.ps1 index b4f03a1..b3d6f10 100644 --- a/scripts/run/cursor_win_id_modifier.ps1 +++ b/scripts/run/cursor_win_id_modifier.ps1 @@ -24,10 +24,13 @@ function Generate-RandomString { return $result } -# 修改Cursor内核JS文件实现设备识别绕过(从macOS版本移植) +# 🔧 修改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应用路径 @@ -56,15 +59,28 @@ function Modify-CursorJSFiles { Write-Host "$GREEN✅ [发现]$NC 找到Cursor安装路径: $cursorAppPath" - # 生成新的设备标识符 + # 生成新的设备标识符(使用固定格式确保兼容性) $newUuid = [System.Guid]::NewGuid().ToString().ToLower() - $machineId = "auth0|user_$(Generate-RandomString -Length 32)" + $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() - $macMachineId = Generate-RandomString -Length 64 + $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路径) + # 目标JS文件列表(Windows路径,按优先级排序) $jsFiles = @( "$cursorAppPath\resources\app\out\vs\workbench\api\node\extensionHostProcess.js", "$cursorAppPath\resources\app\out\main.js", @@ -74,7 +90,7 @@ function Modify-CursorJSFiles { $modifiedCount = 0 $needModification = $false - # 检查是否需要修改 + # 检查是否需要修改(使用统一标记 __cursor_patched__) Write-Host "$BLUE🔍 [检查]$NC 检查JS文件修改状态..." foreach ($file in $jsFiles) { if (-not (Test-Path $file)) { @@ -83,12 +99,11 @@ function Modify-CursorJSFiles { } $content = Get-Content $file -Raw -ErrorAction SilentlyContinue - if ($content -and $content -notmatch "return crypto\.randomUUID\(\)") { + 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 - break - } else { - Write-Host "$GREEN✅ [已修改]$NC 文件已修改: $(Split-Path $file -Leaf)" } } @@ -134,88 +149,72 @@ function Modify-CursorJSFiles { try { $content = Get-Content $file -Raw -Encoding UTF8 - # 检查是否已经修改过 - if ($content -match "return crypto\.randomUUID\(\)" -or $content -match "// Cursor ID 修改工具注入") { + # 检查是否已经修改过(使用统一标记) + if ($content -match "__cursor_patched__") { Write-Host "$GREEN✅ [跳过]$NC 文件已经被修改过" $modifiedCount++ continue } - # ES模块兼容的JavaScript注入代码 - $timestampVar = [DateTimeOffset]::Now.ToUnixTimeSeconds() - $injectCode = @" -// Cursor ID 修改工具注入 - $(Get-Date) - ES模块兼容版本 -import crypto from 'crypto'; - -// 保存原始函数引用 -const originalRandomUUID_${timestampVar} = crypto.randomUUID; - -// 重写crypto.randomUUID方法 -crypto.randomUUID = function() { - return '${newUuid}'; -}; - -// 覆盖所有可能的系统ID获取函数 - ES模块兼容版本 -globalThis.getMachineId = function() { return '${machineId}'; }; -globalThis.getDeviceId = function() { return '${deviceId}'; }; -globalThis.macMachineId = '${macMachineId}'; - -// 确保在不同环境下都能访问 -if (typeof window !== 'undefined') { - window.getMachineId = globalThis.getMachineId; - window.getDeviceId = globalThis.getDeviceId; - window.macMachineId = globalThis.macMachineId; -} - -// 确保模块顶层执行 -console.log('Cursor设备标识符已成功劫持 - ES模块版本 煎饼果子(86) 关注公众号【煎饼果子卷AI】一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬)'); - -"@ + $replaced = $false - # 方法1: 查找IOPlatformUUID相关函数 - if ($content -match "IOPlatformUUID") { - Write-Host "$BLUE🔍 [发现]$NC 找到IOPlatformUUID关键字" + # ========== 方法A: someValue占位符替换(稳定锚点) ========== + # 这些字符串是固定的占位符,不会被混淆器修改,跨版本稳定 - # 针对不同的函数模式进行修改 - if ($content -match "function a\$") { - $content = $content -replace "function a\$\(t\)\{switch", "function a`$(t){return crypto.randomUUID(); switch" - Write-Host "$GREEN✅ [成功]$NC 修改a`$函数成功" - $modifiedCount++ - continue - } + # 替换 someValue.machineId + if ($content -match 'someValue\.machineId') { + $content = $content -replace 'someValue\.machineId', $machineId + Write-Host " $GREEN✓$NC [方案A] 替换 someValue.machineId" + $replaced = $true + } - # 通用注入方法 - $content = $injectCode + $content - Write-Host "$GREEN✅ [成功]$NC 通用注入方法修改成功" - $modifiedCount++ + # 替换 someValue.macMachineId + if ($content -match 'someValue\.macMachineId') { + $content = $content -replace 'someValue\.macMachineId', $macMachineId + Write-Host " $GREEN✓$NC [方案A] 替换 someValue.macMachineId" + $replaced = $true } - # 方法2: 查找其他设备ID相关函数 - elseif ($content -match "function t\$\(\)" -or $content -match "async function y5") { - Write-Host "$BLUE🔍 [发现]$NC 找到设备ID相关函数" - - # 修改MAC地址获取函数 - if ($content -match "function t\$\(\)") { - $content = $content -replace "function t\$\(\)\{", "function t`$(){return `"00:00:00:00:00:00`";" - Write-Host "$GREEN✅ [成功]$NC 修改MAC地址获取函数" - } - # 修改设备ID获取函数 - if ($content -match "async function y5") { - $content = $content -replace "async function y5\(t\)\{", "async function y5(t){return crypto.randomUUID();" - Write-Host "$GREEN✅ [成功]$NC 修改设备ID获取函数" - } + # 替换 someValue.devDeviceId + if ($content -match 'someValue\.devDeviceId') { + $content = $content -replace 'someValue\.devDeviceId', $deviceId + Write-Host " $GREEN✓$NC [方案A] 替换 someValue.devDeviceId" + $replaced = $true + } - $modifiedCount++ + # 替换 someValue.sqmId + if ($content -match 'someValue\.sqmId') { + $content = $content -replace 'someValue\.sqmId', $sqmId + Write-Host " $GREEN✓$NC [方案A] 替换 someValue.sqmId" + $replaced = $true } - else { - Write-Host "$YELLOW⚠️ [警告]$NC 未找到已知的设备ID函数模式,使用通用注入" - $content = $injectCode + $content - $modifiedCount++ + + # 替换 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文件,无需import语法 + # 劫持crypto.randomUUID从源头拦截所有UUID生成 + $injectCode = ";(function(){/*__cursor_patched__*/var _cr=require('crypto'),_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';}try{var _os=require('os'),_origNI=_os.networkInterfaces;_os.networkInterfaces=function(){var r=_origNI.call(_os);for(var k in r){if(r[k]){for(var i=0;i