-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcursor_shadow_patcher.py
More file actions
287 lines (228 loc) · 8.16 KB
/
Copy pathcursor_shadow_patcher.py
File metadata and controls
287 lines (228 loc) · 8.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
import os
import re
import random
import shutil
import pathlib
import platform
from uuid import uuid4
from logger import info, warning, error
from config import CURSOR_PATH
# 颜色常量定义,保留用于日志输出
GREEN = "\033[92m"
RED = "\033[91m"
YELLOW = "\033[93m"
BLUE = "\033[96m"
PURPLE = "\033[95m"
RESET = "\033[0m"
SYSTEM = platform.system()
if SYSTEM not in ("Windows", "Linux", "Darwin"):
raise OSError(f"不支持的操作系统: {SYSTEM}")
def uuid():
"""生成随机UUID"""
return str(uuid4())
def path(path_str):
"""获取绝对路径"""
return pathlib.Path(path_str).resolve()
def randomuuid(randomuuid_str):
"""获取随机UUID,如果提供则使用提供的值"""
if not randomuuid_str:
randomuuid_str = uuid()
return randomuuid_str
def random_mac(macaddr: str = None):
"""生成随机MAC地址"""
if not macaddr:
while not macaddr or macaddr in (
"00:00:00:00:00:00",
"ff:ff:ff:ff:ff:ff",
"ac:de:48:00:11:22",
):
macaddr = ":".join([f"{random.randint(0, 255):02X}" for _ in range(6)])
return macaddr
def load(file_path: pathlib.Path):
"""加载文件内容"""
with open(file_path, "rb") as f:
return f.read()
def save(file_path: pathlib.Path, data: bytes):
"""保存文件内容"""
with open(file_path, "wb") as f:
f.write(data)
def backup(file_path: pathlib.Path):
"""备份文件"""
backup_path = file_path.with_suffix(file_path.suffix + ".bak")
if not backup_path.exists():
shutil.copy2(file_path, backup_path)
print(f"已备份 {file_path} -> {backup_path}")
def replace(data: bytes, pattern: str, replace_str: str, probe: str = None) -> bytes:
"""替换文件内容"""
pattern_bytes = pattern.encode() if isinstance(pattern, str) else pattern
replace_bytes = (
replace_str.encode() if isinstance(replace_str, str) else replace_str
)
if probe:
probe_bytes = probe.encode() if isinstance(probe, str) else probe
if re.search(probe_bytes, data):
print("检测到已经被修补的代码,跳过...")
return data
return re.sub(pattern_bytes, replace_bytes, data)
def find_main_js():
"""查找Cursor的main.js文件"""
error(f"SYSTEM: {SYSTEM}")
if SYSTEM == "Windows":
localappdata = os.getenv("LOCALAPPDATA")
if not localappdata:
raise OSError("环境变量 %LOCALAPPDATA% 不存在")
# 使用本地变量保存路径
cursor_path = CURSOR_PATH
if not cursor_path:
error("当前windows系统, 环境变量 CURSOR_PATH 不存在,使用默认路径")
cursor_path = os.getenv("LOCALAPPDATA", "")
else:
info(f"当前windows系统, CURSOR_PATH: {cursor_path}")
# 常见的Cursor安装路径
paths = [
path(os.path.join(cursor_path, "resources", "app", "out", "main.js")),
path(
os.path.join(
localappdata,
"Programs",
"cursor",
"resources",
"app",
"out",
"main.js",
)
),
path(
os.path.join(
localappdata, "cursor", "resources", "app", "out", "main.js"
)
),
]
for p in paths:
info(f"检查路径: {p}")
if p.exists():
info(f"找到main.js: {p}")
return p
else:
warning(f"路径不存在: {p}")
elif SYSTEM == "Darwin": # macOS
paths = [
path("/Applications/Cursor.app/Contents/Resources/app/out/main.js"),
path(
os.path.expanduser(
"~/Applications/Cursor.app/Contents/Resources/app/out/main.js"
)
),
]
for p in paths:
if p.exists():
return p
elif SYSTEM == "Linux":
# Linux上常见的安装路径
paths = [
path("/usr/share/cursor/resources/app/out/main.js"),
path(os.path.expanduser("~/.local/share/cursor/resources/app/out/main.js")),
]
for p in paths:
if p.exists():
return p
raise FileNotFoundError("无法找到Cursor的main.js文件,请手动指定路径")
def patch_cursor(
js_path=None, machine_id=None, mac_addr=None, sqm_id=None, dev_id=None
):
"""
修补Cursor的main.js文件,替换机器ID等识别信息
参数:
js_path: main.js文件路径,如果为None则自动查找
machine_id: 机器ID,如果为None则随机生成
mac_addr: MAC地址,如果为None则随机生成
sqm_id: Windows SQM ID,如果为None则使用空字符串
dev_id: 设备ID,如果为None则随机生成
返回:
bool: 是否成功
"""
try:
# 查找main.js文件
if not js_path:
js_path = find_main_js()
else:
js_path = path(js_path)
# 如果找不到main.js文件
if not js_path.exists():
print(f"错误: 找不到文件 {js_path}")
return False
print(f"找到main.js文件: {js_path}")
# 随机生成ID
machine_id = randomuuid(machine_id)
mac_addr = mac_addr or random_mac()
sqm_id = sqm_id or ""
dev_id = randomuuid(dev_id)
# 加载文件内容
data = load(js_path)
# 备份文件
backup(js_path)
# 替换机器ID
data = replace(
data,
r"=.{0,50}timeout.{0,10}5e3.*?,",
f'=/*csp1*/"{machine_id}"/*1csp*/,',
r"=/\*csp1\*/.*?/\*1csp\*/,",
)
# 替换MAC地址
data = replace(
data,
r"(function .{0,50}\{).{0,300}Unable to retrieve mac address.*?(\})",
f'\\1return/*csp2*/"{mac_addr}"/*2csp*/;\\2',
r"()return/\*csp2\*/.*?/\*2csp\*/;()",
)
# 替换SQM ID
data = replace(
data,
r'return.{0,50}\.GetStringRegKey.*?HKEY_LOCAL_MACHINE.*?MachineId.*?\|\|.*?""',
f'return/*csp3*/"{sqm_id}"/*3csp*/',
r"return/\*csp3\*/.*?/\*3csp\*/",
)
# 替换设备ID
data = replace(
data,
r"return.{0,50}vscode\/deviceid.*?getDeviceId\(\)",
f'return/*csp4*/"{dev_id}"/*4csp*/',
r"return/\*csp4\*/.*?/\*4csp\*/",
)
# 保存修改后的文件
save(js_path, data)
print(f"成功修补 {js_path}")
print(f"机器ID: {machine_id}")
print(f"MAC地址: {mac_addr}")
print(f"SQM ID: {sqm_id}")
print(f"设备ID: {dev_id}")
return True
except Exception as e:
print(f"错误: {str(e)}")
import traceback
traceback.print_exc()
return False
class CursorShadowPatcher:
"""Cursor机器标识修改器"""
@staticmethod
def reset_machine_ids():
"""重置所有机器标识"""
return patch_cursor()
if __name__ == "__main__":
# 作为独立脚本运行时,执行交互式修补
print(f"\n{'=' * 50}")
print("Cursor 机器标识重置工具 (Shadow Patch 增强版)")
print(f"{'=' * 50}")
js_path = input("请输入main.js路径 (留空=自动检测): ")
machine_id = input("机器ID (留空=随机生成): ")
mac_addr = input("MAC地址 (留空=随机生成): ")
sqm_id = input("Windows SQM ID (留空=使用空值): ")
dev_id = input("设备ID (留空=随机生成): ")
success = patch_cursor(js_path, machine_id, mac_addr, sqm_id, dev_id)
if success:
print(f"\n{'=' * 50}")
print("修补成功!")
else:
print(f"\n{'=' * 50}")
print("修补失败!")
input("按回车键退出...")