Browse Source

```

feat(cursor-hook): 添加machineGuid和会话标识符支持并优化设备识别绕过方案

添加了新的标识符字段包括machineGuid、macAddress、sessionId和firstSessionDate,
实现对注册表MachineGuid/IOPlatformUUID的模拟。增强了ID配置的向后兼容性,
当配置文件缺失字段时自动补全并更新。

优化了设备识别绕过方案为三重保护机制:
- 方案A: someValue占位符替换(稳定锚点)
- 方案B: b6 定点重写(机器码源函数)
- 方案C: Loader Stub + 外置 Hook(支持在线下载)

改进了模块劫持逻辑,兼容node:前缀,并增加了execFileSync的支持。
同时在Linux脚本中添加了相应的ID生成和配置文件部署功能。
```
煎饼果子卷鲨鱼辣椒 2 weeks ago
parent
commit
a217ddd2be
  1. 93
      scripts/hook/cursor_hook.js
  2. 236
      scripts/run/cursor_linux_id_modifier.sh
  3. 273
      scripts/run/cursor_mac_id_modifier.sh
  4. 240
      scripts/run/cursor_win_id_modifier.ps1

93
scripts/hook/cursor_hook.js

@ -110,9 +110,14 @@ var __cursor_hook_config__ = {
if (process.env.CURSOR_MACHINE_ID) { if (process.env.CURSOR_MACHINE_ID) {
ids = { ids = {
machineId: process.env.CURSOR_MACHINE_ID, machineId: process.env.CURSOR_MACHINE_ID,
// machineGuid 用于模拟注册表 MachineGuid/IOPlatformUUID
machineGuid: process.env.CURSOR_MACHINE_GUID || generateUUID(),
macMachineId: process.env.CURSOR_MAC_MACHINE_ID || generateHex64(), macMachineId: process.env.CURSOR_MAC_MACHINE_ID || generateHex64(),
devDeviceId: process.env.CURSOR_DEV_DEVICE_ID || generateUUID(), 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 配置'); log('从环境变量加载 ID 配置');
return ids; return ids;
@ -123,6 +128,32 @@ var __cursor_hook_config__ = {
if (fs.existsSync(configPath)) { if (fs.existsSync(configPath)) {
const content = fs.readFileSync(configPath, 'utf8'); const content = fs.readFileSync(configPath, 'utf8');
ids = JSON.parse(content); 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); log('从配置文件加载 ID 配置:', configPath);
return ids; return ids;
} }
@ -133,10 +164,13 @@ var __cursor_hook_config__ = {
// 生成新的 ID // 生成新的 ID
ids = { ids = {
machineId: generateHex64(), machineId: generateHex64(),
machineGuid: generateUUID(),
macMachineId: generateHex64(), macMachineId: generateHex64(),
devDeviceId: generateUUID(), devDeviceId: generateUUID(),
sqmId: `{${generateUUID().toUpperCase()}}`, sqmId: `{${generateUUID().toUpperCase()}}`,
macAddress: generateMacAddress(), macAddress: generateMacAddress(),
sessionId: generateUUID(),
firstSessionDate: new Date().toISOString(),
createdAt: new Date().toISOString() createdAt: new Date().toISOString()
}; };
@ -153,6 +187,8 @@ var __cursor_hook_config__ = {
// 加载 ID 配置 // 加载 ID 配置
const __cursor_ids__ = loadOrGenerateIds(); const __cursor_ids__ = loadOrGenerateIds();
// 统一获取 MachineGuid,缺失时回退到 machineId 的前 36 位
const getMachineGuid = () => __cursor_ids__.machineGuid || __cursor_ids__.machineId.substring(0, 36);
log('当前 ID 配置:', __cursor_ids__); log('当前 ID 配置:', __cursor_ids__);
// ==================== Module Hook ==================== // ==================== Module Hook ====================
@ -164,40 +200,42 @@ var __cursor_hook_config__ = {
const hookedModules = new Map(); const hookedModules = new Map();
Module.prototype.require = function(id) { Module.prototype.require = function(id) {
// 兼容 node: 前缀
const normalizedId = (typeof id === 'string' && id.startsWith('node:')) ? id.slice(5) : id;
const result = originalRequire.apply(this, arguments); const result = originalRequire.apply(this, arguments);
// 如果已经 Hook 过,直接返回缓存 // 如果已经 Hook 过,直接返回缓存
if (hookedModules.has(id)) {
return hookedModules.get(id);
if (hookedModules.has(normalizedId)) {
return hookedModules.get(normalizedId);
} }
let hooked = result; let hooked = result;
// Hook child_process 模块 // Hook child_process 模块
if (id === 'child_process') {
if (normalizedId === 'child_process') {
hooked = hookChildProcess(result); hooked = hookChildProcess(result);
} }
// Hook os 模块 // Hook os 模块
else if (id === 'os') {
else if (normalizedId === 'os') {
hooked = hookOs(result); hooked = hookOs(result);
} }
// Hook crypto 模块 // Hook crypto 模块
else if (id === 'crypto') {
else if (normalizedId === 'crypto') {
hooked = hookCrypto(result); hooked = hookCrypto(result);
} }
// Hook @vscode/deviceid 模块 // Hook @vscode/deviceid 模块
else if (id === '@vscode/deviceid') {
else if (normalizedId === '@vscode/deviceid') {
hooked = hookDeviceId(result); hooked = hookDeviceId(result);
} }
// Hook @vscode/windows-registry 模块 // Hook @vscode/windows-registry 模块
else if (id === '@vscode/windows-registry') {
else if (normalizedId === '@vscode/windows-registry') {
hooked = hookWindowsRegistry(result); hooked = hookWindowsRegistry(result);
} }
// 缓存 Hook 结果 // 缓存 Hook 结果
if (hooked !== result) { if (hooked !== result) {
hookedModules.set(id, hooked);
log(`已 Hook 模块: ${id}`);
hookedModules.set(normalizedId, hooked);
log(`已 Hook 模块: ${normalizedId}`);
} }
return hooked; return hooked;
@ -207,6 +245,7 @@ var __cursor_hook_config__ = {
function hookChildProcess(cp) { function hookChildProcess(cp) {
const originalExecSync = cp.execSync; const originalExecSync = cp.execSync;
const originalExecFileSync = cp.execFileSync;
cp.execSync = function(command, options) { cp.execSync = function(command, options) {
const cmdStr = String(command).toLowerCase(); const cmdStr = String(command).toLowerCase();
@ -215,13 +254,13 @@ var __cursor_hook_config__ = {
if (cmdStr.includes('reg') && cmdStr.includes('machineguid')) { if (cmdStr.includes('reg') && cmdStr.includes('machineguid')) {
log('拦截 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) // 拦截 ioreg 命令 (macOS)
if (cmdStr.includes('ioreg') && cmdStr.includes('ioplatformexpertdevice')) { if (cmdStr.includes('ioreg') && cmdStr.includes('ioplatformexpertdevice')) {
log('拦截 IOPlatformUUID 查询'); log('拦截 IOPlatformUUID 查询');
return Buffer.from(`"IOPlatformUUID" = "${__cursor_ids__.machineId.substring(0, 36).toUpperCase()}"`);
return Buffer.from(`"IOPlatformUUID" = "${getMachineGuid().toUpperCase()}"`);
} }
// 拦截 machine-id 读取 (Linux) // 拦截 machine-id 读取 (Linux)
@ -233,6 +272,30 @@ var __cursor_hook_config__ = {
return originalExecSync.apply(this, arguments); 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; return cp;
} }
@ -347,7 +410,7 @@ var __cursor_hook_config__ = {
// 拦截 MachineGuid 读取 // 拦截 MachineGuid 读取
if (name === 'MachineGuid' || path.includes('Cryptography')) { if (name === 'MachineGuid' || path.includes('Cryptography')) {
log('拦截注册表 MachineGuid 读取'); log('拦截注册表 MachineGuid 读取');
return __cursor_ids__.machineId.substring(0, 36);
return getMachineGuid();
} }
return originalGetStringRegKey?.apply(this, arguments) || ''; return originalGetStringRegKey?.apply(this, arguments) || '';
} }
@ -439,7 +502,7 @@ var __cursor_hook_config__ = {
} }
if (name === 'MachineGuid' || path?.includes('Cryptography')) { if (name === 'MachineGuid' || path?.includes('Cryptography')) {
log('动态导入: 拦截 MachineGuid'); log('动态导入: 拦截 MachineGuid');
return __cursor_ids__.machineId.substring(0, 36);
return getMachineGuid();
} }
return originalGetStringRegKey?.apply(this, arguments) || ''; return originalGetStringRegKey?.apply(this, arguments) || '';
} }
@ -459,6 +522,7 @@ var __cursor_hook_config__ = {
log('Cursor Hook 初始化完成'); log('Cursor Hook 初始化完成');
log('machineId:', __cursor_ids__.machineId.substring(0, 16) + '...'); log('machineId:', __cursor_ids__.machineId.substring(0, 16) + '...');
log('machineGuid:', getMachineGuid().substring(0, 16) + '...');
log('devDeviceId:', __cursor_ids__.devDeviceId); log('devDeviceId:', __cursor_ids__.devDeviceId);
log('sqmId:', __cursor_ids__.sqmId); log('sqmId:', __cursor_ids__.sqmId);
@ -474,4 +538,3 @@ if (typeof module !== 'undefined' && module.exports) {
if (typeof globalThis !== 'undefined') { if (typeof globalThis !== 'undefined') {
globalThis.__cursor_hook_config__ = __cursor_hook_config__; globalThis.__cursor_hook_config__ = __cursor_hook_config__;
} }

236
scripts/run/cursor_linux_id_modifier.sh

@ -72,6 +72,7 @@ BACKUP_DIR="$CURSOR_CONFIG_DIR/User/globalStorage/backups"
# 共享ID(用于配置与JS注入保持一致) # 共享ID(用于配置与JS注入保持一致)
CURSOR_ID_MACHINE_ID="" CURSOR_ID_MACHINE_ID=""
CURSOR_ID_MACHINE_GUID=""
CURSOR_ID_MAC_MACHINE_ID="" CURSOR_ID_MAC_MACHINE_ID=""
CURSOR_ID_DEVICE_ID="" CURSOR_ID_DEVICE_ID=""
CURSOR_ID_SQM_ID="" CURSOR_ID_SQM_ID=""
@ -529,6 +530,7 @@ PY
# 仅用于JS注入的ID生成(不写配置) # 仅用于JS注入的ID生成(不写配置)
generate_ids_for_js_only() { generate_ids_for_js_only() {
CURSOR_ID_MACHINE_ID=$(openssl rand -hex 32) 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_MAC_MACHINE_ID=$(openssl rand -hex 32)
CURSOR_ID_DEVICE_ID=$(generate_uuid) CURSOR_ID_DEVICE_ID=$(generate_uuid)
CURSOR_ID_SQM_ID="{$(generate_uuid | tr '[:lower:]' '[:upper:]')}" CURSOR_ID_SQM_ID="{$(generate_uuid | tr '[:lower:]' '[:upper:]')}"
@ -787,10 +789,12 @@ find_cursor_js_files() {
local js_patterns=( local js_patterns=(
"resources/app/out/vs/workbench/api/node/extensionHostProcess.js" "resources/app/out/vs/workbench/api/node/extensionHostProcess.js"
"resources/app/out/main.js" "resources/app/out/main.js"
"resources/app/out/vs/code/electron-utility/sharedProcess/sharedProcessMain.js"
"resources/app/out/vs/code/node/cliProcessMain.js" "resources/app/out/vs/code/node/cliProcessMain.js"
# 添加其他可能的路径模式 # 添加其他可能的路径模式
"app/out/vs/workbench/api/node/extensionHostProcess.js" # 如果资源目录是 app 的父目录 "app/out/vs/workbench/api/node/extensionHostProcess.js" # 如果资源目录是 app 的父目录
"app/out/main.js" "app/out/main.js"
"app/out/vs/code/electron-utility/sharedProcess/sharedProcessMain.js"
"app/out/vs/code/node/cliProcessMain.js" "app/out/vs/code/node/cliProcessMain.js"
) )
@ -841,13 +845,13 @@ find_cursor_js_files() {
} }
# 修改Cursor的JS文件 # 修改Cursor的JS文件
# 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版 Hook 方案)
# 🔧 修改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"
# 先查找需要修改的JS文件 # 先查找需要修改的JS文件
if ! find_cursor_js_files; then if ! find_cursor_js_files; then
@ -861,6 +865,7 @@ modify_cursor_js_files() {
# 生成或复用设备标识符(优先使用配置中读取的值) # 生成或复用设备标识符(优先使用配置中读取的值)
local machine_id="${CURSOR_ID_MACHINE_ID:-}" local machine_id="${CURSOR_ID_MACHINE_ID:-}"
local machine_guid="${CURSOR_ID_MACHINE_GUID:-}"
local device_id="${CURSOR_ID_DEVICE_ID:-}" local device_id="${CURSOR_ID_DEVICE_ID:-}"
local mac_machine_id="${CURSOR_ID_MAC_MACHINE_ID:-}" local mac_machine_id="${CURSOR_ID_MAC_MACHINE_ID:-}"
local sqm_id="${CURSOR_ID_SQM_ID:-}" local sqm_id="${CURSOR_ID_SQM_ID:-}"
@ -873,6 +878,10 @@ modify_cursor_js_files() {
machine_id=$(openssl rand -hex 32) machine_id=$(openssl rand -hex 32)
ids_missing=true ids_missing=true
fi fi
if [ -z "$machine_guid" ]; then
machine_guid=$(generate_uuid)
ids_missing=true
fi
if [ -z "$device_id" ]; then if [ -z "$device_id" ]; then
device_id=$(generate_uuid) device_id=$(generate_uuid)
ids_missing=true ids_missing=true
@ -901,6 +910,7 @@ modify_cursor_js_files() {
fi fi
CURSOR_ID_MACHINE_ID="$machine_id" CURSOR_ID_MACHINE_ID="$machine_id"
CURSOR_ID_MACHINE_GUID="$machine_guid"
CURSOR_ID_DEVICE_ID="$device_id" CURSOR_ID_DEVICE_ID="$device_id"
CURSOR_ID_MAC_MACHINE_ID="$mac_machine_id" CURSOR_ID_MAC_MACHINE_ID="$mac_machine_id"
CURSOR_ID_SQM_ID="$sqm_id" CURSOR_ID_SQM_ID="$sqm_id"
@ -910,6 +920,7 @@ modify_cursor_js_files() {
log_info "🔑 [准备] 设备标识符已就绪" 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"
@ -923,16 +934,75 @@ 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
chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$ids_config_path" 2>/dev/null || true chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$ids_config_path" 2>/dev/null || true
log_info "💾 [保存] 新的 ID 配置已保存到: $ids_config_path" 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 modified_count=0
local file_modification_status=() local file_modification_status=()
@ -1041,102 +1111,66 @@ EOF
replaced=true replaced=true
fi 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__*/ ;(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 __require__=typeof require==="function"?require:null;
if(!__require__){
var __m__=await import("module"); var __m__=await import("module");
__require__=__m__.createRequire(import.meta.url); __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 } { print }
' "$file" > "$temp_file" ' "$file" > "$temp_file"
log_info " ✓ [方案B] 增强版 Hook 代码已注入(版权声明后)"
log_info " ✓ [方案C] Loader Stub 已注入(版权声明后)"
else else
echo "$inject_code" > "$temp_file" echo "$inject_code" > "$temp_file"
cat "$file" >> "$temp_file" cat "$file" >> "$temp_file"
log_info " ✓ [方案B] 增强版 Hook 代码已注入(文件开头)"
log_info " ✓ [方案C] Loader Stub 已注入(文件开头)"
fi fi
if mv "$temp_file" "$file"; then if mv "$temp_file" "$file"; then
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++))
file_modification_status+=("'$(basename "$file")': Success") file_modification_status+=("'$(basename "$file")': Success")
@ -1191,9 +1228,10 @@ console.log("[Cursor ID Modifier] 增强版 Hook 已激活 - 煎饼果子(86)
fi fi
log_info "🎉 [完成] 成功修改 $modified_count 个JS文件" log_info "🎉 [完成] 成功修改 $modified_count 个JS文件"
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
} }

273
scripts/run/cursor_mac_id_modifier.sh

@ -755,6 +755,7 @@ BACKUP_DIR="$TARGET_HOME/Library/Application Support/Cursor/User/globalStorage/b
# 共享ID(用于配置与JS注入保持一致) # 共享ID(用于配置与JS注入保持一致)
CURSOR_ID_MACHINE_ID="" CURSOR_ID_MACHINE_ID=""
CURSOR_ID_MACHINE_GUID=""
CURSOR_ID_MAC_MACHINE_ID="" CURSOR_ID_MAC_MACHINE_ID=""
CURSOR_ID_DEVICE_ID="" CURSOR_ID_DEVICE_ID=""
CURSOR_ID_SQM_ID="" CURSOR_ID_SQM_ID=""
@ -1434,31 +1435,10 @@ _show_troubleshooting_info() {
echo echo
} }
# 智能设备识别绕过(优先MAC地址修改,失败则JS注入)
# 智能设备识别绕过(已移除 MAC 地址修改,仅保留 JS 注入)
run_device_bypass() { 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 if modify_cursor_js_files; then
log_info "✅ [JS] JS 内核注入完成" log_info "✅ [JS] JS 内核注入完成"
return 0 return 0
@ -1572,13 +1552,13 @@ protect_storage_file() {
fi fi
} }
# 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版 Hook 方案)
# 🔧 修改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应用是否存在
@ -1589,6 +1569,7 @@ modify_cursor_js_files() {
# 生成或复用设备标识符(优先使用配置中生成的值) # 生成或复用设备标识符(优先使用配置中生成的值)
local machine_id="${CURSOR_ID_MACHINE_ID:-}" local machine_id="${CURSOR_ID_MACHINE_ID:-}"
local machine_guid="${CURSOR_ID_MACHINE_GUID:-}"
local device_id="${CURSOR_ID_DEVICE_ID:-}" local device_id="${CURSOR_ID_DEVICE_ID:-}"
local mac_machine_id="${CURSOR_ID_MAC_MACHINE_ID:-}" local mac_machine_id="${CURSOR_ID_MAC_MACHINE_ID:-}"
local sqm_id="${CURSOR_ID_SQM_ID:-}" local sqm_id="${CURSOR_ID_SQM_ID:-}"
@ -1601,6 +1582,10 @@ modify_cursor_js_files() {
machine_id=$(openssl rand -hex 32) machine_id=$(openssl rand -hex 32)
ids_missing=true ids_missing=true
fi fi
if [ -z "$machine_guid" ]; then
machine_guid=$(uuidgen | tr '[:upper:]' '[:lower:]')
ids_missing=true
fi
if [ -z "$device_id" ]; then if [ -z "$device_id" ]; then
device_id=$(uuidgen | tr '[:upper:]' '[:lower:]') device_id=$(uuidgen | tr '[:upper:]' '[:lower:]')
ids_missing=true ids_missing=true
@ -1629,6 +1614,7 @@ modify_cursor_js_files() {
fi fi
CURSOR_ID_MACHINE_ID="$machine_id" CURSOR_ID_MACHINE_ID="$machine_id"
CURSOR_ID_MACHINE_GUID="$machine_guid"
CURSOR_ID_DEVICE_ID="$device_id" CURSOR_ID_DEVICE_ID="$device_id"
CURSOR_ID_MAC_MACHINE_ID="$mac_machine_id" CURSOR_ID_MAC_MACHINE_ID="$mac_machine_id"
CURSOR_ID_SQM_ID="$sqm_id" CURSOR_ID_SQM_ID="$sqm_id"
@ -1638,6 +1624,7 @@ modify_cursor_js_files() {
log_info "🔑 [准备] 设备标识符已就绪" 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"
@ -1652,18 +1639,78 @@ 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 [ -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=( 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
@ -1791,106 +1838,66 @@ EOF
replaced=true replaced=true
fi 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__*/ ;(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 __require__=typeof require==="function"?require:null;
if(!__require__){
var __m__=await import("module"); var __m__=await import("module");
__require__=__m__.createRequire(import.meta.url); __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));
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);
} }
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;}};
}
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 } { 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
@ -2855,7 +2866,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
@ -2865,7 +2876,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
@ -2964,10 +2975,10 @@ 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 if ! run_device_bypass; then
log_warn "⚠️ [设备识别] 智能设备识别绕过未完全成功,请查看日志" log_warn "⚠️ [设备识别] 智能设备识别绕过未完全成功,请查看日志"
fi fi

240
scripts/run/cursor_win_id_modifier.ps1

@ -27,11 +27,11 @@ function Generate-RandomString {
# 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版三重方案) # 🔧 修改Cursor内核JS文件实现设备识别绕过(增强版三重方案)
# 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名 # 方案A: someValue占位符替换 - 稳定锚点,不依赖混淆后的函数名
# 方案B: b6 定点重写 - 机器码源函数直接返回固定值 # 方案B: b6 定点重写 - 机器码源函数直接返回固定值
# 方案C: 深度 Hook + 共享进程注入 - 拦截 child_process/crypto/os/@vscode 等模块
# 方案C: Loader Stub + 外置 Hook - 主/共享进程仅加载外置 Hook 文件
function Modify-CursorJSFiles { function Modify-CursorJSFiles {
Write-Host "" Write-Host ""
Write-Host "$BLUE🔧 [内核修改]$NC 开始修改Cursor内核JS文件实现设备识别绕过..." Write-Host "$BLUE🔧 [内核修改]$NC 开始修改Cursor内核JS文件实现设备识别绕过..."
Write-Host "$BLUE💡 [方案]$NC 使用增强版三重方案:占位符替换 + b6 定点重写 + 共享进程 Hook"
Write-Host "$BLUE💡 [方案]$NC 使用增强版三重方案:占位符替换 + b6 定点重写 + Loader Stub + 外置 Hook"
Write-Host "" Write-Host ""
# Windows版Cursor应用路径 # Windows版Cursor应用路径
@ -125,6 +125,46 @@ function Modify-CursorJSFiles {
$idsConfig | ConvertTo-Json | Set-Content -Path $idsConfigPath -Encoding UTF8 $idsConfig | ConvertTo-Json | Set-Content -Path $idsConfigPath -Encoding UTF8
Write-Host "$GREEN💾 [保存]$NC 新的 ID 配置已保存到: $idsConfigPath" 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路径,按优先级排序) # 目标JS文件列表(Windows路径,按优先级排序)
$jsFiles = @( $jsFiles = @(
"$cursorAppPath\resources\app\out\main.js", "$cursorAppPath\resources\app\out\main.js",
@ -258,7 +298,8 @@ function Modify-CursorJSFiles {
# ========== 方法B: b6 定点重写(机器码源函数,仅 main.js) ========== # ========== 方法B: b6 定点重写(机器码源函数,仅 main.js) ==========
# 说明:b6(t) 是 machineId 的核心生成函数,t=true 返回原始值,t=false 返回哈希 # 说明:b6(t) 是 machineId 的核心生成函数,t=true 返回原始值,t=false 返回哈希
if ((Split-Path $file -Leaf) -eq "main.js") { 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';}" $b6Replacement = "async function b6(t){return t?'$machineGuid':'$machineId';}"
$b6Regex = [regex]::new($b6Pattern) $b6Regex = [regex]::new($b6Pattern)
if ($b6Regex.IsMatch($content)) { 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 = @" $injectCode = @"
// ========== Cursor Hook 注入开始 ==========
// ========== Cursor Hook Loader 开始 ==========
;(async function(){/*__cursor_patched__*/ ;(async function(){/*__cursor_patched__*/
'use strict'; 'use strict';
if (globalThis.__cursor_patched__) return;
globalThis.__cursor_patched__ = true;
if (globalThis.__cursor_hook_loaded__) return;
globalThis.__cursor_hook_loaded__ = true;
try { 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; var __require__ = typeof require === 'function' ? require : null;
if (!__require__) { if (!__require__) {
try {
var __m__ = await import('module'); var __m__ = await import('module');
__require__ = __m__.createRequire(import.meta.url); __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;
}
}
// 处理 node: 前缀模块名
function __normalizeId__(id){
return (typeof id === 'string' && id.indexOf('node:') === 0) ? id.slice(5) : id;
}
// 先覆盖全局 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 osMAC 地址
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 cryptohash/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 + 共享进程)');
}
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);
}
} catch (e) { } 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)') { if ($content -match '(\*/\s*\n)') {
$content = $content -replace '(\*/\s*\n)', "`$1$injectCode" $content = $content -replace '(\*/\s*\n)', "`$1$injectCode"
Write-Host " $GREEN✓$NC [方案C] 增强版 Hook 代码已注入(版权声明后)"
Write-Host " $GREEN✓$NC [方案C] Loader Stub 已注入(版权声明后)"
} else { } else {
# 如果没有找到版权声明,则注入到文件开头 # 如果没有找到版权声明,则注入到文件开头
$content = $injectCode + $content $content = $injectCode + $content
Write-Host " $GREEN✓$NC [方案C] 增强版 Hook 代码已注入(文件开头)"
Write-Host " $GREEN✓$NC [方案C] Loader Stub 已注入(文件开头)"
} }
# 写入修改后的内容 # 写入修改后的内容
@ -473,7 +359,7 @@ try {
$summaryParts = @() $summaryParts = @()
if ($replaced) { $summaryParts += "someValue替换" } if ($replaced) { $summaryParts += "someValue替换" }
if ($replacedB6) { $summaryParts += "b6定点重写" } if ($replacedB6) { $summaryParts += "b6定点重写" }
$summaryParts += "深度Hook"
$summaryParts += "Hook加载器"
$summaryText = ($summaryParts -join " + ") $summaryText = ($summaryParts -join " + ")
Write-Host "$GREEN✅ [成功]$NC 增强版方案修改成功($summaryText)" Write-Host "$GREEN✅ [成功]$NC 增强版方案修改成功($summaryText)"
$modifiedCount++ $modifiedCount++
@ -497,7 +383,7 @@ try {
Write-Host "$BLUE💡 [说明]$NC 使用增强版三重方案:" Write-Host "$BLUE💡 [说明]$NC 使用增强版三重方案:"
Write-Host " • 方案A: someValue占位符替换(稳定锚点,跨版本兼容)" Write-Host " • 方案A: someValue占位符替换(稳定锚点,跨版本兼容)"
Write-Host " • 方案B: b6 定点重写(机器码源函数)" 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" Write-Host "$BLUE📁 [配置]$NC ID 配置文件: $idsConfigPath"
return $true return $true
} else { } else {

Loading…
Cancel
Save