Typora → Rebrand Reverse Engineering Skill
逆向工程与品牌替换 Typora Electron 应用的完整方法论。核心理念:Typora 是层层加密的 Electron 应用,品牌替换需要精确理解哪些可以改、哪些改了会炸。
架构概览
Typora.exe (Electron runtime, renamed)
└── resources/
├── app.asar ← Electron 归档 (包含 atom.js, main.node, package.json)
├── app.asar.unpacked/ ← 原生模块提取目录
│ └── main.node ← **实际加载的** C++ 原生模块 (PE32 DLL)
├── window.html ← 主窗口 UI (可安全修改用户可见文本)
├── page-dist/ ← Vite 构建的页面产物
├── locales/ ← 39 种语言的本地化文件
├── plugin/ ← 插件系统 (terminal, copilot, etc.)
├── appsrc/ ← 未压缩的源代码 (frame.js, finder-worker.js)
├── html/ ← 编辑器 iframe 内容 (content.html, preview.html)
├── style/ ← CSS 样式表
└── copilot/ ← GitHub Copilot 集成
核心规则:安全与不安全的替换
可以安全修改(仅用户可见文本)
这些修改只影响用户看到的文字,不涉及内部逻辑:
window.html中的<title>、标题栏<span id="title-text">package.json元数据:name, author, homepage, concatconf.default.json中的 URL 引用- 所有
locales/*/JSON 文件中的品牌名和 URL page-dist/*.html页面中的可见文本copilot/package.json元数据Docs/*.md文档文件plugin/**/*.js中console.log("Typora")等可见字符串
绝对不能修改(修改会破坏应用)
这些都是内部架构标识符,改了会导致功能异常或应用崩溃:
typora://协议 URL — 由 main.node 注册的自定义协议,window.html 和所有页面通过它加载资源。修改 main.node 中的协议名 → 所有typora://app/...引用全部失效 → 应用白屏ty-CSS 类名前缀 — 全局 CSS 选择器依赖- DOM IDs —
typora-sidebar,typora-quick-open,typora-source等,JS 代码通过 ID 查找元素 - JS 函数/变量名 —
typoraVersion,exitTypora(),canOpenByTypora()等 --tyopt=CLI 参数 — 由 main.node 解析的命令行参数- atom.js 加密内容 — 主进程核心逻辑,修改需走完整解密→修改→重加密流程
详细清单见
references/branding-guide.md
关键技能领域
1. app.asar 操作
# 提取
npx asar extract app.asar <output_dir>
# 列出内容
npx asar list app.asar
# 重新打包
npx asar pack <input_dir> app.asar --unpack "{*.node,*.so,*.dylib}"
关键陷阱:app.asar.unpacked/ 中的原生模块 (.node) 是 Electron 实际加载的版本。asar 内的同名文件仅作为占位符。修改原生模块必须同时修改 unpacked 版本。
2. main.node 逆向
main.node 是编译的 C++ Node.js 原生模块 (PE32 DLL on Windows)。包含单一的 "typora" 字符串,控制:
- 自定义协议注册 (
typora://) - 注册表键名 (
HKCU\Software\Typora) - 可能的其他内部标识符
# 查找 typora 字符串
strings main.node | grep -i typora
# 精确定位偏移量
hexdump -C main.node | grep typora
# 比较两个 main.node 的差异
cmp -l main1.node main2.node
Hex-patch 规则:
- 必须保持字符串长度不变("typora" → "typola" 同为 6 字节,可替换)
- 警告:修改此字符串会改变协议注册名 → 所有
typora://URL 失效 → 应用无法加载资源 - 经验结论:不要修改 main.node 中的 "typora" 字符串,品牌信息通过 package.json 和 HTML 控制
3. atom.js 加密系统
atom.js 是 Electron 主进程的核心 JavaScript 文件,包含:
- 窗口管理和菜单创建
- 自定义协议注册 (
protocol.registerFileProtocol) - 激活/许可证验证
- Sentry 错误上报
- 自动更新检查
- IPC 通信处理
atom.js 存储在 app.asar 中,经过 AES-256-CBC 加密 + Base64 编码:
- 密钥和 IV 计算逻辑在 main.node 的编译代码中
- 解密需逆向 main.node 获取密钥派生算法
- 可以从 main.node 中提取密钥,或通过 hex-patch 跳过解密步骤直接执行明文 JS
# 检查 atom.js 是否为加密内容 (base64 编码的头部特征)
head -c 100 atom.js | xxd
详细流程见
references/atomjs-crypto.md
4. 7-Zip SFX 安装包制作
用于创建 Windows 自解压安装程序:
# Step 1: 创建 config.txt
cat > config.txt << 'EOF'
;!@Install@!UTF-8!
Title="MyApp 1.0.0 Setup"
BeginPrompt="Welcome to MyApp Setup. Install to the selected folder?"
ExtractPathText="Select installation folder:"
ExtractDialogText="MyApp Setup"
GUIFlags="8+32+64+256+4096"
CancelPrompt="Cancel installation?"
FinishMessage="MyApp has been installed."
RunProgram="scripts\\setup.bat"
;!@InstallEnd@!
EOF
# Step 2: 创建 7z 归档
7z a -t7z -m0=lzma2 -mx=9 -mhe=on archive.7z ./app-folder/ -xr!*.bak -xr!.git*
# Step 3: 拼接 SFX
cat "C:/Program Files/7-Zip/7z.sfx" config.txt archive.7z > Setup-MyApp.exe
注意事项:
- 排除
.bak文件和.git目录 - RunProgram 在提取后从提取目录执行
- 使用
7z l Setup.exe验证内容
5. macOS → Linux 转换
基于 macos2linuxapp 技能的经验:
# 从 DMG 提取 (需要 7zz 24.09+, 旧版无法处理 APFS DMG)
7zz x App.dmg
# 提取 app.asar
npx asar extract "App.app/Contents/Resources/app.asar" app-extracted
# 为目标平台重建原生模块
npx @electron/rebuild -v <ELECTRON_VERSION> --force
# 移除 macOS 专有模块
rm -rf app-extracted/node_modules/sparkle-darwin
# Linux UI 适配:动态检测 path 变量名
# 不要硬编码 t.join,Vite 压缩后变量名会变化
pathVarMatch = source.match(/\blet\s+([A-Za-z_$][\w$]*)=require\(`(?:node:)?path`\)/)
# 修复透明窗口闪烁 (Linux 不支持 vibrancy)
# dark mode: backgroundColor → '#000000'
# light mode: backgroundColor → '#f9f9f9'
详细流程见
references/cross-platform.md
调试与验证
# 用户数据目录 (由 package.json name 决定)
%APPDATA%/{app.name}/
# 日志文件
%APPDATA%/{app.name}/typora.log
# 注册表路径 (由 main.node 写入)
HKCU\Software\{app.name}
# 验证主进程日志
tail -f %APPDATA%/Typola/typora.log
# 检查协议引用
grep -r "typora://" resources/ --include="*.html" --include="*.js"
# 验证 asar 完整性
npx asar list resources/app.asar
# 检查 SFX 内容
7z l Setup-App.exe
# 运行时错误:检查 typora.log 中的 ERROR 行
grep ERROR %APPDATA%/Typola/typora.log
常见问题
| 症状 | 原因 | 修复 |
|---|---|---|
| 应用白屏/资源加载失败 | 修改了 main.node 中的 "typora" 字符串 | 恢复原始 main.node,品牌信息通过 HTML/package.json 控制 |
render process is killed |
JS 错误或资源 404 | 检查 window.html 中的 typora:// 协议引用未被修改 |
| 窗口透明闪烁 (Linux) | 原应用使用 macOS vibrancy | patch backgroundColor 为不透明色 |
Cannot find module |
asar 打包不完整 | 重新从原始 DMG/安装提取 |
| 原生模块加载失败 | .node 文件与平台不匹配 | 使用 @electron/rebuild 为目标平台编译 |
| SFX 安装后不运行 | RunProgram 路径错误或 setup.bat 权限问题 | 检查 SFX config 中 RunProgram 路径和脚本语法 |