一、前言 本篇主要实现在微信上自动添加好友,从而熟悉 iOS 逆向分析的过程。 二、 工具 2.1 MacBook 软件
2.2 越狱iPhone 软件 以下软件在 Cydia 中即可下载
使用 debugserver 需要先进行处理。因为缺少 先通过 ssh 拷贝 debugserver scp 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 分析
先打开新的朋友界面。 使用 python tcprelay.py -t 22:2222 再使用ssh连接至手机 ssh roothome.php?mod=space&uid=485241 -p 2222// ssh [email protected] 查看微信的进程信息 ps -e |grep WeChat cycript 注入 cycript -p WeChat 查看当前 UI 布局 UIApp.keyWindow.recursiveDescription().toString() 因为知道当前的视图有tableview,所以找到tableview的对象。从上图可以看到该对象的地址为0x18c4be00。 在使用 找到当前的控制器,为 3.1.2 Log 分析 使用 class-dump -S -s -H demo.app -o ~/Document/headers/// 保存在 ~/Document/headers/ 目录中 再使用 theos 的 logify 工具,该工具用来注入 logify.pl ~/Document/headers/SayHelloViewController.h > ~/Desktop/Tweak.xm 注意:一般该Tweak.xm仍然无法执行,需要进行修改:
再使用theos配置相关文件具体查看前一篇文章, 然后进行make package install 安装至手机。 重新启动微信进入新的朋友界面。 在ssh中使用 这时用另一个微信号添加自己好友。出发好友请求的方法。可以看到以下的 log 说明有好友添加请求的时候,会调用
3.1.3 动态分析 既然已经知道了当前控制器会调用 先用 hopper 打开微信的二进制文件。搜索 可以看到当前方法在微信中的偏移地址0x14a4824。 再使用 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(这个值不是不变的) 通过以上可以找到 内存地址 = 进程内存基地址 + 方法偏移地址 使用 br 打断点查看 br s -a "0x000b2000 + 0x14a4824" 接着输入
使用 第一个表示当前的方法,可以看到在调用此方法前,该进程总共调用了3个方法。 分别计算出这三个方法在微信中的偏移量。
将这三个地址在 hopper 中查看,找到了对应的方法为 // 调用的顺序为从下到上[SayHelloViewController OnSayHelloDataChange][SayHelloDataLogic onFriendAssistAddMsg:][FriendAsistSessionMgr OnAddMsgForSpecialSession:MsgList:][CMessageMgr MainThreadNotifyToExt:] 从以上方法名可以猜测 [FriendAsistSessionMgr OnAddMsgForSpecialSession:MsgList:] 是用来接收添加好友消息的函数处理,其中
看出r3确实是个数组,同时也得到了消息的对象为 解释下为什么要看r3,因为在 armv7 中,一个方法的调用,一般寄存器都是这么存储的。前四个参数放在r0~r3,剩下的存放在堆栈中。查看堆栈的话使用 然而 因此,重复以上步骤,使用 logify 对
3.2 定位 通过好友请求的方法 3.2.1 动态分析 我们知道,通过好友请求的方法,是在新的朋友界面,点击接受的时候触发的。(可以通过 Log 分析,然而这里还有另一个比较快速的方法)
同样,我们可以使用 cycript 进行定位。 先按照 3.1 的方法,打印出所有的UI层级。 找到“接受”按钮的对象,(有个技巧,我们知道当前按钮是在某个cell下面的,所以定位这个)。 在把该对象的 hidden = 1,看是否隐藏。 #0x186922f0.hidden = 1 发现按钮不见了,证明我们是对的。 而我们知道 UIButton 是继承 UIControl 的,而 UIControl 的话可以通过 看出所触发的方法为 3.2.2 静态分析 既然拿到了方法名,那我们怎么看他具体的实现呢? 接下来就是大名鼎鼎的hopper 登场了。 用 hopper 打开微信的二进制文件,并进行汇编与伪代码的转换。 由于汇编读起来比较晦涩,所以还是进行伪代码的转换,这样效率比较快。点击该按钮进行转换 可以得到伪代码
上图我们看到了 r10 = self;r5 = r10 + *0x33befe8;r4 = objc_loadWeakRetained(r5);r8 = @selector(onContactsItemViewRightButtonClick:);r11 = [r4 respondsToSelector:r8]; 可以得出, 也就是 而 再用 hopper 定位
看到这里估计会很蒙不知道从何下手。这时候只要加以推测就可以了。 上图中进行了两个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) {可以得出其实是执行了 而r4是什么呢?可以肯定是 CPushContact 对象,不然下面的代码都不执行了。我们可以根据3.1的动态分析,通过lldb打断点,并查看r3寄存器的对象类型,可以看到该对象为 CPushContact 对象。因此r4就是 CPushContact 对象,根据字面意思可以得到就是联系人对象。 继续看下面的代码,可以看到也进行了一次判断 可以通过Log 分析或者通过 lldb 打断点,会看到都会进入该方法。且参数分别为 CPushContact 对象与 3。 接着继续分析
通过分析,我们可以得到,确认好友申请,显示构造了 代码如下: CContactVerifyLogic *verifyLogic = [[CContactVerifyLogic alloc] init];CVerifyContactWrap *wrap = [[CVerifyContactWrap alloc] init];[wrap setM_nsUsrName:contact.m_nsEncodeUserName];[wrap setM_uiScene:contact.m_uiFriendScene];[wrap setM_nsTicket:contact.m_nsTicket];[wrap setM_nsChatRoomUserName:contact.m_nsChatRoomUserName];wrap.m_oVerifyContact = contact;AutoSetRemarkMgr *mgr = [[MMServiceCenter defaultCenter] getService:[AutoSetRemarkMgr class]];id attr = [mgr GetStrangerAttribute:contact AttributeName:1001];if([attr boolValue]) { [wrap setM_uiWCFlag:(wrap.m_uiWCFlag | 1)];}[verifyLogic startWithVerifyContactWrap:[NSArray arrayWithObject:wrap] opCode:3 parentView:[UIView new] fromChatRoom:NO];这样我们就得到了 获取好友请求的方法与添加好友的方法。 而这里还有一个问题,就是添加好友的对象是 四、编写Tweak 通过以上的分析,将代码合并起来 %hook CMessageMgr- (void)MessageReturn:(unsigned int)arg1 MessageInfo:(NSDictionary *)info Event:(unsigned int)arg3 { %orig; if (arg1 == 332) { // 收到添加好友消息 NSString *keyStr = [info objectForKey:@"5"]; if ([keyStr isEqualToString:@"fmessage"]) { NSArray *wrapArray = [info objectForKey:@"27"]; [self addAutoVerifyWithArray:wrapArray]; } }}%new- (void)addAutoVerifyWithArray:(NSArray *)ary { [ary enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { CPushContact *contact = [%c(SayHelloDataLogic) getContactFrom:obj]; if (![contact isMyContact] && [contact.m_nsDes isEqualToString:autoVerifyKeyword]) { CContactVerifyLogic *verifyLogic = [[%c(CContactVerifyLogic) alloc] init]; CVerifyContactWrap *wrap = [[%c(CVerifyContactWrap) alloc] init]; [wrap setM_nsUsrName:contact.m_nsEncodeUserName]; [wrap setM_uiScene:contact.m_uiFriendScene]; [wrap setM_nsTicket:contact.m_nsTicket]; [wrap setM_nsChatRoomUserName:contact.m_nsChatRoomUserName]; wrap.m_oVerifyContact = contact; AutoSetRemarkMgr *mgr = [[%c(MMServiceCenter) defaultCenter] getService:%c(AutoSetRemarkMgr)]; id attr = [mgr GetStrangerAttribute:contact AttributeName:1001]; if([attr boolValue]) { [wrap setM_uiWCFlag:(wrap.m_uiWCFlag | 1)]; } [verifyLogic startWithVerifyContactWrap:[NSArray arrayWithObject:wrap] opCode:3 parentView:[UIView new] fromChatRoom:NO]; } }];}五、总结 由于整个逆向流程有点繁琐,有时候也不是只要分析一次就可以成功的,需要反反复复的进行UI分析、LOG分析、lldb分析。因此可能在过程中,有些知识没有漏掉,希望大家可以指出。 |
| 本文出处: http://www.toutiao.com/a6466951522549760526/ |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|