吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2299|回复: 2
收起左侧

[会员申请] 会员申请ID:花落人断肠

[复制链接]
吾爱游客  发表于 2021-2-20 16:53
1.申请ID:花落人断肠2.个人邮箱:chacewan@163.com3.在论坛潜水这么多年,每次都错过开发注册的时间,这次静下心来做一个wx获取朋友圈数据的ios小逆向案例,给朋友们提供一个思路。开始App Configurator 2 中导出 wx frIDA-ios-dump 脱壳class-dump 导出 headerMonkeyDev 创建项目。

分析首先,朋友圈的数据分析当然是从朋友圈的UI开始分析是最好的,使用Reveal很快能定位到朋友圈是WCTimeLineViewController,通过导出头文件可以找到WCTimeLineViewController.h从图中可以看到WCTimeLineViewController中有实现tableViewDelegate代{过}{滤}理:[img]blob:https://www.52pojie.cn/c0e43b04-d6c0-4ad3-abe8-2f1bf9fd5f90[/img]

此时,感觉就应该要从 UITableView 的数据源入手。Xcode 运行 Debug wx,在朋友圈界面暂停,Console 窗口中打印 WCTimeLineViewController 中猜测有可能是数据源的变量名,简单尝试几个后并没有什么发现。打算反编译程序的逻辑来入手。众所周知,UITableView 一般情况下是使用 tableView:cellForRowAtIndexPath: 设置 Cell 的数据,从这个函数下手,大概率就可以知道数据从哪里来的了。启动 Hopper 导入 wx 二进制文件,搜索 WCTimeLineViewController tableView:cellForRowAtIndexPath: 查看伪代码(截图为关键部分):[WCTimeLineViewController tableView:cellForRowAtIndexPath:] 数据源部分[img]blob:https://www.52pojie.cn/832de635-19b9-4b06-b3b6-2efcffda4919[/img]
观察到函数 getTimelineDataItemOfIndex 很可能是数据来源,通过函数名 DataItem 做为线索,在导出的 Header 中搜索到 WCDataItem,查看 WCDataItem 推测应该就是朋友圈使用的数据结构。根据上下文可知获取数据的方式是:
[Objective-C] 纯文本查看 复制代码
MMContext *context = [MMContext currentContext];WCFacade *facade = [context getService:[WCFacade class]];WCDataItem *dataItem = [facade getTimelineDataItemOfIndex:index];


没想到这么容易就找到数据源了,继续测试:

[Objective-C] 纯文本查看 复制代码
%hook WCTimeLineViewController
- (void)viewDidLoad {    // [font=&quot]读取朋友圈数据[/font]    MMContext *context = [%c(MMContext) currentContext];    WCFacade *facade = [context getService:[%c(WCFacade) class]];    WCDataItem *dataItem = [facade getTimelineDataItemOfIndex:0];    // --- [font=&quot]此处断点[/font] ---          // dataItem [font=&quot]为[/font] nil        %orig();}
%end

运行!进入朋友圈后断点,查看 dataItem 变量,怎么 dataItem nil?再回头看看 Hopper 的代码,看上去似乎没问题啊,这时候尝试继续运行程序,再次暂停程序,控制台打印获取 WCDataItem:
[Objective-C] 纯文本查看 复制代码
(lldb) po [[[MMContext currentContext] getService:[WCFacade class]] getTimelineDataItemOfIndex:0]
Class name: WCDataItem, addr: 0x10e3b8e80tid: xxxxxxxxxxxxxxxusername: xxxxxxxxxxcreatetime: xxxxxxxx...
成功了,发现只能在朋友圈界面加载完之后,才可以获取通过 getTimelineDataItemOfIndex 获取到数据,到底是缺少了哪一步呢?
继续深挖首先,尝试修改代码,将%orig()移动到获取数据之前:
[Objective-C] 纯文本查看 复制代码
%hook WCTimeLineViewController
- (void)viewDidLoad {    %orig();      // [font=&quot]读取朋友圈数据[/font]    MMContext *context = [%c(MMContext) currentContext];    WCFacade *facade = [context getService:[%c(WCFacade) class]];    WCDataItem *dataItem = [facade getTimelineDataItemOfIndex:0];    // --- [font=&quot]此处断点[/font] ---          // dataItem [font=&quot]有数据[/font]}
%end

再次运行,成功获取数据,由此猜测,在 viewDidLoad 中存在某些代码,是使用 getTimelineDataItemOfIndex 的前提条件。在 Hopper 查看 viewDidLoad 伪代码(代码太长就不贴了),首先搜索 MMContext 关键词,发现只有语言和主题相关内容。再仔细看发现有一个诱人的函数:[img]blob:https://www.52pojie.cn/b5e7826d-9d55-4474-8f66-2b41a05dc951[/img]为了验证 initData 是否是下一步分析的关键,先尝试 hook 它,内部实现为空,这样就相当于不执行 initData 了:
[Objective-C] 纯文本查看 复制代码
%hook WCTimeLineViewController
- (void)initData {}
%end

运行,发现在 initData 不执行任何代码后,朋友圈加载不出数据,这样可以针对它下手了。查看伪代码,发现这里 调用了 WCFacade beginTimeline:[img]blob:https://www.52pojie.cn/23d81a9d-3e65-425c-bb99-3a18e38883c3[/img]beginTimeline加入到initData
[Objective-C] 纯文本查看 复制代码
%hook WCTimeLineViewController
- (void)initData {    MMContext *context = [%c(MMContext) currentContext];    WCFacade *facade = [context getService:[%c(WCFacade) class]];    [facade beginTimeline];}
%end

这时候朋友圈数据又出现了,那么 dataItem nil 仅仅是因为缺少 beginTimeline 吗?在 beginTimeline 之后获取数据试试:
[Objective-C] 纯文本查看 复制代码
%hook WCTimeLineViewController
- (void)initData {MMContext *context = [%c(MMContext) currentContext];WCFacade *facade = [context getService:[%c(WCFacade) class]];[facade beginTimeline];WCDataItem *dataItem = [facade getTimelineDataItemOfIndex:0];// --- [font=&quot]此处断点[/font] ---// dataItem [font=&quot]为[/font] nil}
%end

运行结果 dataItem nil,但朋友圈是能正常显示,推断 beginTimeline 是显示朋友圈的必要但非唯一条件(推断错了,看后面)。只能回到 viewDidLoad 继续探索其他条件。再次检查 viewDidLoad 仅仅从代码函数命名上并没有什么发现,此时只能转战动态调试。
动态调试在这种没头绪的时刻,我想就是动态调试发挥的时候了。打开 Hopper,在 viewDidLoad 中大概找几个位置打上断点,想用于缩小范围来确定是哪个位置执行后, getTimelineDataItemOfIndex 能获取到值:
[Objective-C] 纯文本查看 复制代码
// [font=&quot]输出[/font] ASLR[font=&quot],只需要看[/font] wx [font=&quot]的地址[/font](lldb) im li -o -f
[font=Times]// [/font]打上断点(lldb) br s -a [hopper [font=&quot]中查看的地址[/font]]+[ASLR]
[font=Times]// [/font]执行到断点处再[font=Times] po [/font]获取数据(lldb) po [[[MMContext currentContext] getService:[WCFacade class]] getTimelineDataItemOfIndex:0]


经过几轮断点,发现 getTimelineDataItemOfIndex 的值从 nil 变为有值时所在的位置并不固定,这才发现自己思考的并不全面,此前一直以为的是 beginTimeline 是同步执行,而其实 beginTimeline 是异步的,下一步立刻去获取 getTimelineDataItemOfIndex 时,数据还没有从本地数据库中读取出来(猜测,技术菜,还没有针对 beginTimeline 去深究)。
逆向结果最终,为了检测上一步读取数据是异步的猜想,将 getTimelineDataItemOfIndex 延迟去执行:
[Objective-C] 纯文本查看 复制代码
// [font=&quot]在发现界面显示时获取数据[/font]
@interface FindFriendEntryViewController : UIViewController@end
%hook FindFriendEntryViewController
- (void)viewDidLoad {MMContext *context = [%c(MMContext) currentContext];WCFacade *facade = [context getService:[%c(WCFacade) class]];[facade beginTimeline];[self performSelector:@selector(getDataItem) withObject:nil afterDelay:3];
%orig();}
%new- (void)getDataItem {MMContext *context = [%c(MMContext) currentContext];WCFacade *facade = [context getService:[%c(WCFacade) class]];WCDataItem *dataItem = [facade getTimelineDataItemOfIndex:0];// --- [font=&quot]断点[/font] ---// dataItem [font=&quot]有数据[/font]}
%end

成功!目前只是简单获取到已经加载到本地的数据,并且没有对 beginTimeline(还有 endTimeline)机制深究,在逆向过程中发现会在朋友圈界面的 viewDidLoad 中调用 beginTimelinedealloc 中调用 endTimeline另外如果需要从网络加载需要更深入的挖掘,按自己理解大概是从朋友圈界面逆向出触发请求数据的函数,然后再通过本文的方法读取出来。

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

Hmily 发表于 2021-2-22 10:07
https://iosre.com/t/wx/17841

这是你写的?
呵呵我笑了 发表于 2021-2-22 17:14
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-14 14:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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