MacOS 下 破解 Transmit.app

/
这是我第一次破解macos 应用,遇到了诸多问题

按照破解iOS 应用的套路,首先尝试cycript 注入 Transmit,进行动态调试

cy注入失败
报错了

签入权限 get-task-allow

1
2
<key>get-task-allow</key>
<true/>

重签后,仍旧无法注入,不知道为何,据说是mac SIP在影响。 但是我不想关闭SIP,只能另想办法。

开启Charles 代理抓包 ,发现数据明文传输,并未加密,真是太优秀了

1
2
3
4
5
6
7
8
URL:  https://circle.panic.com/api/v1/app_store/subscription_status/

返回数据:

"status": "ok", //试用状态
"signed_original_transaction_id": "TsK6nJskEYN97u8X+SrxLnsSy8AlU/wkUs6lQqL3++jh+DnygByojolNm5xBbGKFfeC4qYinWv8TtQQWa50aJoej4p1kpsUz6QN4NdInFOaPr3TlKP5wJi30vgJWU9H6WkVf71IjZ8dBRPQDAcxjH3D6VBVSEm7g4YiGLpbBpyI96lUk62BWvR7FlRPJ20wPDcm8gDLf3VenjQ7Vs9WH/lIWlYYIxdRrygga5sMcpcmYf0JILQGssIzJjgwbuPfjYCsb77xRqUyPtu7anINkWGb3QUwcc5SoSxa8YbAewKjhiAO0rUSvb/06XtXg6lsZ1zXPzp8j1wj2klTofw4AueUk2UA2IHbjMonzz/NeM3/TTLBPjk5KsD1XeJdoT4/4xBEpa3maqn+f8BHVKLbHQh/jHG+AYjqRS57uGSC57WeV6IG1EA9os4LRoUt9K4PUDh4DZPtuKxG/ T1JjWyfWSnwRjTn047k8ZHL4HSAlbD8SUllOZ7quk+CD3+lxsKEU", //AppStore 生成的ID
"expiry_date": "2030-02-25T13:07:29+00:00", //到期日期
"can_start_trial": true //能否试用

注意这里要开启试用,才能抓到这段数据,因为只有在开启订阅试用的时候,才会验证是否试用到期

这里我们看到了数据,只需要把传输数据修改一下即可。那么如何修改呢?

在 Charles 中手动修改传回的数据,后期修改 host 屏蔽 新数据。

https://circle.panic.com/api/v1/app_store/subscription_status/ 下,下断点,修改返回的试用结束时间

1
2
3
4
5
6
修改返回数据:

"status": "ok", //试用状态
"signed_original_transaction_id": "TsK6nJskEYN97u8X+SrxLnsSy8AlU/wkUs6lQqL3++jh+DnygByojolNm5xBbGKFfeC4qYinWv8TtQQWa50aJoej4p1kpsUz6QN4NdInFOaPr3TlKP5wJi30vgJWU9H6WkVf71IjZ8dBRPQDAcxjH3D6VBVSEm7g4YiGLpbBpyI96lUk62BWvR7FlRPJ20wPDcm8gDLf3VenjQ7Vs9WH/lIWlYYIxdRrygga5sMcpcmYf0JILQGssIzJjgwbuPfjYCsb77xRqUyPtu7anINkWGb3QUwcc5SoSxa8YbAewKjhiAO0rUSvb/06XtXg6lsZ1zXPzp8j1wj2klTofw4AueUk2UA2IHbjMonzz/NeM3/TTLBPjk5KsD1XeJdoT4/4xBEpa3maqn+f8BHVKLbHQh/jHG+AYjqRS57uGSC57WeV6IG1EA9os4LRoUt9K4PUDh4DZPtuKxG/ T1JjWyfWSnwRjTn047k8ZHL4HSAlbD8SUllOZ7quk+CD3+lxsKEU", //AppStore 生成的ID
"expiry_date": "2090-02-25T13:07:29+00:00", //到期日期
"can_start_trial": true //能否试用

退出App,修改 sudo vi /etc/hosts
添加

1
2
0.0.0.0 circle.panic.com #Transmit App authorization
0.0.0.0 panic.com #Transmit App authorization

这个方法是最为简单的,但是,由于本人经常要用的代理工具,在开启全局代理之后 数据就不走host,导致屏蔽失败。这个很蛋疼。

Hook App 解密过程 , 串改数据

把APP 可执行文件拖进 Hopper Disassembler 分析,搜索URL字符串,字符串没加密,找到字符串地址

字符串

找到引用位置

发起调用

解析返回数据

发现通过解析

1
rax = [NSJSONSerialization JSONObjectWithData:r12 options:0x0 error:0x0];

正常情况下,只需hook住该方法,修改一下值即可。

参照 如何注入mac os app

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@interface NSJSONSerialization (HOOK)
@end
@implementation NSJSONSerialization (HOOK)
+(id)HOOK_JSONObjectWithData:(id)data options:(int)option error:(NSError **)error
{
id ret = [self HOOK_JSONObjectWithData:fakeData options:option error:error];
if(ret[@"status"]&&ret[@"expiry_date"]&&ret[@"can_start_trial"])
{
NSString * signed_original_transaction_id = @"你的key";
NSMutableDictionary * mret = [[NSMutableDictionary alloc]init];
[mret setValue:@"ok" forKey:@"status"];
[mret setValue:signed_original_transaction_id forKey:@"signed_original_transaction_id"];
[mret setValue:@"2099-12-31T09:58:59+00:00" forKey:@"expiry_date"];
[mret setValue:@"true" forKey:@"can_start_trial"];
return mret;
}
}
@end

static void __attribute__((constructor)) initialize(void) {
NSLog(@"++++++++ loaded ++++++++");
[NSJSONSerialization jr_swizzleClassMethod:@selector(JSONObjectWithData:options:error:) withClassMethod:@selector(HOOK_JSONObjectWithData:options:error:) error:nil];
}

编写插件,生成的libTransmitHook.dylib插件
命令行执行

1
2
3
cp libTransmitHook.dylib /Applications/Transmit.app/Contents/Frameworks/
cd /Applications/Transmit.app/Contents/Frameworks/
export DYLD_INSERT_LIBRARIES=./libTransmitHook.dylib && /Applications/Transmit.app/Contents/MacOS/Transmit`

App启动,但是hook报错,或许是加了某种 hook检测。 此路不通。

直接静态修改 URL字符串,指向一个空域名

我们在手动串改过一次数据后,只要把后续数据请求给屏蔽,即可。在代理中篡改完之后,假的数据已被保存,阻断后续数据。

静态修改 https://circle.panic.com/api/v1/app_store/subscription_status/https://aaaaaa.panic.com/api/v1/app_store/subscription_status/

找到字符串

字符串

点 windown->show hexadecimal Editor.

编辑

双击 右侧 字符 直接修改

修改完毕后,点 File->Produce New Executable 保存.

如果app原本有签名信息,这里会提示删除签名信息。但是这个删除有bug,就是无法重签。

这里用macho_edit工具,先删除签名。

删除签名信息

再用Hopper Disassembler静态修改,再保存即可。

把 新生成的 可执行文件,替换到 /Applications/Transmit.app/Contents/MacOS/Transmit 保存。

点击启动会 提示内部错误。
应该由于没有重签,导致某些权限不可用。

发现貌似有签名校验,patch签名检测

1
BOOL VerifySignedString(__int64 a1, RSA **a2, __int64 a3)

VerifySignedString

找到函数中 rax 寄存器 最后赋值 位置,选中这一行
点 Modify->Assemble instruction
输出
movzx eax, 0x01
点击 next,即可

这里我们重新签下名

1
2
3
4
security find-identity -v -p codesigning //查看可用证书
ldid -e /Applications/Transmit.app/Contents/MacOS/Transmit > ~/Desktop/ent.plist //导出权限信息
cd ~/Desktop
codesign -fs "证书信息" --no-strict --entitlements=ent.plist /Applications/Transmit.app //重新签名

如果签名异常可以尝试

1
2
codesign --force --deep --sign - /Applications/Transmit.app
codesign -fds - /Applications/Transmit.app

重新启动,正常运行,抓包看,回传数据接口已被修改。查看订阅时间为我们串改的值。

启动后再关闭总是提示AppStore 评分弹框。分析patch掉

因为此弹窗为系统公开API,我们定位到

1
2
[SKStoreReviewController requestReview];
-[TRDocument requestReview]:

汇编代码

00000001000b3478 jne loc_1000b349b

je为相等转移,jne是不相等转

修改 jne 为 je

0x75 对应 汇编指令jne, 0x74 对应汇编指令 je

选中 jne 指令, 点 windown->show hexadecimal Editor 修改 75 为 74 生成新的可执行文件。

重新签名即可,成功屏蔽弹框。

到这里因该是破解完成。中间太曲折了。

由于 在 mac os 10.15 上 权限影响,导致无法运行

这里从新分析了这个软件,修改 “chid” 属性的返回值为9999即为授权成功。
不过签名很麻烦,在签上权限后会提示 文件损坏。可以用下面命令重签,不过没有权限。但是也能用、

1
codesign --force --deep --sign - /Applications/Transmit.app

(PS)当然有更好的方式,但是暂时因为无法实现动态调试,就不再折腾了。