如何调试支付宝(iOS)

作者 | 帕巴拉
来源 | 掘金

前言

最近在做的一件事情,从代码层面分析下各家小程序(微信、头条、支付宝、百度)的启动性能,探究各家小程序的实现细节和差异。具体步骤如下:

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。

反反调试详细步骤

iOS12

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] 为空实现

iOS13

MONKEYDEV_DEFAUTL_BUNDLEID=YES

• 在iOS13手机上报如下错 An unknown error has occurred. Domain: com.apple.dt.MobileDeviceErrorDomain Code: -402620415

此路不通 ?

MONKEYDEV_DEFAUTL_BUNDLEID=NO

1、 可以安装到手机,但是启动闪退

控制台log如下

  • 触发my_sysctl的调用栈如下

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

支付宝应用的架构到底有多牛?

自 2008 年双 11 以来,在每年双 11 超大规模流量的冲击上,蚂蚁金服都会不断突破现有技术的极限。 2010 年双 11 的支付峰值为 2 万笔/分钟,到 2017 年双 11 时这个数字变为了 25.6 万笔/秒。 2018 年双 11 的支付峰值为 48 万笔/秒,2019 年双 11 支付峰值为 54.4 万笔/秒,创下新纪录,是 2009 年第一次双 11 的 1360 倍。

发布于:14天以前  |  55次阅读  |  详细内容 »

iOS 隐形水印之 LSB 实现

在音视频的领域里,其涵盖的知识点繁多,学习方向也很多。而本篇就是一篇比较入门的文章它简单地介绍如何在 iOS 上读取图片 RGB 数据,并通过修改最后一位 bit 来记录数字水印的信息下面就介绍《隐形水印之 iOS 实现》

发布于:18天以前  |  61次阅读  |  详细内容 »

网易支付-高性能NEJFlutter小程序动态化架构实践

大家好,今天跟大家分享的主题是《NEJFlutter小程序动态化高性能架构》,这是关于网易支付团队在Flutter小程序动态化方向上尝试的一套技术解决方案,一句话介绍NEJFlutter,就是用JavaScript开发业务逻辑、Flutter开发UI布局的小程序架构,性能堪比原生Flutter应用;

发布于:18天以前  |  85次阅读  |  详细内容 »

声明式 UIKit 在有赞美业的实践

随着 Flutter 的出现,UI 开发形式也越来越趋向相同,Flutter,SwiftUI,RN,Weex 等新兴UI框架无一意外都使用了声明式的 UI 开发模式,和支持了FlexBox的布局系统。

发布于:18天以前  |  62次阅读  |  详细内容 »

如何调试支付宝(iOS)

最近在做的一件事情,从代码层面分析下各家小程序(微信、头条、支付宝、百度)的启动性能,探究各家小程序的实现细节和差异。

发布于:20天以前  |  108次阅读  |  详细内容 »

最多阅读

快速配置 Sign In with Apple 11月以前  |  2361次阅读
给数组NSMutableArray排序 1年以前  |  2089次阅读
开篇 关于iOS越狱开发 1年以前  |  1929次阅读
UITableViewCell高亮效果实现 1年以前  |  1926次阅读
在越狱的iPhone设置上使用lldb调试 1年以前  |  1914次阅读
APP适配iOS11 1年以前  |  1829次阅读
关于Xcode不能打印崩溃日志 1年以前  |  1631次阅读
App Store 审核指南[2017年最新版本] 1年以前  |  1618次阅读
所有iPhone设备尺寸汇总 1年以前  |  1596次阅读
使用ssh访问越狱iPhone的两种方式 1年以前  |  1549次阅读
使用 GPUImage 实现一个简单相机 1年以前  |  1502次阅读
使用ssh 访问越狱iPhone的两种方式 1年以前  |  1491次阅读
UIDevice的简单使用 1年以前  |  1439次阅读
为对象添加一个释放时触发的block 1年以前  |  1361次阅读
使用最高权限操作iPhone手机 1年以前  |  1291次阅读