@ -37,6 +37,43 @@ YELLOW='\033[1;33m'
BLUE = '\033[0;34m'
BLUE = '\033[0;34m'
NC = '\033[0m' # No Color
NC = '\033[0m' # No Color
# 启动时尝试调整终端窗口大小为 120x40(列x行);不支持/失败时静默忽略,避免影响脚本主流程
try_resize_terminal_window( ) {
local target_cols = 120
local target_rows = 40
# 仅在交互终端中尝试,避免输出被重定向时出现乱码
if [ ! -t 1 ] ; then
return 0
fi
case " ${ TERM :- } " in
"" | dumb)
return 0
; ;
esac
# 终端类型检测:仅对常见 xterm 体系终端尝试窗口调整(Terminal.app/iTerm2 以及常见终端通常为 xterm*)
case " ${ TERM :- } " in
xterm*| screen*| tmux*| rxvt*| alacritty*| kitty*| foot*| wezterm*)
; ;
*)
return 0
; ;
esac
# 优先通过 xterm 窗口控制序列调整;在 tmux/screen 下需要 passthrough 包装
if [ -n " ${ TMUX :- } " ] ; then
printf '\033Ptmux;\033\033[8;%d;%dt\033\\' " $target_rows " " $target_cols " 2>/dev/null || true
elif [ -n " ${ STY :- } " ] ; then
printf '\033P\033[8;%d;%dt\033\\' " $target_rows " " $target_cols " 2>/dev/null || true
else
printf '\033[8;%d;%dt' " $target_rows " " $target_cols " 2>/dev/null || true
fi
return 0
}
# 日志函数 - 同时输出到终端和日志文件
# 日志函数 - 同时输出到终端和日志文件
log_info( ) {
log_info( ) {
echo -e " ${ GREEN } [INFO] ${ NC } $1 "
echo -e " ${ GREEN } [INFO] ${ NC } $1 "
@ -68,6 +105,27 @@ log_cmd_output() {
echo "" >> " $LOG_FILE "
echo "" >> " $LOG_FILE "
}
}
# 生成指定字节长度的十六进制串(2*bytes 个字符),优先 openssl,缺失时使用 python3 兜底
generate_hex_bytes( ) {
local bytes = " $1 "
if command -v openssl >/dev/null 2>& 1; then
openssl rand -hex " $bytes "
return 0
fi
# mac 脚本已要求 python3,可作为兜底
python3 -c 'import os, sys; print(os.urandom(int(sys.argv[1])).hex())' " $bytes "
}
# 生成随机 UUID(小写),优先 uuidgen,缺失时使用 python3 兜底
generate_uuid( ) {
if command -v uuidgen >/dev/null 2>& 1; then
uuidgen | tr '[:upper:]' '[:lower:]'
return 0
fi
# mac 脚本已要求 python3,可作为兜底
python3 -c 'import uuid; print(str(uuid.uuid4()))'
}
# 🚀 新增 Cursor 防掉试用Pro删除文件夹功能
# 🚀 新增 Cursor 防掉试用Pro删除文件夹功能
remove_cursor_trial_folders( ) {
remove_cursor_trial_folders( ) {
echo
echo
@ -223,7 +281,8 @@ test_cursor_environment() {
issues += ( " 配置文件不存在: $config_path " )
issues += ( " 配置文件不存在: $config_path " )
else
else
# 验证JSON格式
# 验证JSON格式
if python3 -c " import json; json.load(open(' $config_path ')) " 2>/dev/null; then
# 🔧 修复:避免把路径直接拼进 Python 源码字符串(路径包含引号等特殊字符时会导致语法错误)
if python3 -c 'import json, sys; json.load(open(sys.argv[1], "r", encoding="utf-8"))' " $config_path " 2>/dev/null; then
log_info "✅ [检查] 配置文件格式正确"
log_info "✅ [检查] 配置文件格式正确"
else
else
issues += ( "配置文件格式错误或损坏" )
issues += ( "配置文件格式错误或损坏" )
@ -412,7 +471,8 @@ modify_machine_code_config() {
# 验证配置文件格式并显示结构
# 验证配置文件格式并显示结构
log_info "🔍 [验证] 检查配置文件格式..."
log_info "🔍 [验证] 检查配置文件格式..."
if ! python3 -c " import json; json.load(open(' $config_path ')) " 2>/dev/null; then
# 🔧 修复:避免把路径直接拼进 Python 源码字符串(路径包含引号等特殊字符时会导致语法错误)
if ! python3 -c 'import json, sys; json.load(open(sys.argv[1], "r", encoding="utf-8"))' " $config_path " 2>/dev/null; then
log_error "❌ [错误] 配置文件格式错误或损坏"
log_error "❌ [错误] 配置文件格式错误或损坏"
log_info "💡 [建议] 配置文件可能已损坏,建议选择'重置环境+修改机器码'选项"
log_info "💡 [建议] 配置文件可能已损坏,建议选择'重置环境+修改机器码'选项"
return 1
return 1
@ -421,10 +481,13 @@ modify_machine_code_config() {
# 显示当前配置文件中的相关属性
# 显示当前配置文件中的相关属性
log_info "📋 [当前配置] 检查现有的遥测属性:"
log_info "📋 [当前配置] 检查现有的遥测属性:"
# 🔧 修复:避免把路径直接拼进 Python 源码字符串(路径包含引号等特殊字符时会导致语法错误)
python3 -c "
python3 -c "
import json
import json
import sys
try:
try:
with open( '$config_path' , 'r' , encoding = 'utf-8' ) as f:
config_path = sys.argv[ 1]
with open( config_path, 'r' , encoding = 'utf-8' ) as f:
config = json.load( f)
config = json.load( f)
properties = [ 'telemetry.machineId' , 'telemetry.macMachineId' , 'telemetry.devDeviceId' , 'telemetry.sqmId' ]
properties = [ 'telemetry.machineId' , 'telemetry.macMachineId' , 'telemetry.devDeviceId' , 'telemetry.sqmId' ]
@ -437,22 +500,30 @@ try:
print( f' - {prop} (不存在,将创建)' )
print( f' - {prop} (不存在,将创建)' )
except Exception as e:
except Exception as e:
print( f'Error reading config: {e}' )
print( f'Error reading config: {e}' )
"
" " $config_path "
echo
echo
# 显示操作进度
# 显示操作进度
log_info "⏳ [进度] 1/5 - 生成新的设备标识符..."
log_info "⏳ [进度] 1/5 - 生成新的设备标识符..."
# 生成新的ID
# 生成新的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 SQM_ID = " { $( uuidgen | tr '[:lower:]' '[:upper:]' ) } "
local MAC_MACHINE_ID = $( generate_uuid )
local UUID = $( generate_uuid )
local MACHINE_ID = $( generate_hex_bytes 32)
local SQM_ID = " { $( generate_ uuid | tr '[:lower:]' '[:upper:]' ) } "
# 🔧 新增: serviceMachineId (用于 storage.serviceMachineId)
# 🔧 新增: serviceMachineId (用于 storage.serviceMachineId)
local SERVICE_MACHINE_ID = $( uuidgen | tr '[:upper:]' '[:lower:]' )
local SERVICE_MACHINE_ID = $( generate_uuid )
# 🔧 新增: firstSessionDate (重置首次会话日期)
# 🔧 新增: firstSessionDate (重置首次会话日期)
local FIRST_SESSION_DATE = $( date -u +"%Y-%m-%dT%H:%M:%S.000Z" )
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 = $( generate_uuid)
CURSOR_ID_MAC_ADDRESS = " ${ CURSOR_ID_MAC_ADDRESS :- 00 : 11 : 22 : 33 : 44 : 55 } "
log_info "✅ [进度] 1/5 - 设备标识符生成完成"
log_info "✅ [进度] 1/5 - 设备标识符生成完成"
log_info "⏳ [进度] 2/5 - 创建备份目录..."
log_info "⏳ [进度] 2/5 - 创建备份目录..."
@ -490,23 +561,32 @@ except Exception as e:
log_info "⏳ [进度] 4/5 - 更新配置文件..."
log_info "⏳ [进度] 4/5 - 更新配置文件..."
# 使用Python修改JSON配置(更可靠,安全方式)
# 使用Python修改JSON配置(更可靠,安全方式)
# 🔧 修复:避免把路径/值直接拼进 Python 源码字符串(引号/反斜杠等特殊字符会导致语法错误或写入错误)
local python_result = $( python3 -c "
local python_result = $( python3 -c "
import json
import json
import sys
import sys
try:
try:
with open( '$config_path' , 'r' , encoding = 'utf-8' ) as f:
config_path = sys.argv[ 1]
machine_id = sys.argv[ 2]
mac_machine_id = sys.argv[ 3]
dev_device_id = sys.argv[ 4]
sqm_id = sys.argv[ 5]
service_machine_id = sys.argv[ 6]
first_session_date = sys.argv[ 7]
with open( config_path, 'r' , encoding = 'utf-8' ) as f:
config = json.load( f)
config = json.load( f)
# 安全更新配置,确保属性存在
# 安全更新配置,确保属性存在
# 🔧 修复: 添加 storage.serviceMachineId 和 telemetry.firstSessionDate
# 🔧 修复: 添加 storage.serviceMachineId 和 telemetry.firstSessionDate
properties_to_update = {
properties_to_update = {
'telemetry.machineId' : '$MACHINE_ID' ,
'telemetry.macMachineId' : '$MAC_MACHINE_ID' ,
'telemetry.devDeviceId' : '$UUID' ,
'telemetry.sqmId' : '$SQM_ID' ,
'storage.serviceMachineId' : '$SERVICE_MACHINE_ID' ,
'telemetry.firstSessionDate' : '$FIRST_SESSION_DATE'
'telemetry.machineId' : machine_id ,
'telemetry.macMachineId' : mac_machine_id ,
'telemetry.devDeviceId' : dev_device_id ,
'telemetry.sqmId' : sqm_id ,
'storage.serviceMachineId' : service_machine_id ,
'telemetry.firstSessionDate' : first_session_date
}
}
for key, value in properties_to_update.items( ) :
for key, value in properties_to_update.items( ) :
@ -516,14 +596,14 @@ try:
print( f' + 添加属性: {key}' )
print( f' + 添加属性: {key}' )
config[ key] = value
config[ key] = value
with open( '$ config_path' , 'w' , encoding = 'utf-8' ) as f:
with open( config_path, 'w' , encoding = 'utf-8' ) as f:
json.dump( config, f, indent = 2, ensure_ascii = False)
json.dump( config, f, indent = 2, ensure_ascii = False)
print( 'SUCCESS' )
print( 'SUCCESS' )
except Exception as e:
except Exception as e:
print( f'ERROR: {e}' )
print( f'ERROR: {e}' )
sys.exit( 1)
sys.exit( 1)
" 2>&1)
" " $config_path " " $MACHINE_ID " " $MAC_MACHINE_ID " " $UUID " " $SQM_ID " " $SERVICE_MACHINE_ID " " $FIRST_SESSION_DATE " 2>&1)
# 🔧 关键修复:正确解析Python执行结果
# 🔧 关键修复:正确解析Python执行结果
local python_exit_code = $?
local python_exit_code = $?
@ -553,20 +633,30 @@ except Exception as e:
chmod 644 " $config_path " 2>/dev/null || true
chmod 644 " $config_path " 2>/dev/null || true
# 验证修改是否成功
# 验证修改是否成功
# 🔧 修复:避免把路径/值直接拼进 Python 源码字符串(引号/反斜杠等特殊字符会导致语法错误或写入错误)
local verification_result = $( python3 -c "
local verification_result = $( python3 -c "
import json
import json
import sys
try:
try:
with open( '$config_path' , 'r' , encoding = 'utf-8' ) as f:
config_path = sys.argv[ 1]
machine_id = sys.argv[ 2]
mac_machine_id = sys.argv[ 3]
dev_device_id = sys.argv[ 4]
sqm_id = sys.argv[ 5]
service_machine_id = sys.argv[ 6]
first_session_date = sys.argv[ 7]
with open( config_path, 'r' , encoding = 'utf-8' ) as f:
config = json.load( f)
config = json.load( f)
# 🔧 修复: 添加 storage.serviceMachineId 和 telemetry.firstSessionDate 验证
# 🔧 修复: 添加 storage.serviceMachineId 和 telemetry.firstSessionDate 验证
properties_to_check = {
properties_to_check = {
'telemetry.machineId' : '$MACHINE_ID' ,
'telemetry.macMachineId' : '$MAC_MACHINE_ID' ,
'telemetry.devDeviceId' : '$UUID' ,
'telemetry.sqmId' : '$SQM_ID' ,
'storage.serviceMachineId' : '$SERVICE_MACHINE_ID' ,
'telemetry.firstSessionDate' : '$FIRST_SESSION_DATE'
'telemetry.machineId' : machine_id ,
'telemetry.macMachineId' : mac_machine_id ,
'telemetry.devDeviceId' : dev_device_id ,
'telemetry.sqmId' : sqm_id ,
'storage.serviceMachineId' : service_machine_id ,
'telemetry.firstSessionDate' : first_session_date
}
}
verification_passed = True
verification_passed = True
@ -584,7 +674,7 @@ try:
print( 'VERIFICATION_FAILED' )
print( 'VERIFICATION_FAILED' )
except Exception as e:
except Exception as e:
print( f'VERIFICATION_ERROR: {e}' )
print( f'VERIFICATION_ERROR: {e}' )
" 2>&1)
" " $config_path " " $MACHINE_ID " " $MAC_MACHINE_ID " " $UUID " " $SQM_ID " " $SERVICE_MACHINE_ID " " $FIRST_SESSION_DATE " 2>&1)
# 检查验证结果(忽略其他输出,只关注最终结果)
# 检查验证结果(忽略其他输出,只关注最终结果)
if echo " $verification_result " | grep -q "VERIFICATION_SUCCESS" ; then
if echo " $verification_result " | grep -q "VERIFICATION_SUCCESS" ; then
@ -642,7 +732,7 @@ except Exception as e:
log_info " 💾 [备份] .updaterId 文件已备份: $updater_id_backup "
log_info " 💾 [备份] .updaterId 文件已备份: $updater_id_backup "
fi
fi
# 生成新的 updaterId(UUID格式)
# 生成新的 updaterId(UUID格式)
local new_updater_id = $( uuidgen | tr '[:upper:]' '[:lower:]' )
local new_updater_id = $( generate_uuid )
if echo -n " $new_updater_id " > " $updater_id_file_path " 2>/dev/null; then
if echo -n " $new_updater_id " > " $updater_id_file_path " 2>/dev/null; then
log_info " ✅ [updaterId] .updaterId 文件修改成功: $new_updater_id "
log_info " ✅ [updaterId] .updaterId 文件修改成功: $new_updater_id "
# 设置 .updaterId 文件为只读
# 设置 .updaterId 文件为只读
@ -745,6 +835,16 @@ TARGET_HOME="$(get_user_home_dir "$TARGET_USER")"
STORAGE_FILE = " $TARGET_HOME /Library/Application Support/Cursor/User/globalStorage/storage.json "
STORAGE_FILE = " $TARGET_HOME /Library/Application Support/Cursor/User/globalStorage/storage.json "
BACKUP_DIR = " $TARGET_HOME /Library/Application Support/Cursor/User/globalStorage/backups "
BACKUP_DIR = " $TARGET_HOME /Library/Application Support/Cursor/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 = ""
CURSOR_ID_FIRST_SESSION_DATE = ""
CURSOR_ID_SESSION_ID = ""
CURSOR_ID_MAC_ADDRESS = "00:11:22:33:44:55"
# 定义 Cursor 应用程序路径
# 定义 Cursor 应用程序路径
CURSOR_APP_PATH = "/Applications/Cursor.app"
CURSOR_APP_PATH = "/Applications/Cursor.app"
@ -1417,6 +1517,19 @@ _show_troubleshooting_info() {
echo
echo
}
}
# 智能设备识别绕过(已移除 MAC 地址修改,仅保留 JS 注入)
run_device_bypass( ) {
log_info "🔧 [设备识别] 已禁用 MAC 地址修改,直接执行 JS 内核注入..."
if modify_cursor_js_files; then
log_info "✅ [JS] JS 内核注入完成"
return 0
fi
log_error "❌ [JS] JS 内核注入失败"
return 1
}
# 检查权限
# 检查权限
check_permissions( ) {
check_permissions( ) {
if [ " $EUID " -ne 0 ] ; then
if [ " $EUID " -ne 0 ] ; then
@ -1510,13 +1623,24 @@ backup_config() {
fi
fi
}
}
# 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版 Hook 方案)
# 重新设置配置文件只读(避免权限修复覆盖)
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文件实现设备识别绕过(增强版三重方案)
# 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名
# 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名
# 方案B: 深度 Hook 注入 - 从底层拦截所有设备标识符生成
# 方案C: Module.prototype.require 劫持 - 拦截 child_process, crypto, os 等模块
# 方案B: b6 定点重写 - 机器码源函数直接返回固定值
# 方案C: Loader Stub + 外置 Hook - 主/共享进程仅加载外置 Hook 文件
modify_cursor_js_files( ) {
modify_cursor_js_files( ) {
log_info "🔧 [内核修改] 开始修改Cursor内核JS文件实现设备识别绕过..."
log_info "🔧 [内核修改] 开始修改Cursor内核JS文件实现设备识别绕过..."
log_info "💡 [方案] 使用增强版 Hook 方案:深度模块劫持 + someValue替换"
log_info "💡 [方案] 使用增强版三重方案:占位符替换 + b6 定点重写 + Loader Stub + 外置 Hook "
echo
echo
# 检查Cursor应用是否存在
# 检查Cursor应用是否存在
@ -1525,25 +1649,71 @@ modify_cursor_js_files() {
return 1
return 1
fi
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 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 :- } "
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 = $( generate_hex_bytes 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
fi
if [ -z " $mac_machine_id " ] ; then
mac_machine_id = $( generate_hex_bytes 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
log_info "🔑 [生成] 已生成新的设备标识符"
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 "
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 " machineId: ${ machine_id : 0 : 16 } ... "
log_info " machineGuid: ${ machine_guid : 0 : 16 } ... "
log_info " deviceId: ${ device_id : 0 : 16 } ... "
log_info " deviceId: ${ device_id : 0 : 16 } ... "
log_info " macMachineId: ${ mac_machine_id : 0 : 16 } ... "
log_info " macMachineId: ${ mac_machine_id : 0 : 16 } ... "
log_info " sqmId: $sqm_id "
log_info " sqmId: $sqm_id "
# 保存 ID 配置到用户目录(供 Hook 读取)
# 保存 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
if [ -f " $ids_config_path " ] ; then
rm -f " $ids_config_path "
rm -f " $ids_config_path "
log_info "🗑️ [清理] 已删除旧的 ID 配置文件"
log_info "🗑️ [清理] 已删除旧的 ID 配置文件"
@ -1551,18 +1721,93 @@ modify_cursor_js_files() {
cat > " $ids_config_path " << EOF
cat > " $ids_config_path " << EOF
{
{
"machineId" : " $machine_id " ,
"machineId" : " $machine_id " ,
"machineGuid" : " $machine_guid " ,
"macMachineId" : " $mac_machine_id " ,
"macMachineId" : " $mac_machine_id " ,
"devDeviceId" : " $device_id " ,
"devDeviceId" : " $device_id " ,
"sqmId" : " $sqm_id " ,
"sqmId" : " $sqm_id " ,
"macAddress" : " $mac_address " ,
"macAddress" : " $mac_address " ,
"sessionId" : " $session_id " ,
"firstSessionDate" : " $first_session_date " ,
"createdAt" : " $first_session_date "
"createdAt" : " $first_session_date "
}
}
EOF
EOF
log_info " 💾 [保存] 新的 ID 配置已保存到: $ids_config_path "
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 [ -n " $CURSOR_HOOK_DOWNLOAD_URLS " ] ; then
IFS = ',' read -r -a hook_download_urls <<< " $CURSOR_HOOK_DOWNLOAD_URLS "
log_info "ℹ️ [Hook] 检测到自定义下载节点列表,将优先使用"
fi
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
log_info "ℹ️ [Hook] 正在下载外置 Hook,用于设备标识拦截..."
local hook_downloaded = false
local total_urls = ${# hook_download_urls [@] }
if [ " $total_urls " -eq 0 ] ; then
log_warn "⚠️ [Hook] 下载节点列表为空,跳过在线下载"
elif command -v curl >/dev/null 2>& 1; then
local index = 0
for url in " ${ hook_download_urls [@] } " ; do
index = $(( index + 1 ))
log_info " ⏳ [Hook] ( $index / $total_urls ) 当前下载节点: $url "
if curl -fL --progress-bar " $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
local index = 0
for url in " ${ hook_download_urls [@] } " ; do
index = $(( index + 1 ))
log_info " ⏳ [Hook] ( $index / $total_urls ) 当前下载节点: $url "
if wget --progress= bar:force -O " $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 = (
local js_files = (
" $CURSOR_APP_PATH /Contents/Resources/app/out/main.js "
" $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
local modified_count = 0
@ -1690,106 +1935,37 @@ EOF
replaced = true
replaced = true
fi
fi
# ========== 方法B: 增强版深度 Hook 注入 ==========
# 创建注入代码
local inject_code = ' // = = = = = = = = = = Cursor Hook 注入 开始 = = = = = = = = = =
# ========== 方法C: Loader Stub 注入 ==========
local inject_code = ' // = = = = = = = = = = Cursor Hook Loader 开始 = = = = = = = = = =
; ( async function ( ) { /*__cursor_patched__*/
; ( async function ( ) { /*__cursor_patched__*/
"use strict" ;
"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 __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 "'"
} ;
// 兼容 ESM/CJS:避免使用 import.meta(仅 ESM 支持),统一用动态 import 加载 Hook
var fsMod = await import( "fs" ) ;
var pathMod = await import( "path" ) ;
var osMod = await import( "os" ) ;
var urlMod = await import( "url" ) ;
globalThis.__cursor_ids__= __ids__;
var fs = fsMod&& ( fsMod.default|| fsMod) ;
var path = pathMod&& ( pathMod.default|| pathMod) ;
var os = osMod&& ( osMod.default|| osMod) ;
var url = urlMod&& ( urlMod.default|| urlMod) ;
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 ( fs&& path&& os&& url&& typeof url.pathToFileURL= = = "function" ) {
var hookPath = path.join( os.homedir( ) , ".cursor_hook.js" ) ;
if ( typeof fs.existsSync= = = "function" && fs.existsSync( hookPath) ) {
await import( url.pathToFileURL( hookPath) .href) ;
}
}
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; } } ;
} catch( e) {
// 失败静默,避免影响启动
}
}
if ( hooked!= = result) _hooked.set( id,hooked) ;
return hooked;
} ;
console.log( "[Cursor ID Modifier] 增强版 Hook 已激活 - 煎饼果子(86) 公众号【煎饼果子卷AI】" ) ;
} ) ( ) ;
} ) ( ) ;
// = = = = = = = = = = Cursor Hook 注入 结束 = = = = = = = = = =
// = = = = = = = = = = Cursor Hook Loader 结束 = = = = = = = = = =
'
'
@ -1807,32 +1983,36 @@ console.log("[Cursor ID Modifier] 增强版 Hook 已激活 - 煎饼果子(86)
{ print }
{ print }
' " $file " > " ${ file } .new "
' " $file " > " ${ file } .new "
mv " ${ file } .new " " $file "
mv " ${ file } .new " " $file "
log_info " ✓ [方案B] 增强版 Hook 代码 已注入(版权声明后)"
log_info " ✓ [方案C] Loader Stub 已注入(版权声明后)"
else
else
# 注入到文件开头
# 注入到文件开头
echo " $inject_code " > " ${ file } .new "
echo " $inject_code " > " ${ file } .new "
cat " $file " >> " ${ file } .new "
cat " $file " >> " ${ file } .new "
mv " ${ file } .new " " $file "
mv " ${ file } .new " " $file "
log_info " ✓ [方案B] 增强版 Hook 代码 已注入(文件开头)"
log_info " ✓ [方案C] Loader Stub 已注入(文件开头)"
fi
fi
# 清理临时文件
# 清理临时文件
rm -f " ${ file } .tmp "
rm -f " ${ file } .tmp "
local summary = "Hook加载器"
if [ " $replaced " = true ] ; then
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
fi
log_info " ✅ [成功] 增强版方案修改成功( $summary ) "
( ( modified_count++) )
( ( modified_count++) )
done
done
if [ $modified_count -gt 0 ] ; then
if [ $modified_count -gt 0 ] ; then
log_info " 🎉 [完成] 成功修改 $modified_count 个JS文件 "
log_info " 🎉 [完成] 成功修改 $modified_count 个JS文件 "
log_info " 💾 [备份] 原始文件备份位置: $backup_dir "
log_info " 💾 [备份] 原始文件备份位置: $backup_dir "
log_info "💡 [说明] 使用增强版 Hook 方案:"
log_info "💡 [说明] 使用增强版三重 方案:"
log_info " • 方案A: someValue占位符替换(稳定锚点,跨版本兼容)"
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 "
log_info " 📁 [配置] ID 配置文件: $ids_config_path "
return 0
return 0
else
else
@ -2290,10 +2470,10 @@ if (typeof window !== 'undefined') {
console.log( 'Cursor全局设备标识符拦截已激活 - ES模块版本' ) ;
console.log( 'Cursor全局设备标识符拦截已激活 - ES模块版本' ) ;
"
"
# 将代码注入到文件开头
# 将代码注入到文件开头
local new_uuid = $( uuidgen | tr '[:upper:]' '[:lower:]' )
local machine_id = " auth0|user_ $( openssl rand -hex 16) "
local device_id = $( uuidgen | tr '[:upper:]' '[:lower:]' )
local mac_machine_id = $( openssl rand -hex 32)
local new_uuid = $( generate_uuid )
local machine_id = " auth0|user_ $( generate_hex_bytes 16) "
local device_id = $( generate_uuid )
local mac_machine_id = $( generate_hex_bytes 32)
inject_universal_code = ${ inject_universal_code // \$ \{ new_uuid \} / $new_uuid }
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 // \$ \{ machine_id \} / $machine_id }
@ -2530,7 +2710,8 @@ restore_feature() {
# 解决"应用已损坏,无法打开"问题
# 解决"应用已损坏,无法打开"问题
fix_damaged_app( ) {
fix_damaged_app( ) {
log_info "正在修复" 应用已损坏"问题..."
# 🔧 修复:字符串内双引号需转义,避免脚本解析中断
log_info "正在修复\"应用已损坏\"问题..."
# 检查Cursor应用是否存在
# 检查Cursor应用是否存在
if [ ! -d " $CURSOR_APP_PATH " ] ; then
if [ ! -d " $CURSOR_APP_PATH " ] ; then
@ -2558,7 +2739,7 @@ fix_damaged_app() {
log_info "修复完成!请尝试重新打开Cursor应用"
log_info "修复完成!请尝试重新打开Cursor应用"
echo
echo
echo -e " ${ YELLOW } 如果仍然无法打开,您可以尝试以下方法: ${ NC } "
echo -e " ${ YELLOW } 如果仍然无法打开,您可以尝试以下方法: ${ NC } "
echo "1. 在系统偏好设置->安全性与隐私中,点击" 仍要打开 "按钮"
echo "1. 在系统偏好设置->安全性与隐私中,点击\"仍要打开\ "按钮"
echo "2. 暂时关闭Gatekeeper(不建议): sudo spctl --master-disable"
echo "2. 暂时关闭Gatekeeper(不建议): sudo spctl --master-disable"
echo "3. 重新下载安装Cursor应用"
echo "3. 重新下载安装Cursor应用"
echo
echo
@ -2642,6 +2823,9 @@ select_menu_option() {
# 主函数
# 主函数
main( ) {
main( ) {
# 在显示菜单/流程说明前调整终端窗口大小;不支持则静默忽略
try_resize_terminal_window
# 初始化日志文件
# 初始化日志文件
initialize_log
initialize_log
log_info "脚本启动..."
log_info "脚本启动..."
@ -2655,7 +2839,8 @@ main() {
log_info " 当前用户: $CURRENT_USER "
log_info " 当前用户: $CURRENT_USER "
log_cmd_output "sw_vers" "macOS 版本信息"
log_cmd_output "sw_vers" "macOS 版本信息"
log_cmd_output "which codesign" "codesign 路径"
log_cmd_output "which codesign" "codesign 路径"
log_cmd_output "ls -ld " $CURSOR_APP_PATH "" "Cursor 应用信息"
# 修复:统一引号并显式转义,避免引号嵌套导致脚本解析错误
log_cmd_output " ls -ld \" $CURSOR_APP_PATH \" " "Cursor 应用信息"
# 新增环境检查
# 新增环境检查
if [ [ $( uname) != "Darwin" ] ] ; then
if [ [ $( uname) != "Darwin" ] ] ; then
@ -2679,7 +2864,7 @@ main() {
echo -e " ${ YELLOW } 🤝 一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬) ${ NC } "
echo -e " ${ YELLOW } 🤝 一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬) ${ NC } "
echo -e " ${ BLUE } ================================ ${ NC } "
echo -e " ${ BLUE } ================================ ${ NC } "
echo
echo
echo -e " ${ YELLOW } ⚡ [小小广告] Cursor官网正规成品号:Pro¥65 | Pro+¥265 | Ultra¥888 独享账号/7天质保 ,WeChat:JavaRookie666 ${ NC } "
echo -e " ${ YELLOW } ⚡ [小小广告] Cursor官网正规成品号:Pro¥65 | Pro+¥265 | Ultra¥888 独享账号| ¥488 Team绝版次数号1000次+20刀额度 | 全部7天质保 | ,WeChat:JavaRookie666 ${ NC } "
echo
echo
echo -e " ${ YELLOW } 💡 [重要提示] ${ NC } 本工具采用分阶段执行策略,既能彻底清理又能修改机器码。 "
echo -e " ${ YELLOW } 💡 [重要提示] ${ NC } 本工具采用分阶段执行策略,既能彻底清理又能修改机器码。 "
echo -e " ${ YELLOW } 💡 [重要提示] ${ NC } 本工具免费,如果对您有帮助,请关注公众号【煎饼果子卷AI】 "
echo -e " ${ YELLOW } 💡 [重要提示] ${ NC } 本工具免费,如果对您有帮助,请关注公众号【煎饼果子卷AI】 "
@ -2692,6 +2877,7 @@ main() {
echo
echo
echo -e " ${ BLUE } 1️⃣ 仅修改机器码 ${ NC } "
echo -e " ${ BLUE } 1️⃣ 仅修改机器码 ${ NC } "
echo -e " ${ YELLOW } • 仅执行机器码修改功能 ${ NC } "
echo -e " ${ YELLOW } • 仅执行机器码修改功能 ${ NC } "
echo -e " ${ YELLOW } • 同步执行 JS 内核注入 ${ NC } "
echo -e " ${ YELLOW } • 跳过文件夹删除/环境重置步骤 ${ NC } "
echo -e " ${ YELLOW } • 跳过文件夹删除/环境重置步骤 ${ NC } "
echo -e " ${ YELLOW } • 保留现有Cursor配置和数据 ${ NC } "
echo -e " ${ YELLOW } • 保留现有Cursor配置和数据 ${ NC } "
echo
echo
@ -2733,7 +2919,8 @@ main() {
echo -e " ${ BLUE } 1️⃣ 检测Cursor配置文件 ${ NC } "
echo -e " ${ BLUE } 1️⃣ 检测Cursor配置文件 ${ NC } "
echo -e " ${ BLUE } 2️⃣ 备份现有配置文件 ${ NC } "
echo -e " ${ BLUE } 2️⃣ 备份现有配置文件 ${ NC } "
echo -e " ${ BLUE } 3️⃣ 修改机器码配置 ${ NC } "
echo -e " ${ BLUE } 3️⃣ 修改机器码配置 ${ NC } "
echo -e " ${ BLUE } 4️⃣ 显示操作完成信息 ${ NC } "
echo -e " ${ BLUE } 4️⃣ 执行 JS 内核注入 ${ NC } "
echo -e " ${ BLUE } 5️⃣ 显示操作完成信息 ${ NC } "
echo
echo
echo -e " ${ YELLOW } ⚠️ [注意事项] ${ NC } "
echo -e " ${ YELLOW } ⚠️ [注意事项] ${ NC } "
echo -e " ${ YELLOW } • 不会删除任何文件夹或重置环境 ${ NC } "
echo -e " ${ YELLOW } • 不会删除任何文件夹或重置环境 ${ NC } "
@ -2752,7 +2939,7 @@ main() {
echo -e " ${ BLUE } 5️⃣ 等待配置文件生成完成(最多45秒) ${ NC } "
echo -e " ${ BLUE } 5️⃣ 等待配置文件生成完成(最多45秒) ${ NC } "
echo -e " ${ BLUE } 6️⃣ 关闭Cursor进程 ${ NC } "
echo -e " ${ BLUE } 6️⃣ 关闭Cursor进程 ${ NC } "
echo -e " ${ BLUE } 7️⃣ 修改新生成的机器码配置文件 ${ 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 } 9️⃣ 禁用自动更新 ${ NC } "
echo -e " ${ BLUE } 🔟 显示操作完成统计信息 ${ NC } "
echo -e " ${ BLUE } 🔟 显示操作完成统计信息 ${ NC } "
echo
echo
@ -2762,7 +2949,7 @@ main() {
echo -e " ${ YELLOW } • 执行完成后需要重新启动Cursor ${ NC } "
echo -e " ${ YELLOW } • 执行完成后需要重新启动Cursor ${ NC } "
echo -e " ${ YELLOW } • 原配置文件会自动备份到backups文件夹 ${ NC } "
echo -e " ${ YELLOW } • 原配置文件会自动备份到backups文件夹 ${ NC } "
echo -e " ${ YELLOW } • 需要Python3环境来处理JSON配置文件 ${ NC } "
echo -e " ${ YELLOW } • 需要Python3环境来处理JSON配置文件 ${ NC } "
echo -e " ${ YELLOW } • MAC地址修改是临时的,重启后恢复 ${ NC } "
echo -e " ${ YELLOW } • 已移除 MAC 地址修改,仅保留 JS 注入方案 ${ NC } "
fi
fi
echo
echo
@ -2800,14 +2987,18 @@ main() {
echo
echo
log_info "🎉 [完成] 机器码修改完成!"
log_info "🎉 [完成] 机器码修改完成!"
log_info "💡 [提示] 现在可以启动Cursor使用新的机器码配置"
log_info "💡 [提示] 现在可以启动Cursor使用新的机器码配置"
echo
log_info "🔧 [设备识别] 正在执行 JS 内核注入..."
if modify_cursor_js_files; then
log_info "✅ [设备识别] JS 内核注入完成"
else
log_warn "⚠️ [设备识别] JS 内核注入失败,请检查日志"
fi
else
else
echo
echo
log_error "❌ [失败] 机器码修改失败!"
log_error "❌ [失败] 机器码修改失败!"
log_info "💡 [建议] 请尝试'重置环境+修改机器码'选项"
log_info "💡 [建议] 请尝试'重置环境+修改机器码'选项"
fi
fi
# 🚫 禁用自动更新(仅修改模式也需要)
# 🚫 禁用自动更新(仅修改模式也需要)
echo
echo
log_info "🚫 [禁用更新] 正在禁用Cursor自动更新..."
log_info "🚫 [禁用更新] 正在禁用Cursor自动更新..."
@ -2857,10 +3048,13 @@ main() {
# 🛠️ 修改机器码配置
# 🛠️ 修改机器码配置
modify_machine_code_config
modify_machine_code_config
# 🔧 智能设备识别绕过(MAC地址修改或JS内核修改 )
# 🔧 智能设备识别绕过(仅 JS 内核注入 )
echo
echo
log_info "🔧 [设备识别] 开始智能设备识别绕过..."
log_info "🔧 [设备识别] 开始智能设备识别绕过..."
log_info "💡 [说明] 将根据系统环境自动选择最佳方案(MAC地址修改或JS内核修改)"
log_info "💡 [说明] 已移除 MAC 地址修改,直接使用 JS 内核注入"
if ! run_device_bypass; then
log_warn "⚠️ [设备识别] 智能设备识别绕过未完全成功,请查看日志"
fi
# 🔧 关键修复:修复应用签名问题(防止"应用已损坏"错误)
# 🔧 关键修复:修复应用签名问题(防止"应用已损坏"错误)
@ -2889,7 +3083,7 @@ main() {
# 📱 显示公众号信息
# 📱 显示公众号信息
echo -e " ${ GREEN } ================================ ${ NC } "
echo -e " ${ GREEN } ================================ ${ NC } "
echo -e " ${ YELLOW } 📱 关注公众号【煎饼果子卷AI】一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬) ${ NC } "
echo -e " ${ YELLOW } 📱 关注公众号【煎饼果子卷AI】一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬) ${ NC } "
echo -e " ${ YELLOW } ⚡ [小小广告] Cursor官网正规成品号:Pro¥65 | Pro+¥265 | Ultra¥888 独享账号/7天质保 ,WeChat:JavaRookie666 ${ NC } "
echo -e " ${ YELLOW } ⚡ [小小广告] Cursor官网正规成品号:Pro¥65 | Pro+¥265 | Ultra¥888 独享账号| ¥488 Team绝版次数号1000次+20刀额度 | 全部7天质保 | ,WeChat:JavaRookie666 ${ NC } "
echo -e " ${ GREEN } ================================ ${ NC } "
echo -e " ${ GREEN } ================================ ${ NC } "
echo
echo
log_info "🚀 [提示] 现在可以重新启动 Cursor 尝试使用了!"
log_info "🚀 [提示] 现在可以重新启动 Cursor 尝试使用了!"
@ -2909,6 +3103,7 @@ main() {
echo
echo
log_info "🛡️ [最终权限修复] 执行脚本完成前的最终权限修复..."
log_info "🛡️ [最终权限修复] 执行脚本完成前的最终权限修复..."
ensure_cursor_directory_permissions
ensure_cursor_directory_permissions
protect_storage_file
# 🎉 脚本执行完成
# 🎉 脚本执行完成
log_info "🎉 [完成] 所有操作已完成!"
log_info "🎉 [完成] 所有操作已完成!"
@ -2936,4 +3131,3 @@ main() {
# 执行主函数
# 执行主函数
main
main