Xmind 介绍
Xmind 是一款 全功能 的思维导图和头脑风暴软件。像大脑的瑞士军刀一般,助你理清思路,捕捉创意。
Windows 版本激活/破解脚本
注意:必须安装 python 环境,否则报错:

安装 python 环境
下载 python for windows:https://www.python.org/downloads/windows/



python 环境安装成功后,按下面流程操作:
1、下载完整脚本包:crack_xmind.zip (5.3 KB) 2、解压后执行 一键脚本 (无需管理员身份运行)
常见问题
FileExistsError
Traceback (most recent call last): File "C:\Users\admin\AppData\Local\Programs\Xmind\xmind.py", line 108, in <module> XmindKeyGen().run() File "C:\Users\admin\AppData\Local\Programs\Xmind\xmind.py", line 31, in run patch_info = self.patch() ^^^^^^^^^^^^ File "C:\Users\admin\AppData\Local\Programs\Xmind\xmind.py", line 69, in patch extract_asar(str(self.asar_file), str(self.crack_asar_dir)) File "C:\Users\admin\AppData\Local\Programs\Xmind\venv\Lib\site-packages\asarPy\asar.py", line 162, in extract_asar a.extract(dest) File "C:\Users\admin\AppData\Local\Programs\Xmind\venv\Lib\site-packages\asarPy\asar.py", line 143, in extract raise FileExistsError() FileExistsError 请按任意键继续. . .

解决方案
卸载重装!卸载重装!卸载重装!
重要的事情说三遍,讲你的 xmind 卸载,下载重装最新版即可。不需要管理员权限运行,脚本也没问题。
解决后正常脚本输出如下图:

破解成功

脚本源码
import os
import pathlib
import shutil
from abc import ABCMeta
from abc import abstractmethod
from base64 import b64encode, b64decode
from asarPy import extract_asar, pack_asar
from crypto_plus import CryptoPlus
from crypto_plus.encrypt import encrypt_by_key, decrypt_by_key
class KeyGen(metaclass=ABCMeta):
@abstractmethod
def generate(self):
pass
@abstractmethod
def parse(self, licenses):
pass
@abstractmethod
def patch(self):
return ""
def run(self, patch=True):
ciphertext_licenses = self.generate()
print(f"ciphertext_licenses: \n{ciphertext_licenses}")
if patch:
patch_info = self.patch()
if patch_info:
print(f"patch: \n{patch_info}")
plaintext_licenses = self.parse(ciphertext_licenses)
print(f'plaintext_licenses: \n{plaintext_licenses}')
class XmindKeyGen(KeyGen):
def __init__(self):
tmp_path = os.environ['TMP']
asar_path = pathlib.Path(tmp_path).parent.joinpath(r'Programs\Xmind\resources')
self.asar_file = asar_path.joinpath('app.asar')
self.asar_file_bak = asar_path.joinpath('app.asar.bak')
self.crack_asar_dir = asar_path.joinpath('ext')
self.main_dir = self.crack_asar_dir.joinpath("main")
self.renderer_dir = self.crack_asar_dir.joinpath("renderer")
self.private_key = None
self.public_key = None
self.old_public_key = open('old.pem').read()
def generate(self):
if os.path.isfile('key.pem'):
rsa = CryptoPlus.load('key.pem')
else:
rsa = CryptoPlus.generate_rsa(1024)
rsa.dump("key.pem", "new_public_key.pem")
license_info = '{"status": "sub", "expireTime": 4093057076000, "ss": "", "deviceId": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"}'
self.public_key = rsa.public_key
self.private_key = rsa.private_key
self.license_data = b64encode(encrypt_by_key(rsa.private_key, license_info.encode()))
return self.license_data
def parse(self, licenses):
return decrypt_by_key(self.public_key, b64decode(licenses))
def patch(self):
# 解包
extract_asar(str(self.asar_file), str(self.crack_asar_dir))
shutil.copytree('crack', self.main_dir, dirs_exist_ok=True)
# 注入
with open(self.main_dir.joinpath('main.js'), 'rb') as f:
lines = f.readlines()
lines[5] = b'require("./hook")\n'
with open(self.main_dir.joinpath('main.js'), 'wb') as f:
f.writelines(lines)
# 替换密钥
old_key = f"String.fromCharCode({','.join([str(i) for i in self.old_public_key.encode()])})".encode()
new_key = f"String.fromCharCode({','.join([str(i) for i in self.public_key.export_key()])})".encode()
for js_file in self.renderer_dir.rglob("*.js"):
with open(js_file, 'rb') as f:
byte_str = f.read()
index = byte_str.find(old_key)
if index != -1:
byte_str.replace(old_key, new_key)
with open(js_file, 'wb') as _f:
_f.write(byte_str.replace(old_key, new_key))
print(js_file)
break
# 占位符填充
with open(self.main_dir.joinpath('hook.js'), 'r', encoding='u8') as f:
content = f.read()
content = content.replace("{{license_data}}", self.license_data.decode())
with open(self.main_dir.joinpath('hook.js'), 'w', encoding='u8') as f:
f.write(content)
with open(self.main_dir.joinpath('hook').joinpath('crypto.js'), 'r', encoding='u8') as f:
content = f.read()
content = content.replace("{{old_public_key}}", self.old_public_key.replace("\n", "\\n"))
content = content.replace("{{new_public_key}}", self.public_key.export_key().decode().replace("\n", "\\n"))
with open(self.main_dir.joinpath('hook').joinpath('crypto.js'), 'w', encoding='u8') as f:
f.write(content)
# 封包
os.remove(self.asar_file)
pack_asar(self.crack_asar_dir, self.asar_file)
shutil.rmtree(self.crack_asar_dir)
if __name__ == '__main__':
XmindKeyGen().run()
macOS 版本激活/破解脚本
1、下载完整脚本包:crack_xmind_macos.zip(12 KB) 2、解压后执行 xmind.py (需要python 环境,见:macOS 安装 python)
python3 xmind.py
如果脚本运行正常,你会得到以下内容:

此时不要打开xmind,否则会得到如下反馈(xmind 已损坏,无法打开):

3、为解决上述报错,在命令行执行如下脚本:
sudo xattr -rd com.apple.quarantine /Applications/Xmind.app
破解成功
注册登录账号后,打开 xmind:

脚本源码
import os
import pathlib
import shutil
from base64 import b64decode, b64encode
from asarPy import extract_asar, pack_asar
from crypto_plus import CryptoPlus
from crypto_plus.encrypt import decrypt_by_key, encrypt_by_key
from abc import ABCMeta, abstractmethod
class KeyGen(metaclass=ABCMeta):
@abstractmethod
def generate(self):
pass
@abstractmethod
def parse(self, licenses):
pass
@abstractmethod
def patch(self):
return ""
def run(self, patch=True):
ciphertext_licenses = self.generate()
print(f"ciphertext_licenses: \n{ciphertext_licenses}")
if patch:
patch_info = self.patch()
if patch_info:
print(f"patch: \n{patch_info}")
plaintext_licenses = self.parse(ciphertext_licenses)
print(f'plaintext_licenses: \n{plaintext_licenses}')
class XmindKeyGen(KeyGen):
def __init__(self):
# tmp_path = os.environ['TMP']
# mac 软件路径不一样,可以自己看着修改
asar_path = pathlib.Path('/Applications/Xmind.app/Contents/Resources')
self.asar_file = asar_path.joinpath('app.asar')
self.asar_file_bak = asar_path.joinpath('app.asar.bak')
self.crack_asar_dir = asar_path.joinpath('ext')
self.main_dir = self.crack_asar_dir.joinpath("main")
self.renderer_dir = self.crack_asar_dir.joinpath("renderer")
self.private_key = None
self.public_key = None
self.old_public_key = open('old.pem').read()
def generate(self):
if os.path.isfile('key.pem'):
rsa = CryptoPlus.load('key.pem')
else:
rsa = CryptoPlus.generate_rsa(1024)
rsa.dump("key.pem", "new_public_key.pem")
license_info = '{"status": "sub", "expireTime": 4093057076000, "ss": "", "deviceId": "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"}'
self.public_key = rsa.public_key
self.private_key = rsa.private_key
self.license_data = b64encode(encrypt_by_key(rsa.private_key, license_info.encode()))
return self.license_data
def parse(self, licenses):
return decrypt_by_key(self.public_key, b64decode(licenses))
def patch(self):
# 先删除接包的内容,防止已经存在报错
shutil.rmtree(self.crack_asar_dir, ignore_errors=True)
# 解包
extract_asar(str(self.asar_file), str(self.crack_asar_dir))
shutil.copytree('crack', self.main_dir, dirs_exist_ok=True)
# 注入
# 看了一下mac最新版本的源代码只有一行,这里采用插入首行
with open(self.main_dir.joinpath('main.js'), 'rb') as f:
lines = f.readlines()
# lines[5] = b'require("./hook")\n'
lines.insert(0, b'require("./hook");\n')
with open(self.main_dir.joinpath('main.js'), 'wb') as f:
f.writelines(lines)
# 替换密钥
old_key = f"String.fromCharCode({','.join([str(i) for i in self.old_public_key.encode()])})".encode()
new_key = f"String.fromCharCode({','.join([str(i) for i in self.public_key.export_key()])})".encode()
for js_file in self.renderer_dir.rglob("*.js"):
with open(js_file, 'rb') as f:
byte_str = f.read()
index = byte_str.find(old_key)
if index != -1:
byte_str.replace(old_key, new_key)
with open(js_file, 'wb') as _f:
_f.write(byte_str.replace(old_key, new_key))
print(js_file)
break
# 手动搜索发现 main.js 里面也有公钥信息,一起替换掉
for js_file in self.main_dir.rglob("*.js"):
with open(js_file, 'rb') as f:
byte_str = f.read()
index = byte_str.find(old_key)
if index != -1:
byte_str.replace(old_key, new_key)
with open(js_file, 'wb') as _f:
_f.write(byte_str.replace(old_key, new_key))
print(js_file)
break
# 占位符填充
with open(self.main_dir.joinpath('hook.js'), 'r', encoding='u8') as f:
content = f.read()
content = content.replace("{{license_data}}", self.license_data.decode())
with open(self.main_dir.joinpath('hook.js'), 'w', encoding='u8') as f:
f.write(content)
with open(self.main_dir.joinpath('hook').joinpath('crypto.js'), 'r', encoding='u8') as f:
content = f.read()
content = content.replace("{{old_public_key}}", self.old_public_key.replace("\n", "\\n"))
content = content.replace("{{new_public_key}}", self.public_key.export_key().decode().replace("\n", "\\n"))
with open(self.main_dir.joinpath('hook').joinpath('crypto.js'), 'w', encoding='u8') as f:
f.write(content)
# 封包
os.remove(self.asar_file)
pack_asar(self.crack_asar_dir, self.asar_file)
shutil.rmtree(self.crack_asar_dir)
if __name__ == '__main__':
XmindKeyGen().run()
常见问题
ModuleNotFoundErrore No module named “asarPy“

解决方案
pip install asarPy ##or pip3 install asarPy
更新日志
2024.10.18 新增读者朋友反馈windows环境没有python导致脚本无法执行的问题及解决方案 2024.10.09 新增读者朋友反馈 FileExistsError 问题导致无法激活问题复现及解决方案。 2024.3.22: 修复无法激活的bug,提供了一键脚本。 注意:
如果以前替换过公钥,需要还原一下app.asar再执行一键脚本,否则重新生成的公钥会不匹配;没备份app.asar的话建议重装最新版。
参考资料
Crack 脚本项目:项目 939
免责申明
本文内容收集自互联网,仅供学习交流,如果不慎侵权请联系(#换@)[email protected] 删除。
请勿传播盗版软件。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
☝️用微信请我喝杯咖啡☕️
😛如果文章对您有用,请支持作者😛
☝️用支付宝请我喝杯奶茶🧋
相关文章
暂无评论...