吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 148913|回复: 655
上一主题 下一主题
收起左侧

[iOS 原创] iOS逆向 - 微信自动添加好友

    [复制链接]
跳转到指定楼层
楼主
TKkk 发表于 2017-9-4 17:28 回帖奖励
本帖最后由 TKkk 于 2017-9-4 17:43 编辑


相关源码:Github地址

WeChatPlugin-iOS
Mac OS 版微信小助手(远程控制、消息防撤回、自动回复、微信多开)

一、前言

本篇主要实现在微信上自动添加好友,从而熟悉 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 拷贝 debugserver

scp root@iOSIP:/Developer/usr/bin/debugserver ~/debugserver

减肥

lipo -thin armv7s ~/debugserver -output ~/debugserver
// 看自己手机是armv7s 还是arm64

下载 ldident,进行

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

查看当前 UI 布局

UIApp.keyWindow.recursiveDescription().toString()

屏幕快照 2017-04-01 上午10.57.28.png

因为知道当前的视图有tableview,所以找到tableview的对象。从上图可以看到该对象的地址为0x18c4be00。
在使用 nextResponder()根据响应者往上找当前的控制器。

屏幕快照 2017-04-01 上午11.01.03.png
找到当前的控制器,为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

说明有好友添加请求的时候,会调用
-[SayHelloViewController OnSayHelloDataChange]

3.1.3 动态分析

既然已经知道了当前控制器会调用OnSayHelloDataChange,那么我们可以想如何查看是哪些方法触发了OnSayHelloDataChange,这时候就要用到 lldb + hopper 神器了。

先用 hopper 打开微信的二进制文件。搜索-[SayHelloViewController OnSayHelloDataChange]方法。
可以看到当前方法在微信中的偏移地址0x14a4824。
QQ20170401-113150@2x.png

再使用 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(这个值不是不变的)
QQ20170401-113326@2x.png

通过以上可以找到 [SayHelloViewController OnSayHelloDataChange]方法在手机上的内存地址。即

内存地址 = 进程内存基地址 + 方法偏移地址

使用 br 打断点查看

 br s -a "0x000b2000 + 0x14a4824"

屏幕快照 2017-04-01 上午11.39.22.png

接着输入 c 继续运行,重新使用另一微信账号添加好友,会触发该断点。

屏幕快照 2017-04-01 上午11.41.35.png

使用 bt 查看调用栈信息,即哪些方法调用了当前的方法,找到方法的上游。(异步调用的话没办法查看)

QQ20170401-114245@2x.png

第一个表示当前的方法,可以看到在调用此方法前,该进程总共调用了3个方法。
分别计算出这三个方法在微信中的偏移量。

屏幕快照 2017-04-01 上午11.48.13.png

将这三个地址在 hopper 中查看,找到了对应的方法为

// 调用的顺序为从下到上
[SayHelloViewController OnSayHelloDataChange]
[SayHelloDataLogic onFriendAssistAddMsg:]
[FriendAsistSessionMgr OnAddMsgForSpecialSession:MsgList:]
[CMessageMgr MainThreadNotifyToExt:]

从以上方法名可以猜测

[FriendAsistSessionMgr OnAddMsgForSpecialSession:MsgList:]

是用来接收添加好友消息的函数处理,其中MsgList:后面的参数可能为消息的数组,为了证明我们可以打个断点查看下。
屏幕快照 2017-04-01 下午2.05.24.png

看出r3确实是个数组,同时也得到了消息的对象为CMessageWrap 证明我们是对的。

解释下为什么要看r3,因为在 armv7 中,一个方法的调用,一般寄存器都是这么存储的。前四个参数放在r0~r3,剩下的存放在堆栈中。查看堆栈的话使用x/10 $sp 查看前10个堆栈里的对象地址。

然而FriendAsistSessionMgr这个类可能需要一些初始化,且放在SayHelloViewController中,而我们想要的是不管在哪个控制器里都可以 hook 住上面的消息数组对象。因此我们往上找,[CMessageMgr MainThreadNotifyToExt:],然而里面并没有我们需要的信息。而根据类名我们推测CMessageMgr是用来管理消息的。有可能是在异步执行了消息数组的获取。

因此,重复以上步骤,使用 logify 对CMessageMgr进行 Log 分析。最终锁定了
CMessageMgr MessageReturn: MessageInfo:Event:

屏幕快照 2017-04-05 下午3.02.50.png

3.2 定位 通过好友请求的方法

3.2.1 动态分析

我们知道,通过好友请求的方法,是在新的朋友界面,点击接受的时候触发的。(可以通过 Log 分析,然而这里还有另一个比较快速的方法)

WechatIMG15.jpeg

同样,我们可以使用 cycript 进行定位。
先按照 3.1 的方法,打印出所有的UI层级。
找到“接受”按钮的对象,(有个技巧,我们知道当前按钮是在某个cell下面的,所以定位这个)。

WX20170405-152315@2x.png
在把该对象的 hidden = 1,看是否隐藏。

#0x186922f0.hidden = 1

发现按钮不见了,证明我们是对的。
而我们知道 UIButton 是继承 UIControl 的,而 UIControl 的话可以通过allTargetsallControlEvents查看所有的对象与事件,再使用actionsForTarget:forControlEvent:从而找到触发的方法。

屏幕快照 2017-04-05 下午3.30.08.png

看出所触发的方法为[ContactsItemView onRightBtnAction]

3.2.2 静态分析

既然拿到了方法名,那我们怎么看他具体的实现呢?
接下来就是大名鼎鼎的hopper 登场了。
用 hopper 打开微信的二进制文件,并进行汇编与伪代码的转换。
由于汇编读起来比较晦涩,所以还是进行伪代码的转换,这样效率比较快。点击该按钮进行转换

QQ20170401-094655@2x.png

可以得到伪代码
屏幕快照 2017-04-05 下午3.56.21.png
上图我们看到了

r10 = self;
r5 = r10 + *0x33befe8;
r4 = objc_loadWeakRetained(r5);
r8 = @selector(onContactsItemViewRightButtonClick:);
r11 = [r4 respondsToSelector:r8];

可以得出,r11 = [r5 onContactsItemViewRightButtonClick:btn],而 r5 我们判断为 self 的代{过}{滤}理,这个我们也可以通过在之前用 class-dump 的头文件里面搜索onContactsItemViewRightButtonClick,会发现在ContactsItemViewDelegate中。
也就是[ContactsItemView onRightBtnAction]内部调用了[self.delegate onContactsItemViewRightButtonClick:].
ContactsItemViewdelegateSayHelloViewController

再用 hopper 定位onContactsItemViewRightButtonClick

屏幕快照 2017-04-05 下午4.05.49.png
屏幕快照 2017-04-05 下午4.14.09.png

看到这里估计会很蒙不知道从何下手。这时候只要加以推测就可以了。
上图中进行了两个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 isKindOfClass:[CPushContact class]]);
而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:方法。主要的部分如下所示。

Paste_Image.png

通过分析,我们可以得到,确认好友申请,显示构造了CContactVerifyLogic对象。再构造了一个CVerifyContactWrap对象,并设置了相关属性,比如m_nsUsrName m_uiScene m_nsTicket.然后通过添加到数组中,通过CContactVerifyLogic对象的startWithVerifyContactWrap:opCode:parentView:fromChatRoom:方法发送。
代码如下:

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

这样我们就得到了 获取好友请求的方法与添加好友的方法。
而这里还有一个问题,就是添加好友的对象是CPushContact,而获得好友请求的对象的CMessageWrap。这里需要进行转换,而转换的方法也在SayHelloViewController中,可以重复上面的分析方法获得。

四、编写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分析。因此可能在过程中,有些知识没有漏掉,希望大家可以指出。

六、参考

iOS应用逆向工程 第2版
移动App入侵与逆向破解技术-iOS篇

免费评分

参与人数 193吾爱币 +191 热心值 +185 收起 理由
weijie27 + 1 + 1 谢谢@Thanks!
浮梁买茶去 + 1 + 1 可怕,我还是自己去点同意吧……
又木_jun + 1 我很赞同!
wjpaizzy + 1 + 1 我很赞同!
cgp1011 + 1 + 1 我很赞同!
Archture + 1 + 1 用心讨论,共获提升!
庞海洋 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
18759069860 + 1 + 1 谢谢@Thanks!
fr33m4n + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
h1mcraft + 1 + 1 谢谢@Thanks!
fengyi521 + 1 + 1 我很赞同!
qqwwerty12 + 1 + 1 热心回复!
LIAOPU + 1 用心讨论,共获提升!
weijinming1994 + 1 我很赞同!
fungus + 1 谢谢@Thanks!
weiduanwei + 1 用心讨论,共获提升!
huangyiyi + 1 + 1 我很赞同!
wushaominkk + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lyl123 + 1 + 1 我很赞同!
猫KsWeb点Cc + 1 + 1 我很赞同!
luckystudio + 1 + 1 感谢!您能看下我的求助吗?iphone被盗收到诈骗网站,请求漏洞
qilelejia + 1 + 1 谢谢@Thanks!
oilbit + 1 + 1 我很赞同!
searchjack + 1 + 1 我很赞同!
xxfx007 + 1 + 1 谢谢@Thanks!
bugsongdou + 1 + 1 我很赞同!
zxq19910508 + 1 我很赞同!
szfans + 1 + 1 谢谢@Thanks!
maoxiaosen + 1 + 1 我很赞同!
半妖ing + 1 + 1 热心回复!
d_apple + 1 + 1 热心回复!
tw368258 + 1 + 1 热心回复!
Mint_Grass + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
有你真好 + 1 + 1 我很赞同!
间望 + 1 + 1 用心讨论,共获提升!
sunnylds7 + 1 + 1 用心讨论,共获提升!
liufulong1313 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
11465 + 1 + 1 用心讨论,共获提升!
Maxle + 1 + 1 我很赞同!
luchaojin38 + 1 用心讨论,共获提升!
_◆鐡钣烧■ + 1 我很赞同!
亂爱 + 1 + 1 用心讨论,共获提升!
zhoubucter + 1 + 1 热心回复!
jodyzyx + 1 + 1 很厉害,不为什么,就是因为我看不懂
花老板 + 1 + 1 热心回复!
面面 + 1 + 1 看不懂路过
音符- + 1 + 1 鼓励转贴优秀软件安全工具和文档!
SueLyon + 1 + 1 用心讨论,共获提升!
小枫丶 + 1 + 1 用心讨论,共获提升!
leung44 + 1 + 1 我很赞同!
Acker + 1 + 1 谢谢@Thanks!
Huggo1995 + 1 + 1 很厉害,不为什么,就是因为我看不懂。
扯蛋 + 1 + 1 膜拜大神!
webmarksman + 1 + 1 谢谢@Thanks!
ldark + 1 + 1 用心讨论,共获提升!
laley + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
EvillenG + 1 + 1 我很赞同!
xiaofengqq + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Monly + 1 + 1 谢谢@Thanks!
sau + 1 + 1 谢谢@Thanks!
helloword121 + 1 + 1 谢谢@Thanks!
昂电工 + 1 + 1 我很赞同!
爷单身1却潇洒 + 1 + 1 谢谢@Thanks!
飞鸽传书 + 1 + 1 用心讨论,共获提升!
mmgglgy + 1 + 1 已答复!
why3316 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
kgdwltao + 1 谢谢@Thanks!
红月落影 + 1 + 1 我很赞同!
crazycannon + 1 + 1 用心讨论,共获提升!
丶丿後宫 + 2 + 1 用心讨论,共获提升!
南宫先生 + 1 + 1 用心讨论,共获提升!
xyuetao + 1 + 1 用心讨论,共获提升!
老道 + 1 + 1 我很赞同!
lamsouls + 1 + 1 谢谢@Thanks!
♂成成の + 1 + 1 收藏备用,谢谢楼主分享
zy1234 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
向码农致敬 + 1 + 1 谢谢@Thanks!
王亦棋 + 1 + 1 谢谢@Thanks!
许我浅笑而安 + 1 + 1 楼主求教这样的帖子是怎么编辑的,在左侧的资料卡里有目录
18692177777 + 1 + 1 虽然看不懂,但是感觉很留比的样子.中国因你而自豪
zhaoling175 + 1 + 1 用心讨论,共获提升!
onacp + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
长情空 + 1 + 1 用心讨论,共获提升!
qongbnb + 1 + 1 技术贴,小白看不懂,求出软件
outlook + 1 + 1 热心回复!
左卫门先生 + 1 + 1 谢谢@Thanks!
52破解☆ + 1 + 1 我很赞同!
吾爱_七哥 + 1 + 1 我很赞同!
long437933622 + 1 + 1 强大,学习了
explorer126 + 2 + 1 热心回复!
1983_qb + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
骨密度 + 1 用心讨论,共获提升!
xiaohang99 + 2 + 1 谢谢@Thanks!
书写寂伤 + 1 + 1 不明觉厉
lmkiwwx + 1 + 1 我很赞同!
gamingnow + 1 + 1 用心讨论,共获提升!
Gfer + 1 + 1 谢谢分享,但是实测72小时内被封号怎么破
ghstar + 1 + 1 谢谢@Thanks!
704357815 + 2 + 1 热心回复!
卟经意 + 1 谢谢分享了 外行人看不明白,外行人问 能出个软件或者APP就更好了

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
rudder 发表于 2017-9-23 14:53 来自手机
TKkk 发表于 2017-9-8 09:30
不越狱可以,我发了个app文件到百度云,然而还是需要重新签名成ipa文件才可以安装,需要的工具有macBook ...

楼主我想请问下我的越狱了可以安装吗?我直接下载百度云里面的app就可以了吗?
推荐
ShawnJi 发表于 2017-10-14 11:55
大神你好,看到你逆向的微信自动同意好友请求的博客,参照你的思路来分析自动加好友,现在已经可以实现自动加好友,只是现在id  wrap = [[%c(CVerifyContactWrap) alloc] init];,[wrap setM_oVerifyContact:addContact];这个addContact我是用的ContactInfoViewController的m_contact赋值过来调用的,然后我就去分析m_contact的set方法,在hopper当中分析出[[[%c(MMServiceCenter) defaultCenter] getService:[%c(CContactMgr) class]] getContactByName:];这个方法是用来获取m_contact的但是微信号不是好友的话看到的userName是v1_xxxxxxxxxx@stranger这种,然而我用我分析出的方法并不能动态的获取到m_contact,大神有没有好的方法分享一下 啊
沙发
Jonwave 发表于 2017-9-4 17:53
3#
Alfred斯斯 发表于 2017-9-4 17:58
感觉好复杂,还没看明白
4#
lp@li.cm 发表于 2017-9-4 17:59
我只想发言,我没有看懂
5#
caddy 发表于 2017-9-4 18:10
谢谢分享。
6#
兆辉鸿 发表于 2017-9-4 18:29
学习学习,支持支持
7#
forrest888 发表于 2017-9-4 18:39
感觉好复杂,还没看明白
8#
cheninye 发表于 2017-9-4 19:03
大神啊 看了半天一点没明白  哈哈
9#
qwertyui 发表于 2017-9-4 19:08
不错精华啊
10#
屿圪 发表于 2017-9-4 19:19
大神  厉害了   666
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 10:19

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表