iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手
本帖最后由 小花匠 于 2017-11-16 12:49 编辑# iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手
###前言
>发现iOS支付宝逆向的分析并不多,蚂蚁森林基于H5应用 套着UIWebView 基本也没这类JS和原生交互分析的帖子,就拿此练手吧 作技术分享
- **去掉 ptrace 和 __RESTRICT section 两个保护**
- **脱壳和dump头文件**
- **分析和调试**
- **编写Tweak**
- **总结**
-------------------
## 环境
- MacBook,iPhone6,iOS 9.3.3越狱, iOS支付宝10.1.5
## 工具
- theos
> Tweak制作工具
- xcode
> 用lldb来附加调试
- class-dump
> 导出头文件
- dumpdecrypted
> 脱appstore的壳
- iHex
>二进制编辑器
### 去掉 __RESTRICT section和 ptrace 两个保护
- 去掉 __RESTRICT section 步骤
- ssh到手机 执行命令 `ps -e`
- 找到 `/var/containers/Bundle/Application/DD6D8BA3-95F2-4C6D-BFD7-0E20420A6E9C/AlipayWallet.app/AlipayWallet`
- 切换到mac电脑 使用scp命令 把执行文件拷到电脑上`scp root@192.168.2.2:/var/containers/Bundle/Application/C6F2DD99-6450-4838-98B8-2899E8EBC1A4/AlipayWallet.app/AlipayWallet /Users/hack/Desktop/wz `
- 打开iHex 查找command+f 把 __RESTRICT和__restrict替换为其他值(比如:__RRRRRRRR和__rrrrrrrr。保证长度不变就行啦)看图1
![这里写图片描述](http://img.blog.csdn.net/20171115160730615?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2lzc2luZ19odW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
- 拷贝文件回去`scp /Users/hack/Desktop/wz/AlipayWallet root@192.168.2.2:/var/containers/Bundle/Application/C6F2DD99-6450-4838-98B8-2899E8EBC1A4/AlipayWallet.app/AlipayWallet`
- 如果打开闪退 请Cydia中安装 AppSync
- 去除ptrace保护
- 使用theos 创建Tweak 代码如下 安装到手机就可以
```
#import <substrate.h>
#import <sys/sysctl.h>
static int (*orig_ptrace) (int request, pid_t pid, caddr_t addr, int data);
static int my_ptrace (int request, pid_t pid, caddr_t addr, int data){
if(request == 31){
NSLog(@" - ptrace request is PT_DENY_ATTACH");
return 0;
}
return orig_ptrace(request,pid,addr,data);
}
%ctor{
MSHookFunction((void *)MSFindSymbol(NULL,"_ptrace"),(void*)my_ptrace,(void**)&orig_ptrace);
NSLog(@" Module loaded!!!");
}
```
###脱壳和dump头文件
- 执行命令 `cycript -p AlipayWallet` 注入支付宝进程
- 执行命令 `[URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]`
- 看到返回 `/var/mobile/Containers/Data/Application/5E744C4A-5B05-4280-A21C-9E6EFE8EF51D/Documents/`
- 执行命令 `cd /var/mobile/Containers/Data/Application/5E744C4A-5B05-4280-A21C-9E6EFE8EF51D/Documents/`
- 把 dumpdecrypted.dylib拷贝进去`scp /Users/cardlan/Downloads/dumpdecrypted-master/dumpdecrypted.dylib root@192.168.2.2:/var/mobile/Containers/Data/Application/5E744C4A-5B05-4280-A21C-9E6EFE8EF51D/Documents/`
- 执行命令 `DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/containers/Bundle/Application/DD6D8BA3-95F2-4C6D-BFD7-0E20420A6E9C/AlipayWallet.app/AlipayWallet`
- 如果发现提示Killed: 9 切换`su mobile` 再试 提示成功如下
```
DISCLAIMER: This tool is only meant for security research purposes, not for application crackers.
[+] detected 64bit ARM binary in memory.
[+] offset to cryptid found: @0x100034d90(from 0x100034000) = d90
[+] Found encrypted data at address 00004000 of length 56786944 bytes - type 1.
[+] Opening /private/var/containers/Bundle/Application/C6F2DD99-6450-4838-98B8-2899E8EBC1A4/AlipayWallet.app/AlipayWallet for reading.
[+] Reading header
[+] Detecting header type
[+] Executable is a plain MACH-O image
[+] Opening AlipayWallet.decrypted for writing.
[+] Copying the not encrypted start of the file
[+] Dumping the decrypted data into the file
[+] Copying the not encrypted remainder of the file
[+] Setting the LC_ENCRYPTION_INFO->cryptid to 0 at offset d90
[+] Closing original file
[+] Closing dump file
```
- 执行`ls` 找到AlipayWallet.decrypted scp拷贝到电脑就可以
- 接下来使用 class-dump 导出头文件到当前文件夹
`class-dump -H AlipayWallet.decrypted -o ./ `
###分析和调试
- 打开支付宝到蚂蚁森林界面 cycript -pAlipayWallet
- 我们从UI入手 执行`[recursiveDescription]` 看到`<H5WebView: 0x1386dc970; baseClass = UIWebView` 看来是H5的应用
我们返回上面找控制器`[#0x1386dc970 nextResponder]`看到`<DTBaseView: 0x1378d6210` 继续`[#0x1378d6210 nextResponder]` 看到了`<H5WebViewController: 0x136a28400>`
- 我们去之前导出的头文件翻翻 找到这个控制器 看看有什么敏感的方法和属性,我们的目要找到关键的点击事件或者相关的逻辑
我们使用`choose(H5WebViewController)` 拿到实例 测试一下头文件的方法看看
看了一大圈真没什么什么进展,url 无法直接打开的 再想想UIWebView和原生交互的方法,如下代码获取个Html源码来看看
类似于WebViewJavascriptBridge 咱们找下callback方法或者send方法试试
```
[#0x136a28400 lastMainRequest]
"<NSMutableURLRequest: 0x1386826e0> { URL: https://60000002.h5app.alipay.com/app/src/home.html?__webview_options__=transparentTitle%3Dauto%26canPullDown%3DNO }"
[#0x136a28400 h5WebView]
#"<H5WebView: 0x1386dc970; baseClass = UIWebView; frame = (0 0; 375 667); autoresize = H; layer = <CALayer: 0x1386171d0>>"
[#0x136a28400 stringByEvaluatingJavaScriptFromString:"document.documentElement.innerHTML"]
```
- 我们来使用THEOS 自带的logify.pl生成H5WebViewController的全部方法调用和参数日志
```
/opt/theos/bin/logify.pl H5WebViewController.h >Tweak.xm
```
编译 Tweak.xm 注意:有编译出错 有些类和代{过}{滤}理block是不认识的 出错的删掉就可以
CDUnknownBlockType 作参数的可以替换成 id 继承于 DTViewController 替换成
安装之后 手机连上我们电脑 打开xcode -菜单Window-Devices-Simulators
我们点击那个能量按钮收取别人的能量看看
![这里写图片描述](http://img.blog.csdn.net/20171116110251911?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2lzc2luZ19odW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
- 接下来我们使用xcode 自带的lldb来调试支付宝(默认xcode无法调试第三方应用)我们接下来给app加个权限
没权限提示
```
Ensure “AlipayWallet” is not already running, and cardlan_yuhuajun has permission to debug it.
```
注意:要使用脱壳之后的AlipayWallet执行下面的命令,也就是AlipayWallet.decrypted 重命名为AlipayWallet(否则闪退)
```
将应用程序从设备上拷贝到本地
利用 ldid 将应用程序的 code sign 导出:ldid -e AlipayWallet >> AlipayWallet.xml
在 AlipayWallet.xml 文件中添加 get-task-allow 权限
<key>get-task-allow</key> <true/>
利用 ldid 对应用进行重签名 ldid -SAlipayWallet.xml ./AlipayWallet
将应用拷回设备,将设置可执行权限 chmod 755 AlipayWallet
完成
```
(图3)
![这里写图片描述](http://img.blog.csdn.net/20171116110321665?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2lzc2luZ19odW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
ps:如果如上操作还闪退 请重启iphone
- 然后我们连上手机 xcode 随便弄个工程 选择iphone 看图来开始附加AlipayWallet(图4) 点到森林界面点击xcode自带的看界面工具 然后再xcode 右下角自带的lldb 下断点
我们先试着下断函数
![这里写图片描述](http://img.blog.csdn.net/20171116110345502?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2lzc2luZ19odW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
```
b -
```
提示找不到no locations 我们随便找个地址 看看堆栈信息
```
po
```
找一个地址
```
b 0x1057daab0
```
重开页面 触发断点 ,点开xcode的堆栈窗口如(图5)
![这里写图片描述](http://img.blog.csdn.net/20171116110359232?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2lzc2luZ19odW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
发现很多地址是没函数名的 当然也无法直接对函数名下断点 我们借用大神写的工具来恢复这些信息 文章链接如下
(http://www.jianshu.com/p/967b6631756c)
之后 再附加一下
下这个断点
```
b -
```
发现是可以成功下断了 继续查看堆栈信息 现在函数名全部全了
(图6)
![这里写图片描述](http://img.blog.csdn.net/20171116110416288?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2lzc2luZ19odW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
往上回溯 思路 因为我们想找到是js过来的参数和调用原生方法是哪里过来的
毕竟 reportClickTime 不是我们要分析的
看到PSDJsBride 调用了很多次 而且看参数和函数名 很有可能 中转了消息和参数 为了验证我们的猜想 ,我们使用logify.pl 来生成tweak 打印他全部的调用日志
安装到手机之后,我们取消断电打开xcode的日志看打印 有没有敏感的信息调用
```
br delete
```
点击好友的那个能量收取 把日志全部copy 到Sublime text
看图(7)
![这里写图片描述](http://img.blog.csdn.net/20171116110430864?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2lzc2luZ19odW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
我们看到这个英文单词 收集的意思 我们猜想这个就是收集能量的命令,看参数体有friedID 确定性90%了
- 证实猜想 我们用cycript 来试试 拿到PSDJsBridge 的实例 可以用choose也可以用日志打印那个
```
[#0x14a0bed80 _doFlushMessageQueue:@"把参数拷贝过来(自己处理转义 里面有/"号)" url:@"第二个参数"];
提供下我日志的
_doFlushMessageQueue:[{"handlerName":"remoteLog","data":{"seedId":"ANTFOREST-BEHAVIOR-CLICK-COLLECT","param1":"shareBiz=none^bubbleId=26219984^actionUserId=2088322012980000^type=behavior^currentTimestamp=1510797618289","param2":"monitor_type=clicked^remoteType=info^pageName=home.html^pageState=friend2088322012980000_enterhomeOff","bizType":"antForest"},"callbackId":"remoteLog_15107976182890.5985529306344688"},{"handlerName":"rpc","data":{"operationType":"alipay.antmember.forest.h5.collectEnergy","requestData":[{"userId":2088322012987680,"bubbleIds":,"av":"5","ct":"ios"}],"disableLimitView":true},"callbackId":"rpc_15107976182910.0005478465463966131"}] url:https://60000002.h5app.alipay.com/app/src/home.html?userId=2088322012980000]
```
我们执行 看看日志打印 有日志输出 看recv这些参数 和刚刚是有点差别 但是大致一样(这个能量只能收一次)来看bubbleId 这个猜一下是能量的ID
- 来找怎么获取的能量ID 我们打开一个有能量的好友,看日志有获取的调用没
由于日志比较多 我们就是着重找有返回bubbleId和friedID 的列表,找到之后往上找调用着参数
```
[m -[<PSDJsBridge: 0x14a1cbce0> transformResponseData:{
bizNo = "092c5f8c-ee77-49ad-a3a2-dd3c059ee579-1510798661871";
bubbles = (
{
business = {
bigIconDisplayName = "\U884c\U8d70";
bizType = xingzou;
dayIconUrl = "https://zos.alipayobjects.com/rmsportal/xxx.png";
id = 9;
nightIconUrl = "https://zos.alipayobjects.com/rmsportal/xxx.png";
smallIconDisplayName = "\U884c\U8d70";
};
collectStatus = AVAILABLE;
fullEnergy = 92;
id = 26343893;
produceTime = 1510788093000;
remainEnergy = 72;
userId = 208890214255xxxx;
}
);
needGuide = 0;
```
结果有了 找调用
```
_doFlushMessageQueue:[{"handlerName":"remoteLog","data":{"seedId":"ANTFOREST-PAGE-READY-home","param1":"shareBiz=none^type=behavior^currentTimestamp=1510798661779","param2":"monitor_type=openPage^remoteType=info","bizType":"antForest"},"callbackId":"remoteLog_15107986617880.34833956067450345"},{"handlerName":"getSystemInfo","data":{},"callbackId":"getSystemInfo_15107986617920.08668778464198112"},{"handlerName":"hideOptionMenu","data":{},"callbackId":"hideOptionMenu_15107986617920.562577509554103"},{"handlerName":"setToolbarMenu","data":{"menus":[],"override":true},"callbackId":"setToolbarMenu_15107986617920.03417412145063281"},{"handlerName":"setGestureBack","data":{"val":true},"callbackId":"setGestureBack_15107986617920.6238974309526384"},{"handlerName":"remoteLog","data":{"seedId":"ANTFOREST-H5_PAGE_SET_PAGE_NAME","param1":"shareBiz=none^type=behavior^currentTimestamp=1510798661796","param2":"monitor_type=clicked^remoteType=info^pageName=home.html","bizType":"antForest"},"callbackId":"remoteLog_15107986617960.3546153837814927"},{"handlerName":"addNotifyListener","data":{"name":"NEBULANOTIFY_AFRefresh"},"callbackId":"addNotifyListener_15107986617960.04098325059749186"},{"handlerName":"rpc","data":{"operationType":"alipay.antmember.forest.h5.queryNextAction","requestData":[{"userId":"208890214255xxxx","av":"5","ct":"ios"}],"disableLimitView":true},"callbackId":"rpc_15107986617970.8864813686814159"}] url:https://60000002.h5app.alipay.com/app/src/home.html?userId=208890214255xxxx]
```
用cycript 测试这个方法 。结果如我们所愿 日志返回了我们需要的能量ID和好友ID 可以构造第一个找到那个方法 实现收一个好友的能量
- 由于这个方法需要好友ID的参数 我们需要拿到全部好友的ID 这样才能实现我们的一键全部收取
- 这里我偷个懒 不去往下折腾 点击页面在PSDJsBridge transformResponseData
取top 10的好友ID(打开页面他本身执行了 friendRanking系列方法 )
### 编写Tweak
- 整理下流程,进页面 他自身调用Top10的好友列表 我们拿到这10个用户的UID
- 拿到UID之后执行上面分析的第二个方法 拿到指定用户可以收的能量 collectStatus=AVAILABLE 返回参数中有 我们看字段就能猜到
- 拿到UID和能量ID 我们就可以执行收能量的功能了
- 具体的代码不一一分析 下面会提供代码下载地址
看成功图8
![这里写图片描述](http://img.blog.csdn.net/20171116110453671?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2lzc2luZ19odW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
### 总结
- UIWebView的应用不同于原生的应用 有正向开发经验能通过UI层能轻易找到触发事件
- 其实很多时候都在试错和猜想 ,逐步的去验证自己的猜想 直到找到答案
- 这个Tweak只作技术分析,并没有完善 Top10用户收取还不够用 大家可以试着动手 获取下一页好友 和全部好友 看日志找到字段是可以轻易实现的 还有其他功能比如 每天定时启动收取啥的
这是代码GitHub地址
https://github.com/hackxhj/alipayForestTweak.git
欢迎star
Hmily 发表于 2017-11-16 11:46
@小花匠 把图片上传论坛本地吧,防止未来可能丢失或者防盗链无法显示,帖子加精鼓励!
论坛图片上传上来变成300*300的小图片了 源文件图片是我csdn博客的地址 小花匠 发表于 2017-11-16 23:19
拷贝出来 otool -l AlipayWallet | grep crypt
看看cryptid 标志位是0 还是1 是1的话要脱壳 把脱壳文件 ...
已经脱壳了 按你说的
将应用程序从设备上拷贝到本地
利用 ldid 将应用程序的 code sign 导出:ldid -e AlipayWallet >> AlipayWallet.xml
在 AlipayWallet.xml 文件中添加 get-task-allow 权限
<key>get-task-allow</key> <true/>
利用 ldid 对应用进行重签名 ldid -SAlipayWallet.xml ./AlipayWallet
将应用拷回设备,将设置可执行权限 chmod 755 AlipayWallet
完成
之后就闪退了,重启也没用 如果越狱了,直接用插件修改步数,领的比我每天去偷别人的多很多{:1_918:} 厉害我的哥 那么安卓有没有类似的软件 年华锦时 发表于 2017-11-16 11:21
如果越狱了,直接用插件修改步数,领的比我每天去偷别人的多很多
我记得新版本支付宝 自定义改了步数 。不生成能量了吧 {:1_903:} 怎么用大神 还有这操作。。 @小花匠 把图片上传论坛本地吧,防止未来可能丢失或者防盗链无法显示,帖子加精鼓励! Hmily 发表于 2017-11-16 11:46
@小花匠 把图片上传论坛本地吧,防止未来可能丢失或者防盗链无法显示,帖子加精鼓励!
好的 感谢老大。 精华帖!必须赞一个了