From 84dfc62342e87f827d0835151378cae077463839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=85=8E=E9=A5=BC=E6=9E=9C=E5=AD=90=E5=8D=B7=E9=B2=A8?= =?UTF-8?q?=E9=B1=BC=E8=BE=A3=E6=A4=92?= Date: Tue, 13 Jan 2026 22:00:41 +0800 Subject: [PATCH] =?UTF-8?q?```=20feat(cursor-modifier):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0ID=E5=90=8C=E6=AD=A5=E6=9C=BA=E5=88=B6=E7=A1=AE?= =?UTF-8?q?=E4=BF=9D=E9=85=8D=E7=BD=AE=E4=B8=8EJS=E6=B3=A8=E5=85=A5?= =?UTF-8?q?=E4=B8=80=E8=87=B4=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增全局ID变量存储机制,包括machineId、macMachineId、deviceId等 - 实现配置文件ID读取功能,优先使用现有配置保持一致性 - 添加ID规范化处理,确保十六进制格式正确性 - 在JS注入时复用配置中的ID,避免设备识别冲突 - 改进错误处理和日志输出,提供更好的调试信息 fix(cursor-modifier): 修复设备识别绕过和更新禁用功能 - 在Mac版本中添加智能设备识别绕过,优先尝试MAC地址修改 - 实现Windows版本的自动更新禁用功能 - 修复JS文件修改时的ID生成逻辑,确保与配置文件同步 - 添加配置文件保护机制,设置只读权限防止意外修改 - 优化脚本执行流程,确保各步骤正确执行 ``` --- scripts/run/cursor_linux_id_modifier.sh | 188 ++++++++++++++++++++++-- scripts/run/cursor_mac_id_modifier.sh | 146 +++++++++++++++--- scripts/run/cursor_win_id_modifier.ps1 | 182 ++++++++++++++++++++--- 3 files changed, 465 insertions(+), 51 deletions(-) diff --git a/scripts/run/cursor_linux_id_modifier.sh b/scripts/run/cursor_linux_id_modifier.sh index b3044af..c04f679 100755 --- a/scripts/run/cursor_linux_id_modifier.sh +++ b/scripts/run/cursor_linux_id_modifier.sh @@ -70,6 +70,15 @@ CURSOR_CONFIG_DIR="$HOME/.config/Cursor" STORAGE_FILE="$CURSOR_CONFIG_DIR/User/globalStorage/storage.json" BACKUP_DIR="$CURSOR_CONFIG_DIR/User/globalStorage/backups" +# 共享ID(用于配置与JS注入保持一致) +CURSOR_ID_MACHINE_ID="" +CURSOR_ID_MAC_MACHINE_ID="" +CURSOR_ID_DEVICE_ID="" +CURSOR_ID_SQM_ID="" +CURSOR_ID_FIRST_SESSION_DATE="" +CURSOR_ID_SESSION_ID="" +CURSOR_ID_MAC_ADDRESS="00:11:22:33:44:55" + # --- 新增:安装相关变量 --- APPIMAGE_SEARCH_DIR="/opt/CursorInstall" # AppImage 搜索目录,可按需修改 APPIMAGE_PATTERN="Cursor-*.AppImage" # AppImage 文件名模式 @@ -432,6 +441,102 @@ generate_uuid() { fi } +# 规范化 machineId(确保为十六进制字符串) +normalize_machine_id() { + local raw="$1" + local cleaned + cleaned=$(echo "$raw" | tr -d '-' | tr '[:upper:]' '[:lower:]') + if [[ "$cleaned" =~ ^[0-9a-f]{32,}$ ]]; then + echo "$cleaned" + return 0 + fi + return 1 +} + +# 从现有配置读取ID(用于JS注入保持一致) +load_ids_from_storage() { + if [ ! -f "$STORAGE_FILE" ]; then + return 1 + fi + + if ! command -v python3 >/dev/null 2>&1; then + log_warn "未检测到 python3,无法从现有配置读取 ID" + return 1 + fi + + local output + output=$(python3 - "$STORAGE_FILE" <<'PY' +import json, sys +path = sys.argv[1] +with open(path, "r", encoding="utf-8") as f: + data = json.load(f) + +def pick(keys): + for k in keys: + v = data.get(k) + if isinstance(v, str) and v: + return v + return "" + +items = { + "machineId": pick(["telemetry.machineId", "machineId"]), + "macMachineId": pick(["telemetry.macMachineId"]), + "devDeviceId": pick(["telemetry.devDeviceId", "deviceId"]), + "sqmId": pick(["telemetry.sqmId"]), + "firstSessionDate": pick(["telemetry.firstSessionDate"]), +} + +for k, v in items.items(): + print(f"{k}={v}") +PY +) + if [ $? -ne 0 ] || [ -z "$output" ]; then + return 1 + fi + + while IFS='=' read -r key value; do + case "$key" in + machineId) CURSOR_ID_MACHINE_ID="$value" ;; + macMachineId) CURSOR_ID_MAC_MACHINE_ID="$value" ;; + devDeviceId) CURSOR_ID_DEVICE_ID="$value" ;; + sqmId) CURSOR_ID_SQM_ID="$value" ;; + firstSessionDate) CURSOR_ID_FIRST_SESSION_DATE="$value" ;; + esac + done <<< "$output" + + if [ -n "$CURSOR_ID_MACHINE_ID" ]; then + local normalized + if normalized=$(normalize_machine_id "$CURSOR_ID_MACHINE_ID"); then + if [ "$normalized" != "$CURSOR_ID_MACHINE_ID" ]; then + log_warn "machineId 非标准格式,JS 注入将使用去除连字符后的值" + fi + CURSOR_ID_MACHINE_ID="$normalized" + else + log_warn "machineId 无法识别为十六进制,JS 注入将改用新值" + CURSOR_ID_MACHINE_ID="" + fi + fi + + CURSOR_ID_SESSION_ID=$(generate_uuid) + CURSOR_ID_MAC_ADDRESS="${CURSOR_ID_MAC_ADDRESS:-00:11:22:33:44:55}" + + if [ -n "$CURSOR_ID_MACHINE_ID" ] && [ -n "$CURSOR_ID_MAC_MACHINE_ID" ] && [ -n "$CURSOR_ID_DEVICE_ID" ] && [ -n "$CURSOR_ID_SQM_ID" ]; then + return 0 + fi + return 1 +} + +# 仅用于JS注入的ID生成(不写配置) +generate_ids_for_js_only() { + CURSOR_ID_MACHINE_ID=$(openssl rand -hex 32) + CURSOR_ID_MAC_MACHINE_ID=$(openssl rand -hex 32) + CURSOR_ID_DEVICE_ID=$(generate_uuid) + CURSOR_ID_SQM_ID="{$(generate_uuid | tr '[:lower:]' '[:upper:]')}" + CURSOR_ID_FIRST_SESSION_DATE=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") + CURSOR_ID_SESSION_ID=$(generate_uuid) + CURSOR_ID_MAC_ADDRESS="${CURSOR_ID_MAC_ADDRESS:-00:11:22:33:44:55}" +} + # 修改现有文件 modify_or_add_config() { local key="$1" @@ -511,8 +616,10 @@ generate_new_config() { log_warn "机器码重置选项" # 使用菜单选择函数询问用户是否重置机器码 + set +e select_menu_option "是否需要重置机器码? (通常情况下,只修改js文件即可):" "不重置 - 仅修改js文件即可|重置 - 同时修改配置文件和机器码" 0 reset_choice=$? + set -e # 记录日志以便调试 echo "[INPUT_DEBUG] 机器码重置选项选择: $reset_choice" >> "$LOG_FILE" @@ -538,7 +645,7 @@ generate_new_config() { # 生成并设置新的设备ID local new_device_id=$(generate_uuid) - local new_machine_id=$(generate_uuid) # 使用 UUID 作为 Machine ID 更常见 + local new_machine_id=$(openssl rand -hex 32) # 🔧 新增: serviceMachineId (用于 storage.serviceMachineId) local new_service_machine_id=$(generate_uuid) # 🔧 新增: firstSessionDate (重置首次会话日期) @@ -547,6 +654,14 @@ generate_new_config() { local new_mac_machine_id=$(openssl rand -hex 32 2>/dev/null || head -c 32 /dev/urandom | xxd -p | tr -d '\n') local new_sqm_id="{$(generate_uuid | tr '[:lower:]' '[:upper:]')}" + CURSOR_ID_MACHINE_ID="$new_machine_id" + CURSOR_ID_MAC_MACHINE_ID="$new_mac_machine_id" + CURSOR_ID_DEVICE_ID="$new_device_id" + CURSOR_ID_SQM_ID="$new_sqm_id" + CURSOR_ID_FIRST_SESSION_DATE="$new_first_session_date" + CURSOR_ID_SESSION_ID=$(generate_uuid) + CURSOR_ID_MAC_ADDRESS="${CURSOR_ID_MAC_ADDRESS:-00:11:22:33:44:55}" + log_info "正在设置新的设备和机器ID..." log_debug "新设备ID: $new_device_id" log_debug "新机器ID: $new_machine_id" @@ -634,8 +749,16 @@ generate_new_config() { log_error "配置文件备份失败,中止操作。" return 1 # 返回错误状态 fi + if load_ids_from_storage; then + log_info "已从现有配置读取 ID,JS 注入将保持一致" + else + log_warn "无法从现有配置读取 ID,JS 注入将使用新生成的 ID(不会修改配置)" + generate_ids_for_js_only + fi else log_warn "未找到配置文件 '$STORAGE_FILE',跳过备份。" + log_warn "无法读取现有ID,JS 注入将使用新生成的 ID(不会修改配置)" + generate_ids_for_js_only fi fi @@ -736,17 +859,56 @@ modify_cursor_js_files() { 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 | tr '[:lower:]' '[:upper:]')}" - local session_id=$(generate_uuid) - local first_session_date=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") - local mac_address="00:11:22:33:44:55" - - log_info "🔑 [生成] 已生成新的设备标识符" + # 生成或复用设备标识符(优先使用配置中读取的值) + local machine_id="${CURSOR_ID_MACHINE_ID:-}" + local device_id="${CURSOR_ID_DEVICE_ID:-}" + local mac_machine_id="${CURSOR_ID_MAC_MACHINE_ID:-}" + local sqm_id="${CURSOR_ID_SQM_ID:-}" + local session_id="${CURSOR_ID_SESSION_ID:-}" + local first_session_date="${CURSOR_ID_FIRST_SESSION_DATE:-}" + local mac_address="${CURSOR_ID_MAC_ADDRESS:-00:11:22:33:44:55}" + local ids_missing=false + + if [ -z "$machine_id" ]; then + machine_id=$(openssl rand -hex 32) + ids_missing=true + fi + if [ -z "$device_id" ]; then + device_id=$(generate_uuid) + ids_missing=true + fi + if [ -z "$mac_machine_id" ]; then + mac_machine_id=$(openssl rand -hex 32) + ids_missing=true + fi + if [ -z "$sqm_id" ]; then + sqm_id="{$(generate_uuid | tr '[:lower:]' '[:upper:]')}" + ids_missing=true + fi + if [ -z "$session_id" ]; then + session_id=$(generate_uuid) + ids_missing=true + fi + if [ -z "$first_session_date" ]; then + first_session_date=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") + ids_missing=true + fi + + if [ "$ids_missing" = true ]; then + log_warn "部分 ID 未从配置获取,已生成新值用于 JS 注入" + else + log_info "已使用配置中的设备标识符进行 JS 注入" + fi + + CURSOR_ID_MACHINE_ID="$machine_id" + CURSOR_ID_DEVICE_ID="$device_id" + CURSOR_ID_MAC_MACHINE_ID="$mac_machine_id" + CURSOR_ID_SQM_ID="$sqm_id" + CURSOR_ID_SESSION_ID="$session_id" + CURSOR_ID_FIRST_SESSION_DATE="$first_session_date" + CURSOR_ID_MAC_ADDRESS="$mac_address" + + log_info "🔑 [准备] 设备标识符已就绪" log_info " machineId: ${machine_id:0:16}..." log_info " deviceId: ${device_id:0:16}..." log_info " macMachineId: ${mac_machine_id:0:16}..." @@ -1354,8 +1516,10 @@ main() { # 查找 Cursor 路径 if ! find_cursor_path; then log_warn "系统中未找到现有的 Cursor 安装。" + set +e select_menu_option "是否尝试从 '$APPIMAGE_SEARCH_DIR' 目录中的 AppImage 文件安装 Cursor?" "是,安装 Cursor|否,退出脚本" 0 install_choice=$? + set -e if [ "$install_choice" -eq 0 ]; then if ! install_cursor_appimage; then diff --git a/scripts/run/cursor_mac_id_modifier.sh b/scripts/run/cursor_mac_id_modifier.sh index d7b644c..85cd53e 100644 --- a/scripts/run/cursor_mac_id_modifier.sh +++ b/scripts/run/cursor_mac_id_modifier.sh @@ -446,13 +446,21 @@ except Exception as e: # 生成新的ID local MAC_MACHINE_ID=$(uuidgen | tr '[:upper:]' '[:lower:]') local UUID=$(uuidgen | tr '[:upper:]' '[:lower:]') - local MACHINE_ID="auth0|user_$(openssl rand -hex 32)" + local MACHINE_ID=$(openssl rand -hex 32) local SQM_ID="{$(uuidgen | tr '[:lower:]' '[:upper:]')}" # 🔧 新增: serviceMachineId (用于 storage.serviceMachineId) local SERVICE_MACHINE_ID=$(uuidgen | tr '[:upper:]' '[:lower:]') # 🔧 新增: firstSessionDate (重置首次会话日期) local FIRST_SESSION_DATE=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") + CURSOR_ID_MACHINE_ID="$MACHINE_ID" + CURSOR_ID_MAC_MACHINE_ID="$MAC_MACHINE_ID" + CURSOR_ID_DEVICE_ID="$UUID" + CURSOR_ID_SQM_ID="$SQM_ID" + CURSOR_ID_FIRST_SESSION_DATE="$FIRST_SESSION_DATE" + CURSOR_ID_SESSION_ID=$(uuidgen | tr '[:upper:]' '[:lower:]') + CURSOR_ID_MAC_ADDRESS="${CURSOR_ID_MAC_ADDRESS:-00:11:22:33:44:55}" + log_info "✅ [进度] 1/5 - 设备标识符生成完成" log_info "⏳ [进度] 2/5 - 创建备份目录..." @@ -745,6 +753,15 @@ TARGET_HOME="$(get_user_home_dir "$TARGET_USER")" STORAGE_FILE="$TARGET_HOME/Library/Application Support/Cursor/User/globalStorage/storage.json" BACKUP_DIR="$TARGET_HOME/Library/Application Support/Cursor/User/globalStorage/backups" +# 共享ID(用于配置与JS注入保持一致) +CURSOR_ID_MACHINE_ID="" +CURSOR_ID_MAC_MACHINE_ID="" +CURSOR_ID_DEVICE_ID="" +CURSOR_ID_SQM_ID="" +CURSOR_ID_FIRST_SESSION_DATE="" +CURSOR_ID_SESSION_ID="" +CURSOR_ID_MAC_ADDRESS="00:11:22:33:44:55" + # 定义 Cursor 应用程序路径 CURSOR_APP_PATH="/Applications/Cursor.app" @@ -1417,6 +1434,40 @@ _show_troubleshooting_info() { echo } +# 智能设备识别绕过(优先MAC地址修改,失败则JS注入) +run_device_bypass() { + log_info "🔧 [设备识别] 开始执行智能设备识别绕过..." + + 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 + fi + + log_error "❌ [JS] JS 内核注入失败" + return 1 +} + # 检查权限 check_permissions() { if [ "$EUID" -ne 0 ]; then @@ -1510,6 +1561,17 @@ backup_config() { fi } +# 重新设置配置文件只读(避免权限修复覆盖) +protect_storage_file() { + if [ -f "$STORAGE_FILE" ]; then + if chmod 444 "$STORAGE_FILE" 2>/dev/null; then + log_info "🔒 [保护] 配置文件已重新设置为只读" + else + log_warn "⚠️ [保护] 配置文件只读设置失败" + fi + fi +} + # 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版 Hook 方案) # 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名 # 方案B: 深度 Hook 注入 - 从底层拦截所有设备标识符生成 @@ -1525,17 +1587,56 @@ modify_cursor_js_files() { return 1 fi - # 生成新的设备标识符(使用固定格式确保兼容性) - local new_uuid=$(uuidgen | tr '[:upper:]' '[:lower:]') - 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 '[:lower:]' '[:upper:]')}" - local session_id=$(uuidgen | tr '[:upper:]' '[:lower:]') - local first_session_date=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") - local mac_address="00:11:22:33:44:55" + # 生成或复用设备标识符(优先使用配置中生成的值) + local machine_id="${CURSOR_ID_MACHINE_ID:-}" + local device_id="${CURSOR_ID_DEVICE_ID:-}" + local mac_machine_id="${CURSOR_ID_MAC_MACHINE_ID:-}" + local sqm_id="${CURSOR_ID_SQM_ID:-}" + local session_id="${CURSOR_ID_SESSION_ID:-}" + local first_session_date="${CURSOR_ID_FIRST_SESSION_DATE:-}" + local mac_address="${CURSOR_ID_MAC_ADDRESS:-00:11:22:33:44:55}" + local ids_missing=false - log_info "🔑 [生成] 已生成新的设备标识符" + if [ -z "$machine_id" ]; then + machine_id=$(openssl rand -hex 32) + ids_missing=true + fi + if [ -z "$device_id" ]; then + device_id=$(uuidgen | tr '[:upper:]' '[:lower:]') + ids_missing=true + fi + if [ -z "$mac_machine_id" ]; then + mac_machine_id=$(openssl rand -hex 32) + ids_missing=true + fi + if [ -z "$sqm_id" ]; then + sqm_id="{$(uuidgen | tr '[:lower:]' '[:upper:]')}" + ids_missing=true + fi + if [ -z "$session_id" ]; then + session_id=$(uuidgen | tr '[:upper:]' '[:lower:]') + ids_missing=true + fi + if [ -z "$first_session_date" ]; then + first_session_date=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") + ids_missing=true + fi + + if [ "$ids_missing" = true ]; then + log_warn "部分 ID 未就绪,已生成新值用于 JS 注入" + else + log_info "已使用配置中的设备标识符进行 JS 注入" + fi + + CURSOR_ID_MACHINE_ID="$machine_id" + CURSOR_ID_DEVICE_ID="$device_id" + CURSOR_ID_MAC_MACHINE_ID="$mac_machine_id" + CURSOR_ID_SQM_ID="$sqm_id" + CURSOR_ID_SESSION_ID="$session_id" + CURSOR_ID_FIRST_SESSION_DATE="$first_session_date" + CURSOR_ID_MAC_ADDRESS="$mac_address" + + log_info "🔑 [准备] 设备标识符已就绪" log_info " machineId: ${machine_id:0:16}..." log_info " deviceId: ${device_id:0:16}..." log_info " macMachineId: ${mac_machine_id:0:16}..." @@ -1543,7 +1644,7 @@ modify_cursor_js_files() { # 保存 ID 配置到用户目录(供 Hook 读取) # 每次执行都删除旧配置并重新生成,确保获得新的设备标识符 - local ids_config_path="$HOME/.cursor_ids.json" + local ids_config_path="$TARGET_HOME/.cursor_ids.json" if [ -f "$ids_config_path" ]; then rm -f "$ids_config_path" log_info "🗑️ [清理] 已删除旧的 ID 配置文件" @@ -2692,6 +2793,7 @@ main() { echo echo -e "${BLUE} 1️⃣ 仅修改机器码${NC}" echo -e "${YELLOW} • 仅执行机器码修改功能${NC}" + echo -e "${YELLOW} • 同步执行 JS 内核注入${NC}" echo -e "${YELLOW} • 跳过文件夹删除/环境重置步骤${NC}" echo -e "${YELLOW} • 保留现有Cursor配置和数据${NC}" echo @@ -2733,7 +2835,8 @@ main() { echo -e "${BLUE} 1️⃣ 检测Cursor配置文件${NC}" echo -e "${BLUE} 2️⃣ 备份现有配置文件${NC}" echo -e "${BLUE} 3️⃣ 修改机器码配置${NC}" - echo -e "${BLUE} 4️⃣ 显示操作完成信息${NC}" + echo -e "${BLUE} 4️⃣ 执行 JS 内核注入${NC}" + echo -e "${BLUE} 5️⃣ 显示操作完成信息${NC}" echo echo -e "${YELLOW}⚠️ [注意事项]${NC}" echo -e "${YELLOW} • 不会删除任何文件夹或重置环境${NC}" @@ -2800,14 +2903,18 @@ main() { echo log_info "🎉 [完成] 机器码修改完成!" log_info "💡 [提示] 现在可以启动Cursor使用新的机器码配置" + echo + log_info "🔧 [设备识别] 正在执行 JS 内核注入..." + if modify_cursor_js_files; then + log_info "✅ [设备识别] JS 内核注入完成" + else + log_warn "⚠️ [设备识别] JS 内核注入失败,请检查日志" + fi else echo log_error "❌ [失败] 机器码修改失败!" log_info "💡 [建议] 请尝试'重置环境+修改机器码'选项" fi - - - # 🚫 禁用自动更新(仅修改模式也需要) echo log_info "🚫 [禁用更新] 正在禁用Cursor自动更新..." @@ -2860,7 +2967,10 @@ main() { # 🔧 智能设备识别绕过(MAC地址修改或JS内核修改) echo log_info "🔧 [设备识别] 开始智能设备识别绕过..." - log_info "💡 [说明] 将根据系统环境自动选择最佳方案(MAC地址修改或JS内核修改)" + log_info "💡 [说明] 将优先尝试 MAC 地址修改,失败则使用 JS 内核注入" + if ! run_device_bypass; then + log_warn "⚠️ [设备识别] 智能设备识别绕过未完全成功,请查看日志" + fi # 🔧 关键修复:修复应用签名问题(防止"应用已损坏"错误) @@ -2909,6 +3019,7 @@ main() { echo log_info "🛡️ [最终权限修复] 执行脚本完成前的最终权限修复..." ensure_cursor_directory_permissions + protect_storage_file # 🎉 脚本执行完成 log_info "🎉 [完成] 所有操作已完成!" @@ -2936,4 +3047,3 @@ main() { # 执行主函数 main - diff --git a/scripts/run/cursor_win_id_modifier.ps1 b/scripts/run/cursor_win_id_modifier.ps1 index d78b661..0d71ccf 100644 --- a/scripts/run/cursor_win_id_modifier.ps1 +++ b/scripts/run/cursor_win_id_modifier.ps1 @@ -60,24 +60,40 @@ function Modify-CursorJSFiles { 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().ToUpper() + "}" - $sessionId = [System.Guid]::NewGuid().ToString().ToLower() - $macAddress = "00:11:22:33:44:55" - - Write-Host "$GREEN🔑 [生成]$NC 已生成新的设备标识符" + # 生成或复用设备标识符(优先使用配置中生成的值) + $useConfigIds = $false + if ($global:CursorIds -and $global:CursorIds.machineId -and $global:CursorIds.macMachineId -and $global:CursorIds.devDeviceId -and $global:CursorIds.sqmId) { + $machineId = [string]$global:CursorIds.machineId + $macMachineId = [string]$global:CursorIds.macMachineId + $deviceId = [string]$global:CursorIds.devDeviceId + $sqmId = [string]$global:CursorIds.sqmId + $sessionId = if ($global:CursorIds.sessionId) { [string]$global:CursorIds.sessionId } else { [System.Guid]::NewGuid().ToString().ToLower() } + $firstSessionDateValue = if ($global:CursorIds.firstSessionDate) { [string]$global:CursorIds.firstSessionDate } else { (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") } + $macAddress = if ($global:CursorIds.macAddress) { [string]$global:CursorIds.macAddress } else { "00:11:22:33:44:55" } + $useConfigIds = $true + } else { + $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().ToUpper() + "}" + $sessionId = [System.Guid]::NewGuid().ToString().ToLower() + $firstSessionDateValue = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") + $macAddress = "00:11:22:33:44:55" + } + + if ($useConfigIds) { + Write-Host "$GREEN🔑 [准备]$NC 已使用配置中的设备标识符" + } else { + 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))..." @@ -96,7 +112,7 @@ function Modify-CursorJSFiles { devDeviceId = $deviceId sqmId = $sqmId macAddress = $macAddress - createdAt = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") + createdAt = $firstSessionDateValue } $idsConfig | ConvertTo-Json | Set-Content -Path $idsConfigPath -Encoding UTF8 Write-Host "$GREEN💾 [保存]$NC 新的 ID 配置已保存到: $idsConfigPath" @@ -162,7 +178,7 @@ function Modify-CursorJSFiles { } # 修改JS文件(每次都重新注入,因为已从原始备份恢复) - Write-Host "$BLUE🔧 [修改]$NC 开始修改JS文件(使用新的设备标识符)..." + Write-Host "$BLUE🔧 [修改]$NC 开始修改JS文件(使用设备标识符)..." foreach ($file in $jsFiles) { if (-not (Test-Path $file)) { @@ -185,7 +201,9 @@ function Modify-CursorJSFiles { # 因此这里优先替换完整的字符串字面量(包含外层引号),并使用 JSON 字符串字面量确保转义安全。 # 🔧 新增: firstSessionDate(重置首次会话日期) - $firstSessionDateValue = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") + if (-not $firstSessionDateValue) { + $firstSessionDateValue = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") + } $placeholders = @( @{ Name = 'someValue.machineId'; Value = [string]$machineId }, @@ -871,6 +889,100 @@ function Update-MachineGuid { } } +# 🚫 禁用 Cursor 自动更新(Windows) +function Disable-CursorAutoUpdate { + Write-Host "" + Write-Host "$BLUE🚫 [禁用更新]$NC 正在尝试禁用 Cursor 自动更新..." + + # 检测 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 "$YELLOW⚠️ [警告]$NC 未找到 Cursor 安装路径,跳过禁用更新" + return $false + } + + # 更新配置文件(JSON/YAML) + $updateFiles = @( + "$cursorAppPath\resources\app-update.yml", + "$cursorAppPath\resources\app\update-config.json", + "$env:APPDATA\Cursor\update-config.json", + "$env:APPDATA\Cursor\settings.json" + ) + + foreach ($file in $updateFiles) { + if (-not (Test-Path $file)) { continue } + + try { + Copy-Item $file "$file.bak_$(Get-Date -Format 'yyyyMMdd_HHmmss')" -Force + } catch { + Write-Host "$YELLOW⚠️ [警告]$NC 备份失败: $file" + } + + if ($file -like "*.yml") { + Set-Content -Path $file -Value "# update disabled by script $(Get-Date)" -Encoding UTF8 + Write-Host "$GREEN✅ [完成]$NC 已处理更新配置: $file" + continue + } + + if ($file -like "*update-config.json") { + $config = @{ autoCheck = $false; autoDownload = $false } + $config | ConvertTo-Json -Depth 5 | Set-Content -Path $file -Encoding UTF8 + Write-Host "$GREEN✅ [完成]$NC 已处理更新配置: $file" + continue + } + + if ($file -like "*settings.json") { + try { + $settings = Get-Content $file -Raw -Encoding UTF8 | ConvertFrom-Json -ErrorAction Stop + } catch { + $settings = @{} + } + if ($settings -is [hashtable]) { + $settings["update.mode"] = "none" + } else { + $settings | Add-Member -MemberType NoteProperty -Name "update.mode" -Value "none" -Force + } + $settings | ConvertTo-Json -Depth 10 | Set-Content -Path $file -Encoding UTF8 + Write-Host "$GREEN✅ [完成]$NC 已处理更新配置: $file" + continue + } + } + + # 尝试禁用更新器可执行文件 + $updaterCandidates = @( + "$cursorAppPath\Update.exe", + "$env:LOCALAPPDATA\Cursor\Update.exe", + "$cursorAppPath\CursorUpdater.exe" + ) + + foreach ($updater in $updaterCandidates) { + if (-not (Test-Path $updater)) { continue } + $backup = "$updater.bak_$(Get-Date -Format 'yyyyMMdd_HHmmss')" + try { + Move-Item -Path $updater -Destination $backup -Force + Write-Host "$GREEN✅ [完成]$NC 已禁用更新器: $updater" + } catch { + Write-Host "$YELLOW⚠️ [警告]$NC 更新器禁用失败: $updater" + } + } + + return $true +} + # 检查配置文件和环境 function Test-CursorEnvironment { param( @@ -1044,6 +1156,18 @@ function Modify-MachineCodeConfig { $SERVICE_MACHINE_ID = [System.Guid]::NewGuid().ToString() # 🔧 新增: firstSessionDate (重置首次会话日期) $FIRST_SESSION_DATE = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") + $SESSION_ID = [System.Guid]::NewGuid().ToString() + + # 共享ID(用于配置与JS注入保持一致) + $global:CursorIds = @{ + machineId = $MACHINE_ID + macMachineId = $MAC_MACHINE_ID + devDeviceId = $UUID + sqmId = $SQM_ID + firstSessionDate = $FIRST_SESSION_DATE + sessionId = $SESSION_ID + macAddress = "00:11:22:33:44:55" + } Write-Host "$GREEN✅ [进度]$NC 1/7 - 设备标识符生成完成" @@ -1745,6 +1869,14 @@ if ($executeMode -eq "MODIFY_ONLY") { } } + Write-Host "" + Write-Host "$BLUE🚫 [禁用更新]$NC 正在禁用 Cursor 自动更新..." + if (Disable-CursorAutoUpdate) { + Write-Host "$GREEN✅ [禁用更新]$NC 自动更新已处理" + } else { + Write-Host "$YELLOW⚠️ [禁用更新]$NC 未能确认禁用更新,可能需要手动处理" + } + Write-Host "$BLUE💡 [提示]$NC 现在可以启动Cursor使用新的机器码配置" } else { Write-Host "" @@ -1873,6 +2005,14 @@ if ($executeMode -eq "MODIFY_ONLY") { Write-Host "$BLUE💡 [建议]$NC 可手动右键文件 → 属性 → 勾选'只读'" } } + + Write-Host "" + Write-Host "$BLUE🚫 [禁用更新]$NC 正在禁用 Cursor 自动更新..." + if (Disable-CursorAutoUpdate) { + Write-Host "$GREEN✅ [禁用更新]$NC 自动更新已处理" + } else { + Write-Host "$YELLOW⚠️ [禁用更新]$NC 未能确认禁用更新,可能需要手动处理" + } } else { Write-Host "" Write-Host "$RED❌ [失败]$NC 机器码配置修改失败!"