作者 | 帕巴拉 来源 | 掘金
最近在做的一件事情,从代码层面分析下各家小程序(微信、头条、支付宝、百度)的启动性能,探究各家小程序的实现细节和差异。具体步骤如下:
1、越狱砸壳获取ipa
2、搭建调试壳工程
3、注入callTrace分析代码
4、hook小程序开始调用入口以及渲染完成入口, 加上callTrace逻辑,统计主线程和js线程方法调用栈以及方法耗时
5、增加callTrace 可视化界面入口
当前的进展如下
1、微信、百度已完成,微信的分析工程已上传到github:CallTraceForWeChat。
2、由于本人在百度做小程序相关的工作,故百度的分析工程无法提供,但是原理都是一样的。
3、支付宝当前,已完成1 2 3 5步骤,第4步只做了主线程。代码已上传到github:AliPayForDebug
4、头条未开始。
5、关于callTrace,可以查看CallTraceForWeChatreadme的介绍。
支付宝为什么只做了一半,原因呢是因为支付宝做了很多复杂的反调试防护,给我的分析工作增加了不少障碍。目前为止也没有很好的完成支付宝的反反调试工作。因此这里写一篇文章记录下反反调试支付宝的过程踩过的坑,分享给大家,希望能帮到遇到同样问题的小伙伴。
• 反调试与绕过的奇淫技巧1
• 反调试:请移步 iOS 反调试2
• 反反调试:请移步AloneMonkey-关于反调试&反反调试那些事3
• lldb调试原理以及ptrace反调试和汇编调用系统方法:iOS安全防护系列之ptrace反调试与汇编调用系统方法详解4
1、下载安装checkra1n
2、checkra1n无法打开,提示“您应该将它移到废纸篓”, 终端执行以下命令
codesign -f -s - --deep /Applications/checkra1n.app
sudo xattr -r -d com.apple.quarantine
sudo xattr -r -d com.apple.quarantine /Applications/checkra1n.app
也可参考Mac 版爱思助手无法打开,提示“您应该将它移到废纸篓”如何解决?5
3、按提示操作越狱
1、我使用的是frida-ios-dump,详细使用步骤可以看作者的githubfrida-ios-dump, 遇到的问题如下
• 更新fria一直卡住
○ 终端先设置代理再执行命令
export https_proxy=你的代理如http://xxx.xxx.com:9999
export http_proxy=你的代理
sudo pip install -r requirements.txt --upgrade
2、ssh连接手机失败
• 确保在一个局域网
• 重新安装openssl openssh,还不行再重新操作一次越狱
• 我使用的是MonkeyDev,安装使用请移步原作者的github
• 重要提醒1:在iOS13手机上报如下错时, 除了按照作者文档提到的步骤,还需要删除 AlipayWallet.app 包里的 com.apple.WatchPlaceholder 文件夹,再删除 DerivedData 重新run。
MONKEYDEV_DEFAUTL_BUNDLEID=YES
1、开始run时,app直接闪退,控制台log如下
2020-03-28 19:06:15.395011+0800 AlipayWallet[12252:1974005] [AntiAntiDebug] - dlsym get ptrace symbol
2020-03-28 19:06:15.395125+0800 AlipayWallet[12252:1974005] [AntiAntiDebug] - ptrace request is PT_DENY_ATTACH
2020-03-28 19:06:15.701070+0800 AlipayWallet[12252:1974265] [NetworkInfo] Signal strength query returned
2、MonkeyDev已经集成了 AntiAntiDebug ,为什么没生效,因为默认没替换sysctl, 这里打开注释
3、打开注释后,还是被杀,log如下
<CTServiceDescriptor 0x10ca47a20, domain=1, instance=2>
2020-03-29 00:44:38.089052+0800 AlipayWallet[13454:2074728] [NetworkInfo] Signal strength query returned error: Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied", descriptor: <CTServiceDescriptor 0x10c9dad30, domain=1, instance=1>
2020-03-29 00:44:38.089937+0800 AlipayWallet[13454:2074728] [NetworkInfo] Signal strength query returned error: Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied", descriptor: <CTServiceDescriptor 0x10c9d9860, domain=1, instance=2>
2020-03-29 00:44:52.923884+0800 AlipayWallet[13454:2074898] [NetworkInfo] Signal strength query returned error: Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied", descriptor: <CTServiceDescriptor 0x10ce07310, domain=1, instance=1>
2020-03-29 00:44:52.925006+0800 AlipayWallet[13454:2074898] [NetworkInfo] Signal strength query returned error: Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied", descriptor: <CTServiceDescriptor 0x10ce07380, domain=1, instance=2>
Message from debugger: Terminated due to signal 5
4、添加符号断点exit,module:libsystem_c.dylib, 看看哪里退出的
○ 没有断住
5、断点my_sysctl方法,可以看到+[AAAPBootStartPoint load]会去调用sysctl
6、+[AAAPBootStartPoint load]做了什么?可以看到用c函数enable_crash_reporter_service去启动crash上报服务,这个服务里有反调试的逻辑?
○ [AAAPBootStartPoint load]
void __cdecl +[AAAPBootStartPoint load](AAAPBootStartPoint_meta *self, SEL a2)
{
__int64 v2; // x0
__int64 v3; // x0
v2 = MPStartupTimeMarkAppStartPoint((__int64)self);
CACurrentMediaTime(v2);
v3 = enable_crash_reporter_service();
CACurrentMediaTime(v3);
MPStartupTimeSetRangeCost("crashinit");
}
7、看了伪代码并没有反调试逻辑,先替换 +[AAAPBootStartPoint load]load 方法为空实现, 顺利进入首页。why?
8、尝试AntiDebugBypass, 也没有生效。
9、接着就是加入我的业务逻辑,主线程已实现,效果如下
小结
针对iOS12设备,完成以下3步就可以正常调试了
1、配置MONKEYDEV_DEFAUTL_BUNDLEID=YES 2、打开 rebind_symbols((struct rebinding[1]){{"sysctl", my_sysctl, (void*)&orig_sysctl}},1); 注释 3、替换 [AAAPBootStartPoint load] 为空实现
MONKEYDEV_DEFAUTL_BUNDLEID=YES
• 在iOS13手机上报如下错 An unknown error has occurred. Domain: com.apple.dt.MobileDeviceErrorDomain Code: -402620415
此路不通 ?
MONKEYDEV_DEFAUTL_BUNDLEID=NO
1、 可以安装到手机,但是启动闪退
控制台log如下
iOS13 替换load不生效
2、是plcrashreporter引起的吗?先替换下enableCrashReporterAndReturnError为空实现
3、替换后 [APDataCenterInterface setDefaultCryptKey:] 会调用exit()直接退出
从伪代码里可以看到取getExtraData, 取到的字符串长度不是32就直接退出了,用lldb调试下,也确实如此。原因是我修改了bundleid, datacenter-default这个值的计算应该是和bundleid绑定的。
(lldb) po [SecurityGuardManager getInstance]
<SecurityGuardManager: 0x10d365fb0>
(lldb) po [[SecurityGuardManager getInstance] getStaticDataStoreComp]
<SecurityGuardStaticDataStore: 0x11440a9d0>
(lldb) po [[[SecurityGuardManager getInstance] getStaticDataStoreComp] getExtraData:@"datacenter-default"]
nil
(lldb)
4、替换getExtraData: 的实现,返回一个长度为32的字符串, 可以正常进入支付宝了,但是无法登陆,还是无法调试,心好累,难道要放弃iOS13吗?
5、我的目的是要调试小程序相关的功能,不登陆也没有关系,所以只要hook调强制登陆的逻辑就可以进入首页了。
• 通过view debuger 找到登陆页面的vc
Printing description of $16:
<ALULoginNewcomerViewController: 0x10e0f0a00>
• 通过memory graph 找到vc创建的调用栈,可以看到登录的逻辑是在下面触发的
-[DFMicroApplicationManager doStartApplication:params:launchMode:]
-[DFMicroApplicationManager doStartApplication:params:launchMode:] 伪代码,1700多行,可以想象业务是多么的复杂。
• 在伪代码里搜索 login 关键字,就能看到调登陆的入口 -[DFMicroApplicationManager loginOperation] ,替换这个方法返回nil,还是强制登陆了,没有效果。
• 还有一个关键字 shouldHoldLoginApp ,替换返回YES,直接黑屏了
• 替换login---此路不通
• 再回到登陆页,打印当前的vc,可以看到有2个ViewController,其中登陆aluNavigationController是被present出来的,因此只要调用下dismissViewControllerAnimated就可以退出登陆VC
(lldb) pvc
<DFNavigationController 0x10e841c00>, state: disappeared, view: <UILayoutContainerView 0x119f7ea40> not in the window
| <ALPLauncherController 0x10e8d0400>, state: disappeared, view: <UILayoutContainerView 0x10d6566c0> not in the window
| | <HPHomeWidgetGroup 0x11101e800>, state: disappeared, view: <DTBaseView 0x1142f85b0> not in the window
| | | <HomeCardMainController 0x10e9f5800>, state: disappeared, view: <DTBaseView 0x1219b9b80> not in the window
| | <FHRootViewController 0x10e8a6e00>, state: disappeared, view: (view not loaded)
| | <O2OIndexViewController 0x10e8efa00>, state: disappeared, view: (view not loaded)
| | <APContactRecentViewController 0x10e9b5200>, state: disappeared, view: <DTBaseView 0x121385680> not in the window
| | <WWAssetsViewController 0x10e107c00>, state: disappeared, view: (view not loaded)
+ <aluNavigationController 0x10e949e00>, state: appeared, view: <UILayoutContainerView 0x119fc21e0>, presented with: <_UIFullscreenPresentationController 0x114219210>
| | <ALULoginNewcomerViewController 0x10e05e800>, state: appeared, view: <UIView 0x110e28f00>
(lldb)
• 我在登陆按钮点击的时候dissMiss登录VC, 顺利进入支付宝首页
• 虽然进了首页,但是小程序还是打不开,网络请求发送失败
因为修改了bundleid, 尝试去恢复bundleid,首先重写NSBundle bundleIdentifier,返回固定值com.alipay.iphoneclient,然后重写infoDictionary, 写死CFBundleIdentifier的值,抓包看,所有发出的请求都请求成功了,但是小程序还是无法打开。
小结
虽然顺利进入了支付宝首页,但是小程序功能还是不可用,我决定暂时放弃iOS13了 , 支付宝针对bundleid做了特殊的防护逻辑,后续再慢慢研究。
我日常工作也调试过很多家的app, 基本上自动化反反调试工具都能攻破,相比支付宝,他们的防护手段还是常规操作。
对比微信和支付宝的防护可以看到支付宝的防护手段是从入口切断调试;微信没有做这种调试入口的防护,但是发现你在调试时会封你登陆的微信账户。
2种防护都会消耗掉反调试者的大量时间和精力,没有耐心的基本就放弃了。
逆向之路,路漫漫其修远兮,继续加油吧。
[1]http://iosre.com/t/topic/9351 [2]https://www.jianshu.com/p/f1f254166cd5 [3]http://bbs.iosre.com/t/topic/8179 [4]https://www.jianshu.com/p/ebdfb0a25c85 [5]https://www.i4.cn/news_detail_39414.html
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8