申 请 I D:TKkk【申请通过】
1、申 请 I D:TKkk
2、个人邮箱:820352852@qq.com
3、原创技术文章:iOS、macOS 逆向开发
iOS逆向 - 微信自动添加好友一、前言本篇主要实现在微信上自动添加好友,从而熟悉 iOS 逆向分析的过程。二、 工具2.1 MacBook 软件
theos
制作 Tweak 的工具
hopper disassembler
用于静态分析
usbmuxd
端口转发,可以让我们通过usb连接手机进行ssh、lldb调试等。主要使用python-client目录下的文件
class-dump
dump 目标对象的 class 信息的工具.
lldb
调试神器,用过的都说好。默认自带,在/Applications/Xcode.app/Contents/Developer/usr/bin/lldb中。
2.2 越狱iPhone 软件以下软件在 Cydia 中即可下载
OpenSSH
实现在越狱手机上远程进行 ssh 服务
iOS 工具大部分都需要在 ssh 环境中使用
Cycript
脚本语言,用于 hook 正在运行的进程,并实时注入代码。
ondeviceconsole
用于在 Terminal 中查看手机的 log
debugserver
用于连接手机进行 lldb 调试的工具。用 Xcode 在手机上进行 app 调试即可生成,在手机目录的 /Developer/usr/bin/ 中。
使用 debugserver 需要先进行处理。因为缺少task_for_pid权限,所以调试不了其他的 app。
先通过 ssh 拷贝 debugserverscp root@iOSIP:/Developer/usr/bin/debugserver ~/debugserver减肥lipo -thin armv7s ~/debugserver -output ~/debugserver// 看自己手机是armv7s 还是arm64下载 ldid 与 ent,进行ldid - Sent.xml debugserver在使用 ssh 拷贝至手机,完成。三、 分析思路:想要实现自动添加好友,则要拿到获取好友请求的方法,以及添加好友的方法。hook 获取好友请求的方法,在接收到好友请求的时候,执行添加好友的方法。
而这些主要逻辑在“新的朋友”界面。3.1 定位好友请求的方法3.1.1 UI 分析
想要拿到好友请求的方法,要先拿到方法实现的 ViewController。而这时候可以通过 UI 分析获得。先打开新的朋友界面。
使用 usbmuxd 进行端口的转发(若手机不卡,可以跳过这步直接使用ssh进行wifi远程连接)python tcprelay.py -t 22:2222再使用ssh连接至手机ssh root@localhost -p 2222// ssh root@192.168.31.94查看微信的进程信息 ps -e |grep WeChatcycript 注入cycript -p WeChathttp://upload-images.jianshu.io/upload_images/965383-e394e365525d39ce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240查看当前 UI 布局UIApp.keyWindow.recursiveDescription().toString()http://upload-images.jianshu.io/upload_images/965383-14fd1a031898e6c5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240因为知道当前的视图有tableview,所以找到tableview的对象。从上图可以看到该对象的地址为0x18c4be00。
在使用 nextResponder()根据响应者往上找当前的控制器。http://upload-images.jianshu.io/upload_images/965383-74de0e0ecc36dea4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
找到当前的控制器,为SayHelloViewController3.1.2 Log 分析使用class-dump dump 出微信的 class 信息。class-dump -S -s -H demo.app -o ~/Document/headers/// 保存在 ~/Document/headers/ 目录中再使用 theos 的 logify 工具,该工具用来注入NSLog来打印方法的入参和出参。(就是在所有的方法里面加 log)logify.pl~/Document/headers/SayHelloViewController.h > ~/Desktop/Tweak.xm注意:一般该Tweak.xm仍然无法执行,需要进行修改: 去掉.cxx_destruct 方法将HBLogDebug 改为NSLog去掉所有的delegate将所有的参数对象类型改成id去掉所有的weak
再使用theos配置相关文件具体查看前一篇文章, 然后进行make package install 安装至手机。重新启动微信进入新的朋友界面。在ssh中使用ondeviceconsole打印手机的 log。这时用另一个微信号添加自己好友。出发好友请求的方法。可以看到以下的 log
http://upload-images.jianshu.io/upload_images/965383-4d05570bb509b76c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240说明有好友添加请求的时候,会调用
-3.1.3 动态分析既然已经知道了当前控制器会调用OnSayHelloDataChange,那么我们可以想如何查看是哪些方法触发了OnSayHelloDataChange,这时候就要用到 lldb + hopper 神器了。先用 hopper 打开微信的二进制文件。搜索-方法。
可以看到当前方法在微信中的偏移地址0x14a4824。
http://upload-images.jianshu.io/upload_images/965383-b26a7b9b0a4b8137.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240再使用 usbmuxd 转换端口python tcprelay.py -t 1234:1234在 ssh 到手机上,开启 debugserver 。debugserver *:1234 -a "WeChat"使用新的 terminal 窗口,打开 lldb,连接1234端口,并查看当前所有进程。
此时会卡住一段时间。// 打开lldb/Applications/Xcode.app/Contents/Developer/usr/bin/lldb// 连接端口调试(lldb) process connect connect://localhost:1234// 打印所有进程(lldb) image list -o -f找到微信在当前手机上的进程内存基地址为0x000b2000(这个值不是不变的)
http://upload-images.jianshu.io/upload_images/965383-b9d03f2861559bc4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240通过以上可以找到 方法在手机上的内存地址。即内存地址 = 进程内存基地址 + 方法偏移地址使用 br 打断点查看 br s -a "0x000b2000 + 0x14a4824"http://upload-images.jianshu.io/upload_images/965383-4df0f7635723f9ad.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240接着输入 c 继续运行,重新使用另一微信账号添加好友,会触发该断点。http://upload-images.jianshu.io/upload_images/965383-0537b74c6a74dc64.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240使用 bt 查看调用栈信息,即哪些方法调用了当前的方法,找到方法的上游。(异步调用的话没办法查看)http://upload-images.jianshu.io/upload_images/965383-2a0b5c07f2b6228f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240第一个表示当前的方法,可以看到在调用此方法前,该进程总共调用了3个方法。
分别计算出这三个方法在微信中的偏移量。http://upload-images.jianshu.io/upload_images/965383-d72d147e34823103.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240将这三个地址在 hopper 中查看,找到了对应的方法为// 调用的顺序为从下到上从以上方法名可以猜测是用来接收添加好友消息的函数处理,其中MsgList:后面的参数可能为消息的数组,为了证明我们可以打个断点查看下。
http://upload-images.jianshu.io/upload_images/965383-6ebda3da00e0961e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240看出r3确实是个数组,同时也得到了消息的对象为CMessageWrap 证明我们是对的。解释下为什么要看r3,因为在 armv7 中,一个方法的调用,一般寄存器都是这么存储的。前四个参数放在r0~r3,剩下的存放在堆栈中。查看堆栈的话使用x/10 $sp 查看前10个堆栈里的对象地址。然而FriendAsistSessionMgr这个类可能需要一些初始化,且放在SayHelloViewController中,而我们想要的是不管在哪个控制器里都可以 hook 住上面的消息数组对象。因此我们往上找,,然而里面并没有我们需要的信息。而根据类名我们推测CMessageMgr是用来管理消息的。有可能是在异步执行了消息数组的获取。因此,重复以上步骤,使用 logify 对CMessageMgr进行 Log 分析。最终锁定了
CMessageMgr MessageReturn: MessageInfo:Event:http://upload-images.jianshu.io/upload_images/965383-3468f03ae467b502.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/12403.2 定位 通过好友请求的方法3.2.1 动态分析我们知道,通过好友请求的方法,是在新的朋友界面,点击接受的时候触发的。(可以通过 Log 分析,然而这里还有另一个比较快速的方法)http://upload-images.jianshu.io/upload_images/965383-99f263b1eeef35d6.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240同样,我们可以使用 cycript 进行定位。
先按照 3.1 的方法,打印出所有的UI层级。
找到“接受”按钮的对象,(有个技巧,我们知道当前按钮是在某个cell下面的,所以定位这个)。http://upload-images.jianshu.io/upload_images/965383-8ee7092ddf3652e2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
在把该对象的 hidden = 1,看是否隐藏。#0x186922f0.hidden = 1发现按钮不见了,证明我们是对的。
而我们知道 UIButton 是继承 UIControl 的,而 UIControl 的话可以通过allTargets 与 allControlEvents查看所有的对象与事件,再使用actionsForTarget:forControlEvent:从而找到触发的方法。http://upload-images.jianshu.io/upload_images/965383-0cc2c5f799fd34a3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240看出所触发的方法为3.2.2 静态分析既然拿到了方法名,那我们怎么看他具体的实现呢?
接下来就是大名鼎鼎的hopper 登场了。
用 hopper 打开微信的二进制文件,并进行汇编与伪代码的转换。
由于汇编读起来比较晦涩,所以还是进行伪代码的转换,这样效率比较快。点击该按钮进行转换http://upload-images.jianshu.io/upload_images/965383-c0af27f7c934875c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240可以得到伪代码
http://upload-images.jianshu.io/upload_images/965383-8460f25f8c48b99f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
上图我们看到了r10 = self;r5 = r10 + *0x33befe8;r4 = objc_loadWeakRetained(r5);r8 = @selector(onContactsItemViewRightButtonClick:);r11 = ;可以得出,r11 = ,而 r5 我们判断为 self 的代{过}{滤}理,这个我们也可以通过在之前用 class-dump 的头文件里面搜索onContactsItemViewRightButtonClick,会发现在ContactsItemViewDelegate中。
也就是内部调用了.
而 ContactsItemView 的delegate为 SayHelloViewController。再用 hopper 定位onContactsItemViewRightButtonClick。http://upload-images.jianshu.io/upload_images/965383-53a73e5158a5d8e2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
http://upload-images.jianshu.io/upload_images/965383-e8d5d1dca6ad78ed.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240看到这里估计会很蒙不知道从何下手。这时候只要加以推测就可以了。
上图中进行了两个if判断,第一个为r10 = @selector(class);r2 = loc_1c099bc(@class(CPushContact), r10);r1 = @selector(isKindOfClass:);r5 = loc_1c099bc(r4, r1, r2);loc_1c099d4(r4);if ((r5 & 0xff) != 0x0) {可以得出其实是执行了 if(]);
而r4是什么呢?可以肯定是 CPushContact 对象,不然下面的代码都不执行了。我们可以根据3.1的动态分析,通过lldb打断点,并查看r3寄存器的对象类型,可以看到该对象为 CPushContact 对象。因此r4就是 CPushContact 对象,根据字面意思可以得到就是联系人对象。继续看下面的代码,可以看到也进行了一次判断if (((loc_1c099bc(r6, @selector(m_bSuspiciousUser)) & 0xff) != 0x0) && ((loc_1c099bc(r6, @selector(isMMContact)) & 0xff) == 0x0)),看到了MMUIAlertView。推测是弹窗的 view ,推测如果是可疑的用户或者当前申请的好友已经是自己的好友,那就进行弹窗。而另一部分为verifyContactWithOpCode:opcode:,推测该部分为添加好友的方法。
可以通过Log 分析或者通过 lldb 打断点,会看到都会进入该方法。且参数分别为 CPushContact 对象与 3。
接着继续分析verifyContactWithOpCode:opcode:方法。主要的部分如下所示。http://upload-images.jianshu.io/upload_images/965383-8ca8ba77b4303d76.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240通过分析,我们可以得到,确认好友申请,显示构造了CContactVerifyLogic对象。再构造了一个CVerifyContactWrap对象,并设置了相关属性,比如m_nsUsrName m_uiScene m_nsTicket.然后通过添加到数组中,通过CContactVerifyLogic对象的startWithVerifyContactWrap:opCode:parentView:fromChatRoom:方法发送。
代码如下:CContactVerifyLogic *verifyLogic = [ init];CVerifyContactWrap *wrap = [ init];;;;;wrap.m_oVerifyContact = contact;AutoSetRemarkMgr *mgr = [ getService:];id attr = ;if() { ;} opCode:3 parentView: fromChatRoom:NO];这样我们就得到了 获取好友请求的方法与添加好友的方法。
而这里还有一个问题,就是添加好友的对象是CPushContact,而获得好友请求的对象的CMessageWrap。这里需要进行转换,而转换的方法也在SayHelloViewController中,可以重复上面的分析方法获得。四、编写Tweak通过以上的分析,将代码合并起来%hook CMessageMgr- (void)MessageReturn:(unsigned int)arg1 MessageInfo:(NSDictionary *)info Event:(unsigned int)arg3 { %orig; if (arg1 == 332) { // 收到添加好友消息 NSString *keyStr = ; if () { NSArray *wrapArray = ; ; } }}%new- (void)addAutoVerifyWithArray:(NSArray *)ary { ; if (! && ) { CContactVerifyLogic *verifyLogic = [[%c(CContactVerifyLogic) alloc] init]; CVerifyContactWrap *wrap = [[%c(CVerifyContactWrap) alloc] init]; ; ; ; ; wrap.m_oVerifyContact = contact; AutoSetRemarkMgr *mgr = [[%c(MMServiceCenter) defaultCenter] getService:%c(AutoSetRemarkMgr)]; id attr = ; if() { ; } opCode:3 parentView: fromChatRoom:NO]; } }];}五、总结由于整个逆向流程有点繁琐,有时候也不是只要分析一次就可以成功的,需要反反复复的进行UI分析、LOG分析、lldb分析。因此可能在过程中,有些知识没有漏掉,希望大家可以指出。六、参考iOS应用逆向工程 第2版
移动App入侵与逆向破解技术-iOS篇 格式这叫一个乱,从哪复制来的? Hmily 发表于 2017-9-4 15:56
格式这叫一个乱,从哪复制来的?
我去,,,markdown 复制过来的。 Hmily 发表于 2017-9-4 15:56
格式这叫一个乱,从哪复制来的?
预览的时候倒是挺正常的… Hmily 发表于 2017-9-4 15:56
格式这叫一个乱,从哪复制来的?
这文章是自己写的,还没发到网上。 # iOS逆向 - 微信自动添加好友
## 一、前言
本篇主要实现在微信上自动添加好友,从而熟悉 iOS 逆向分析的过程。
## 二、 工具
### 2.1 MacBook 软件
*(https://github.com/theos/theos)
> 制作 Tweak 的工具
* (https://www.hopperapp.com)
>用于静态分析
* (http://cgit.sukimashita.com/usbmuxd.git/snapshot/usbmuxd-1.0.8.tar.gz)
> 端口转发,可以让我们通过usb连接手机进行ssh、lldb调试等。~~主要使用`python-client`目录下的文件~~
* (http://stevenygard.com/projects/class-dump/)
>dump 目标对象的 class 信息的工具.
* lldb
> 调试神器,用过的都说好。默认自带,在`/Applications/Xcode.app/Contents/Developer/usr/bin/lldb` 中。
### 2.2 越狱iPhone 软件
**以下软件在 Cydia 中即可下载**
* OpenSSH
>实现在越狱手机上远程进行 ssh 服务
**iOS 工具大部分都需要在 ssh 环境中使用**
* Cycript
>脚本语言,用于 hook 正在运行的进程,并实时注入代码。
* ondeviceconsole
> 用于在 Terminal 中查看手机的 log
* debugserver
> 用于连接手机进行 lldb 调试的工具。用 Xcode 在手机上进行 app 调试即可生成,在手机目录的 `/Developer/usr/bin/` 中。
使用 debugserver 需要先进行处理。因为缺少`task_for_pid`权限,所以调试不了其他的 app。
先通过 ssh 拷贝 debugserver
```
scp root@iOSIP:/Developer/usr/bin/debugserver ~/debugserver
```
减肥
```
lipo -thin armv7s ~/debugserver -output ~/debugserver
// 看自己手机是armv7s 还是arm64
```
下载 (http://joedj.net/ldid) 与 (http://iosre.com/ent.xml),进行
```
ldid - Sent.xml debugserver
```
在使用 ssh 拷贝至手机,完成。
## 三、 分析
思路:想要实现自动添加好友,则要拿到获取好友请求的方法,以及添加好友的方法。hook 获取好友请求的方法,在接收到好友请求的时候,执行添加好友的方法。
而这些主要逻辑在“新的朋友”界面。
### 3.1 定位好友请求的方法
#### 3.1.1 UI 分析
>想要拿到好友请求的方法,要先拿到方法实现的 ViewController。而这时候可以通过 UI 分析获得。
先打开新的朋友界面。
使用 `usbmuxd` 进行端口的转发(~~若手机不卡,可以跳过这步直接使用ssh进行wifi远程连接~~)
```
python tcprelay.py -t 22:2222
```
再使用ssh连接至手机
```
ssh root@localhost -p 2222
// ssh root@192.168.31.94
```
查看微信的进程信息
```
ps -e |grep WeChat
```
cycript 注入
```
cycript -p WeChat
```
![屏幕快照 2017-04-01 上午10.14.43.png](http://upload-images.jianshu.io/upload_images/965383-e394e365525d39ce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
查看当前 UI 布局
```
UIApp.keyWindow.recursiveDescription().toString()
```
![屏幕快照 2017-04-01 上午10.57.28.png](http://upload-images.jianshu.io/upload_images/965383-14fd1a031898e6c5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
因为知道当前的视图有tableview,所以找到tableview的对象。从上图可以看到该对象的地址为0x18c4be00。
在使用 `nextResponder()`根据响应者往上找当前的控制器。
![屏幕快照 2017-04-01 上午11.01.03.png](http://upload-images.jianshu.io/upload_images/965383-74de0e0ecc36dea4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
找到当前的控制器,为`SayHelloViewController`
#### 3.1.2 Log 分析
使用`class-dump` dump 出微信的 class 信息。
```
class-dump -S -s -H demo.app -o ~/Document/headers/
// 保存在 ~/Document/headers/ 目录中
```
再使用 theos 的 logify 工具,该工具用来注入`NSLog`来打印方法的入参和出参。(~~就是在所有的方法里面加 log~~)
```
logify.pl~/Document/headers/SayHelloViewController.h > ~/Desktop/Tweak.xm
```
**注意:**一般该Tweak.xm仍然无法执行,需要进行修改:
* 去掉.cxx_destruct 方法
* 将HBLogDebug 改为NSLog
* 去掉所有的delegate
* 将所有的参数对象类型改成id
* 去掉所有的weak
再使用theos配置相关文件~~具体查看前一篇文章~~, 然后进行make package install 安装至手机。
重新启动微信进入新的朋友界面。
在ssh中使用`ondeviceconsole`打印手机的 log。
这时用另一个微信号添加自己好友。出发好友请求的方法。可以看到以下的 log
![屏幕快照 2017-04-01 上午11.22.48.png](http://upload-images.jianshu.io/upload_images/965383-4d05570bb509b76c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
说明有好友添加请求的时候,会调用
`-`
#### 3.1.3 动态分析
既然已经知道了当前控制器会调用`OnSayHelloDataChange`,那么我们可以想如何查看是哪些方法触发了`OnSayHelloDataChange`,这时候就要用到 lldb + hopper 神器了。
先用 hopper 打开微信的二进制文件。搜索`-`方法。
可以看到当前方法在微信中的偏移地址0x14a4824。
!(http://upload-images.jianshu.io/upload_images/965383-b26a7b9b0a4b8137.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
再使用 usbmuxd 转换端口
```
python tcprelay.py -t 1234:1234
```
在 ssh 到手机上,开启 debugserver 。
```
debugserver *:1234 -a "WeChat"
```
使用新的 terminal 窗口,打开 lldb,连接1234端口,并查看当前所有进程。
此时会卡住一段时间。
```
// 打开lldb
/Applications/Xcode.app/Contents/Developer/usr/bin/lldb
// 连接端口调试
(lldb) process connect connect://localhost:1234
// 打印所有进程
(lldb) image list -o -f
```
找到微信在当前手机上的进程内存基地址为0x000b2000(~~这个值不是不变的~~)
!(http://upload-images.jianshu.io/upload_images/965383-b9d03f2861559bc4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
通过以上可以找到 ``方法在手机上的内存地址。即
```
内存地址 = 进程内存基地址 + 方法偏移地址
```
使用 br 打断点查看
```
br s -a "0x000b2000 + 0x14a4824"
```
![屏幕快照 2017-04-01 上午11.39.22.png](http://upload-images.jianshu.io/upload_images/965383-4df0f7635723f9ad.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
接着输入 `c` 继续运行,重新使用另一微信账号添加好友,会触发该断点。
![屏幕快照 2017-04-01 上午11.41.35.png](http://upload-images.jianshu.io/upload_images/965383-0537b74c6a74dc64.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
使用 `bt` 查看调用栈信息,即哪些方法调用了当前的方法,找到方法的上游。(异步调用的话没办法查看)
!(http://upload-images.jianshu.io/upload_images/965383-2a0b5c07f2b6228f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
第一个表示当前的方法,可以看到在调用此方法前,该进程总共调用了3个方法。
分别计算出这三个方法在微信中的偏移量。
![屏幕快照 2017-04-01 上午11.48.13.png](http://upload-images.jianshu.io/upload_images/965383-d72d147e34823103.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
将这三个地址在 hopper 中查看,找到了对应的方法为
```
// 调用的顺序为从下到上
```
从以上方法名可以猜测
```
```
是用来接收添加好友消息的函数处理,其中`MsgList:`后面的参数可能为消息的数组,为了证明我们可以打个断点查看下。
![屏幕快照 2017-04-01 下午2.05.24.png](http://upload-images.jianshu.io/upload_images/965383-6ebda3da00e0961e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
看出r3确实是个数组,同时也得到了消息的对象为`CMessageWrap` 证明我们是对的。
~~解释下为什么要看r3,因为在 armv7 中,一个方法的调用,一般寄存器都是这么存储的。前四个参数放在r0~r3,剩下的存放在堆栈中。查看堆栈的话使用`x/10 $sp` 查看前10个堆栈里的对象地址。~~
然而`FriendAsistSessionMgr`这个类可能需要一些初始化,且放在`SayHelloViewController`中,而我们想要的是不管在哪个控制器里都可以 hook 住上面的消息数组对象。因此我们往上找,``,然而里面并没有我们需要的信息。而根据类名我们推测`CMessageMgr`是用来管理消息的。有可能是在异步执行了消息数组的获取。
因此,重复以上步骤,使用 logify 对`CMessageMgr`进行 Log 分析。最终锁定了
`CMessageMgr MessageReturn: MessageInfo:Event:`
![屏幕快照 2017-04-05 下午3.02.50.png](http://upload-images.jianshu.io/upload_images/965383-3468f03ae467b502.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
### 3.2 定位 通过好友请求的方法
#### 3.2.1 动态分析
我们知道,通过好友请求的方法,是在新的朋友界面,点击接受的时候触发的。(~~可以通过 Log 分析,然而这里还有另一个比较快速的方法~~)
!(http://upload-images.jianshu.io/upload_images/965383-99f263b1eeef35d6.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
同样,我们可以使用 cycript 进行定位。
先按照 3.1 的方法,打印出所有的UI层级。
找到“接受”按钮的对象,(有个技巧,我们知道当前按钮是在某个cell下面的,所以定位这个)。
!(http://upload-images.jianshu.io/upload_images/965383-8ee7092ddf3652e2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在把该对象的 hidden = 1,看是否隐藏。
```
#0x186922f0.hidden = 1
```
发现按钮不见了,证明我们是对的。
而我们知道 UIButton 是继承 UIControl 的,而 UIControl 的话可以通过`allTargets` 与 `allControlEvents`查看所有的对象与事件,再使用`actionsForTarget:forControlEvent:`从而找到触发的方法。
![屏幕快照 2017-04-05 下午3.30.08.png](http://upload-images.jianshu.io/upload_images/965383-0cc2c5f799fd34a3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
看出所触发的方法为``
#### 3.2.2 静态分析
既然拿到了方法名,那我们怎么看他具体的实现呢?
接下来就是大名鼎鼎的hopper 登场了。
用 hopper 打开微信的二进制文件,并进行汇编与伪代码的转换。
~~由于汇编读起来比较晦涩,所以还是进行伪代码的转换,这样效率比较快。~~点击该按钮进行转换
!(http://upload-images.jianshu.io/upload_images/965383-c0af27f7c934875c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可以得到伪代码
![屏幕快照 2017-04-05 下午3.56.21.png](http://upload-images.jianshu.io/upload_images/965383-8460f25f8c48b99f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
上图我们看到了
```
r10 = self;
r5 = r10 + *0x33befe8;
r4 = objc_loadWeakRetained(r5);
r8 = @selector(onContactsItemViewRightButtonClick:);
r11 = ;
```
可以得出,`r11 = `,而 r5 我们判断为 self 的代{过}{滤}理,这个我们也可以通过在之前用 class-dump 的头文件里面搜索`onContactsItemViewRightButtonClick`,会发现在`ContactsItemViewDelegate`中。
也就是``内部调用了``.
而 `ContactsItemView` 的`delegate`为 `SayHelloViewController`。
再用 hopper 定位`onContactsItemViewRightButtonClick`。
![屏幕快照 2017-04-05 下午4.05.49.png](http://upload-images.jianshu.io/upload_images/965383-53a73e5158a5d8e2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![屏幕快照 2017-04-05 下午4.14.09.png](http://upload-images.jianshu.io/upload_images/965383-e8d5d1dca6ad78ed.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
看到这里估计会很蒙不知道从何下手。这时候只要加以推测就可以了。
上图中进行了两个if判断,第一个为
```
r10 = @selector(class);
r2 = loc_1c099bc(@class(CPushContact), r10);
r1 = @selector(isKindOfClass:);
r5 = loc_1c099bc(r4, r1, r2);
loc_1c099d4(r4);
if ((r5 & 0xff) != 0x0) {
```
可以得出其实是执行了 `if(])`;
而r4是什么呢?可以肯定是 CPushContact 对象,不然下面的代码都不执行了。我们可以根据3.1的动态分析,通过lldb打断点,并查看r3寄存器的对象类型,可以看到该对象为 CPushContact 对象。因此r4就是 CPushContact 对象,根据字面意思可以得到就是联系人对象。
继续看下面的代码,可以看到也进行了一次判断` if (((loc_1c099bc(r6, @selector(m_bSuspiciousUser)) & 0xff) != 0x0) && ((loc_1c099bc(r6, @selector(isMMContact)) & 0xff) == 0x0)) `,看到了`MMUIAlertView`。推测是弹窗的 view ,推测如果是可疑的用户或者当前申请的好友已经是自己的好友,那就进行弹窗。而另一部分为`verifyContactWithOpCode:opcode:`,推测该部分为添加好友的方法。
可以通过Log 分析或者通过 lldb 打断点,会看到都会进入该方法。且参数分别为 CPushContact 对象与 3。
接着继续分析`verifyContactWithOpCode:opcode:`方法。主要的部分如下所示。
!(http://upload-images.jianshu.io/upload_images/965383-8ca8ba77b4303d76.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
通过分析,我们可以得到,确认好友申请,显示构造了`CContactVerifyLogic`对象。再构造了一个`CVerifyContactWrap`对象,并设置了相关属性,比如`m_nsUsrName` `m_uiScene` `m_nsTicket`.然后通过添加到数组中,通过`CContactVerifyLogic`对象的`startWithVerifyContactWrap:opCode:parentView:fromChatRoom:`方法发送。
代码如下:
```
CContactVerifyLogic *verifyLogic = [ init];
CVerifyContactWrap *wrap = [ init];
;
;
;
;
wrap.m_oVerifyContact = contact;
AutoSetRemarkMgr *mgr = [ getService:];
id attr = ;
if() {
;
}
opCode:3 parentView: fromChatRoom:NO];
```
这样我们就得到了 获取好友请求的方法与添加好友的方法。
而这里还有一个问题,就是添加好友的对象是`CPushContact`,而获得好友请求的对象的`CMessageWrap`。这里需要进行转换,而转换的方法也在`SayHelloViewController`中,可以重复上面的分析方法获得。
## 四、编写Tweak
通过以上的分析,将代码合并起来
```
%hook CMessageMgr
- (void)MessageReturn:(unsigned int)arg1 MessageInfo:(NSDictionary *)info Event:(unsigned int)arg3 {
%orig;
if (arg1 == 332) { // 收到添加好友消息
NSString *keyStr = ;
if () {
NSArray *wrapArray = ;
;
}
}
}
%new
- (void)addAutoVerifyWithArray:(NSArray *)ary {
[ary enumerateObjectsUsingBlock:^(id_Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
CPushContact *contact = [%c(SayHelloDataLogic) getContactFrom:obj];
if (! && ) {
CContactVerifyLogic *verifyLogic = [[%c(CContactVerifyLogic) alloc] init];
CVerifyContactWrap *wrap = [[%c(CVerifyContactWrap) alloc] init];
;
;
;
;
wrap.m_oVerifyContact = contact;
AutoSetRemarkMgr *mgr = [[%c(MMServiceCenter) defaultCenter] getService:%c(AutoSetRemarkMgr)];
id attr = ;
if() {
;
}
opCode:3 parentView: fromChatRoom:NO];
}
}];
}
```
## 五、总结
由于整个逆向流程有点繁琐,有时候也不是只要分析一次就可以成功的,需要反反复复的进行UI分析、LOG分析、lldb分析。因此可能在过程中,有些知识没有漏掉,希望大家可以指出。
## 六、参考
(https://book.douban.com/subject/26363333/)
[移动App入侵与逆向破解技术-iOS篇](http://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=2653577384&idx=1&sn=b44a9c9651bf09c5bea7e0337031c53c&scene=0#wechat_redirect) I D:TKkk
邮箱:820352852@qq.com
申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。
ps:登录报道后把文章整理一下发到移动安全区。 报到,感谢管理员。 欢迎大神。。。小弟膜拜了
页:
[1]