序章:大航海时代的开启
“想要我的财宝吗?想要的话可以使用,去找吧!我把 Typora 最纯粹的功能都放在Native层了!”
在这个被 Electron(世界政府)统治的新世界里,Typora 原本是记录历史正文的神器。然而,天龙人设下的 v1.0 结界(强制付费墙),让无数渴望自由的极恶世代海贼止步于红土大陆。
我是蒙奇·D·逆向,是要成为逆向王的男人!
今天的冒险,就是要打破这道叹息之墙,夺回属于我们的自由(Activated Status)!
(注:本次冒险仅供技术切磋,切勿破坏海上的商业秩序,若真心喜爱,请向娜美桑上交 $$$ 购买正版!)
第一章:镀膜出航(环境与装备)
要想在新世界航行,没有趁手的家伙可不行。这是我们桑尼号上的装备:
- IDA Pro (见闻色霸气):能够预知未来,看透二进制内部流动的霸气。
- Xcode (弗兰奇将军):甚至能改造肉体的超级工厂。
- tinyhook (三代鬼彻):一把妖刀,轻便锋利,虽然是 C 语言打造,却能斩断 Objective-C 的因果。
- optool (罗的 Room 空间):能在不破坏船体的情况下,将我们的灵魂注入其中。
第二章:解读历史正文(IDA 静态分析)
启动 见闻色霸气(IDA Pro)!这次的目标是 Typora 的本体(位于 Contents/MacOS 的二进制),而不是外面那层光鲜亮丽的 HTML 皮肤。
1. 聆听万物的声音
按下 Shift + F12,开启全图见闻色。在心网中搜索那个名字:LicenseManager。
这便是守护大秘宝的 CP0 长官。
顺着声音(Xref),我们来到了 Objective-C 的处刑台。
2. 也是 CP0 的弱点
在 Methods 列表中,我们发现了 CP0 长官的三个致命弱点:
-
-[LicenseManager _readLicenseInfo:]
- 情报:这是 CP0 检查“天上金”(License File)的地方。
- 作战:不管他们运送的是什么,只要我们用能力替换掉箱子里的东西,把它变成我们在拉夫德鲁看到的财宝(Fake License)即可。
-
-[LicenseManager sendPost:data:host:callback:]
- 情报:这是用来呼叫海军大将(验证服务器)的屠魔令电话虫。
- 作战:只要切断电话虫的信号,海军本部就永远不会知道我们潜入进来了。
-
-[LicenseManager fingerPrintNew]
- 情报:这是生命卡(生命归还)。用来验证你的灵魂和肉体是否匹配。
- 警报:千万别碰这个!如果生命卡烧毁了,船精灵会哭泣(程序崩溃)。我们必须借用它原来的力量。
第三章:手术果实的能力(策略设计)
面对如此强大的敌人,正面硬刚是不明智的。我们需要 特拉法尔加·罗 的 手术果实(Hook)能力。
ROOM —— 屠宰场!
- Shambles(交换):将
_readLicenseInfo: 的心脏挖出来,换成我们准备好的一颗“跳动的心脏”(Fake Dictionary)。
- Silence(静寂):既然不能用手术果实消除声音,那就直接把
sendPost: 变成哑巴,让它发不出任何声音。
- Identify(扫描):对
fingerPrintNew 使用扫描,获取真实的生命卡数据。
第四章:该出手了,索隆!(代码实现)
在 Xcode 中拔出名刀,新建 Framework TyporaHook。
1. 武装色硬化 (tinyhook)
将 tinyhook 锻造进我们的剑身。
2. 三千世界 (Hook.m)
在 Hook.m 中吟唱这毁灭性的剑招:
#import "tinyhook.h"
#import <Foundation/Foundation.h>
#import <objc/message.h> // 必须引入,为了让霸气(msgSend)能流动
@interface Hook : NSObject
@end
@implementation Hook
// ---------------------------------------------------------------------
// 霸王色霸气爆发:在库加载瞬间震慑全场
// ---------------------------------------------------------------------
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 斩断 _readLicenseInfo: 的因果
ocrt_swap("LicenseManager", "_readLicenseInfo:", "Hook", "hooked_readLicenseInfo:");
// 切断电话虫 sendPost:data:host:callback:
ocrt_swap("LicenseManager", "sendPost:data:host:callback:", "Hook", "hooked_sendPost:data:host:callback:");
});
}
// ---------------------------------------------------------------------
// 伪造的大秘宝 (ONE PIECE)
// ---------------------------------------------------------------------
- (id)hooked_readLicenseInfo:(id)arg1 {
// 1. 抓住 CP0 长官 (LicenseManager 单例)
Class mgrClass = NSClassFromString(@"LicenseManager");
// 开启流樱(objc_msgSend),隔空打击
id sharedInstance = ((id (*)(id, SEL))objc_msgSend)(mgrClass, NSSelectorFromString(@"sharedInstance"));
// 2. 制造假的历史正文
NSMutableDictionary *fakeInfo = [NSMutableDictionary dictionary];
// 3. 复制生命卡 (Fingerprint) - 关键!
// 必须用原装的生命卡,否则由于生命力耗尽,船会沉的
NSString *fingerprint = ((id (*)(id, SEL))objc_msgSend)(sharedInstance, NSSelectorFromString(@"fingerPrintNew"));
if (fingerprint) {
[fakeInfo setObject:fingerprint forKey:@"fingerprint"];
}
// 4. 获取悬赏令 ID (Device ID)
NSString *deviceId = ((id (*)(id, SEL))objc_msgSend)(mgrClass, NSSelectorFromString(@"rawMachineId"));
if (deviceId) {
[fakeInfo setObject:deviceId forKey:@"deviceId"];
}
// 5. 书写新的历史
[fakeInfo setObject:@"macxk@foxmail.com" forKey:@"email"]; // D 之意志继承者
[fakeInfo setObject:@"MAC-SERIAL-MACXK" forKey:@"license"]; // 虚空的悬赏金
[fakeInfo setObject:@"Valid" forKey:@"sig"]; // 政府认证印章
[fakeInfo setObject:@"Standard" forKey:@"type"]; // 没有任何异常
[fakeInfo setObject:[NSDate date] forKey:@"installDate"]; // 就在此刻
[fakeInfo setObject:[NSDate date] forKey:@"lastTry"]; // 就在此刻
return fakeInfo;
}
// ---------------------------------------------------------------------
// 哑巴果实能力:阻断联络
// ---------------------------------------------------------------------
- (void)hooked_sendPost:(id)arg1 data:(id)arg2 host:(id)arg3 callback:(id)arg4 {
// 这里是无风带。
// 没有任何消息能传出去,也没有任何海王类能游进来。
}
@end
">
第五章:新世界的险恶 (避坑指南)
新世界的气候变幻莫测,如果不注意记录指针,很容易全军覆没。
1. 旧时代的残党 (Architecture Mismatch)
不少极恶世代的新人,只顾着在新世界(Apple Silicon arm64)纵横驰骋,却忘记了旧时代(Intel x86_64)的亡灵依旧徘徊。
当你自信满满地注入 Hook,控制台却传来 image not found 的哀嚎时,那是因为你的霸气(架构)与船只不匹配!
若 Typora 运行在 Rosetta 模式下,它是 x86_64 的;而你的库如果是纯 arm64,就会被拒绝登船。
对策:使用 lipo -create 禁术,将两种霸气融合,锻造出能斩断一切时代的 Universal Binary(通用二进制)。
2. 霸气的反噬 (ARC 的诅咒)
当你用 performSelector 想要取巧时,Xcode 就像凯多老师一样,一棒子把你打醒:Warning: Leak...
这时候不能退缩!要学会流樱(objc_msgSend)的高级用法。不仅要会用,还要会转换类型,让霸气在体内正确流动,否则会把自己炸伤。
3. 生命卡的秘密 (指纹校验)
不要试图用假纸片糊弄大妈的生命卡。
fingerPrint 必须是真的!必须是真的!
如果你随便乱填一个字符串,魂魂果实的能力会直接抽走程序的寿命(Crash)。老老实实调用原来的 fingerPrintNew,借用它的力量。
如果你不是像弗兰奇那样精通改造技术的船匠(开发者),或者觉得在 Xcode 中锻造武器太过繁琐。
那么,这件沉睡在拉夫德鲁深处的 “古代兵器” (Pluton) —— MacTools 便是为你而生的神器。
它拥有 “操纵因果,一键注入” 的恐怖能力,能让没有任何霸气的普通人,也能在一瞬间征服 Typora。
兵器的使用说明书
-
启动祭坛 (Launch):
打开 MacTools,切换至 “注入” 模式。这是连接表世界与里世界的通道。
-
连接伟大航路 (Repository):
点击界面中央的 “仓库” 按钮。这里连接着 Mac-XK 军火商的云端宝库,存放着无数传说中的恶魔果实。
-
搜寻目标 (Search):
在搜索框中输入 Typora。见闻色霸气会自动锁定那颗名为 libTypora.dylib 的秘宝。
-
缔结契约 (Download):
点击 “下载”。
此时,古代兵器会启动 “自动同化” 程序。它会自动寻找虽然存在的 Typora 实体,并将 Hook 的灵魂强制注入其中。无需 Xcode,无需编译,无需手动签名。
-
影分身之术 (Duplicate):
如果你担心被世界政府(正版验证)发现,还可以使用右下角的 “制作分身”。
它会创造一个拥有独立沙盒的 Typora 影分身。本体用于应付检查,分身用于享受自由。
对于那些只想静静享受财宝,不想在海上打打杀杀的冒险家来说,这就是最优雅的终极答案。
感谢:Antibiotics大佬的tinyhook
终章:到达拉夫德鲁
经过一番激战,我们终于将 TyporaHook.framework 注入到了 Typora 的心脏。
启动吧,桑尼号!
没有弹窗,没有警报。
点开 License Info,那里刻着乔伊波伊留下的笑话:
Status: Activated
Email: macxk@foxmail.com
海贼王,我当定了!
To Be Continued...
冒险还在继续,代码之海永无止境。