iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手

原文: 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 [email protected]:/var/containers/Bundle/Application/C6F2DD99-6450-4838-98B8-2899E8EBC1A4/AlipayWallet.app/AlipayWallet /Users/hack/Desktop/wz

打开iHex 查找command+f 把 __RESTRICT和__restrict替换为其他值(比如:__RRRRRRRR和__rrrrrrrr。保证长度不变就行啦)看图1

iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手_第1张图片

拷贝文件回去scp /Users/hack/Desktop/wz/AlipayWallet [email protected]:/var/containers/Bundle/Application/C6F2DD99-6450-4838-98B8-2899E8EBC1A4/AlipayWallet.app/AlipayWallet

如果打开闪退 请Cydia中安装 AppSync

去除ptrace保护

使用theos 创建Tweak 代码如下 安装到手机就可以

#import#importstaticint(*orig_ptrace) (intrequest, pid_t pid, caddr_t addr,intdata);staticintmy_ptrace (intrequest, pid_t pid, caddr_t addr,intdata){if(request ==31){NSLog(@"[AntiAntiDebug] - ptrace request is PT_DENY_ATTACH");return0;    }returnorig_ptrace(request,pid,addr,data);}%ctor{  MSHookFunction((void*)MSFindSymbol(NULL,"_ptrace"),(void*)my_ptrace,(void**)&orig_ptrace);NSLog(@"[AntiAntiDebug] Module loaded!!!");}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

脱壳和dump头文件

执行命令cycript -p AlipayWallet注入支付宝进程

执行命令[[NSFileManager defaultManager]URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]

看到返回/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 [email protected]:/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 toolisonly meantforsecurity research purposes,notforapplicationcrackers.[+] detected64bit ARM binaryinmemory.[+]offsettocryptid found: @0x100034d90(from0x100034000) = d90[+] Found encrypted dataataddress00004000oflength56786944bytes - type1.[+] Opening /private/var/containers/Bundle/Application/C6F2DD99-6450-4838-98B8-2899E8EBC1A4/AlipayWallet.app/AlipayWalletforreading.[+] Reading header[+] Detecting header type[+] Executableisa plain MACH-O image[+] Opening AlipayWallet.decryptedforwriting.[+] Copyingthenotencrypted startofthefile[+] Dumpingthedecrypted dataintothefile[+] Copyingthenotencrypted remainderofthefile[+] SettingtheLC_ENCRYPTION_INFO->cryptidto0atoffsetd90[+] Closing originalfile[+] Closing dumpfile

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

执行ls找到 AlipayWallet.decrypted scp拷贝到电脑就可以

接下来使用 class-dump 导出头文件到当前文件夹

class-dump -H AlipayWallet.decrypted -o ./

分析和调试

打开支付宝到蚂蚁森林界面 cycript -p AlipayWallet

我们从UI入手 执行[[UIApp keyWindow]recursiveDescription]看到

我们返回上面找控制器[#0x1386dc970 nextResponder]看到

我们去之前导出的头文件翻翻 找到这个控制器 看看有什么敏感的方法和属性,我们的目要找到关键的点击事件或者相关的逻辑

我们使用choose(H5WebViewController)拿到实例 测试一下头文件的方法看看

看了一大圈真没什么什么进展,url 无法直接打开的 再想想UIWebView和原生交互的方法,如下代码获取个Html源码来看看

类似于WebViewJavascriptBridge 咱们找下callback方法或者send方法试试

[#0x136a28400 lastMainRequest]" { URL: https://60000002.h5app.alipay.com/app/src/home.html?__webview_options__=transparentTitle%3Dauto%26canPullDown%3DNO}"[#0x136a28400 h5WebView]#">"[#0x136a28400 stringByEvaluatingJavaScriptFromString:"document.documentElement.innerHTML"]

1

2

3

4

5

6

7

8

我们来使用THEOS 自带的logify.pl 生成H5WebViewController的全部方法调用和参数日志

/opt/theos/bin/logify.plH5WebViewController.h>Tweak.xm

1

编译 Tweak.xm 注意:有编译出错 有些类和代理block是不认识的 出错的删掉就可以

CDUnknownBlockType 作参数的可以替换成 id 继承于 DTViewController 替换成

安装之后 手机连上我们电脑 打开xcode -菜单Window-Devices-Simulators

我们点击那个能量按钮收取别人的能量看看

iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手_第2张图片

接下来我们使用xcode 自带的lldb来调试支付宝(默认xcode无法调试第三方应用)我们接下来给app加个权限

没权限提示

Ensure“AlipayWallet”isnotalready running,andcardlan_yuhuajunhaspermissiontodebug it.

1

注意:要使用脱壳之后的AlipayWallet执行下面的命令,也就是AlipayWallet.decrypted 重命名为AlipayWallet(否则闪退)

将应用程序从设备上拷贝到本地利用 ldid 将应用程序的 code sign 导出:ldid-eAlipayWallet>>AlipayWallet.xml在 AlipayWallet.xml文件中添加 get-task-allow权限get-task-allow利用 ldid 对应用进行重签名 ldid-SAlipayWallet.xml./AlipayWallet将应用拷回设备,将设置可执行权限 chmod755AlipayWallet完成

1

2

3

4

5

6

7

8

(图3)

iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手_第3张图片

ps:如果如上操作还闪退 请重启iphone

然后我们连上手机 xcode 随便弄个工程 选择iphone 看图来开始附加AlipayWallet(图4) 点到森林界面点击xcode自带的看界面工具 然后再xcode 右下角自带的lldb 下断点

我们先试着下断函数

iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手_第4张图片

b-[H5WebViewController reportClickTime]

1

提示找不到no locations 我们随便找个地址 看看堆栈信息

po[H5WebViewController _shortMethodDescription]

1

找一个地址

b 0x1057daab0

1

重开页面 触发断点 ,点开xcode的堆栈窗口如(图5)

iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手_第5张图片

发现很多地址是没函数名的 当然也无法直接对函数名下断点 我们借用大神写的工具来恢复这些信息 文章链接如下

http://www.jianshu.com/p/967b6631756c

之后 再附加一下

下这个断点

b-[H5WebViewController reportClickTime]

1

发现是可以成功下断了 继续查看堆栈信息 现在函数名全部全了

(图6)

iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手_第6张图片

往上回溯 思路 因为我们想找到是js过来的参数和调用原生方法是哪里过来的

毕竟 reportClickTime 不是我们要分析的

看到PSDJsBride 调用了很多次 而且看参数和函数名 很有可能 中转了消息和参数 为了验证我们的猜想 ,我们使用logify.pl 来生成tweak 打印他全部的调用日志

安装到手机之后,我们取消断电 打开xcode的日志看打印 有没有敏感的信息调用

brdelete

1

点击好友的那个能量收取 把日志全部copy 到Sublime text

看图(7)

iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手_第7张图片

我们看到这个英文单词 收集的意思 我们猜想这个就是收集能量的命令,看参数体有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":[26219984],"av":"5","ct":"ios"}],"disableLimitView":true},"callbackId":"rpc_15107976182910.0005478465463966131"}] url:https://60000002.h5app.alipay.com/app/src/home.html?userId=2088322012980000]

1

2

3

我们执行 看看日志打印 有日志输出 看recv这些参数 和刚刚是有点差别 但是大致一样(这个能量只能收一次)来看bubbleId 这个猜一下是能量的ID

来找怎么获取的能量ID 我们打开一个有能量的好友,看日志 有获取的调用没

由于日志比较多 我们就是着重找有返回bubbleId和friedID 的列表,找到之后往上找调用着参数

[m -[ 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;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

结果有了 找调用

_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]

1

2

用cycript 测试这个方法 。结果如我们所愿 日志返回了我们需要的能量ID和好友ID 可以构造第一个找到那个方法 实现收一个好友的能量

- 由于这个方法需要好友ID的参数 我们需要拿到全部好友的ID 这样才能实现我们的一键全部收取

- 这里我偷个懒 不去往下折腾 点击页面在PSDJsBridge transformResponseData

取top 10的好友ID(打开页面他本身执行了 friendRanking系列方法 )

编写Tweak

整理下流程,进页面 他自身调用Top10的好友列表 我们拿到这10个用户的UID

拿到UID之后执行上面分析的第二个方法 拿到指定用户可以收的能量 collectStatus=AVAILABLE 返回参数中有 我们看字段就能猜到

拿到UID和能量ID 我们就可以执行收能量的功能了

具体的代码不一一分析 下面会提供代码下载地址

看成功图8

iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手_第8张图片

总结

UIWebView的应用不同于原生的应用 有正向开发经验能通过UI层能轻易找到触发事件

其实很多时候都在试错和猜想 ,逐步的去验证自己的猜想 直到找到答案

这个Tweak只作技术分析,并没有完善 Top10用户收取还不够用 大家可以试着动手 获取下一页好友 和全部好友 看日志找到字段是可以轻易实现的 还有其他功能比如 每天定时启动收取啥的

这是代码GitHub地址

https://github.com/hackxhj/alipayForestTweak.git

欢迎star

你可能感兴趣的:(iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手)