一、背景
经过之前对 iOS 逆向的初步了解,想了个实现 TikTok 自动播放下一个视频的小需求实践一下。
二、实现过程
1、使用 class-dump 工具获取类信息
class-dump 工具通过解析 MachO 文件生成类信息,包括 OC 方法、属性、成员变量等。
有几个点需要留意:
- C 语言函数无法 dump;
- OC 方法的参数如果是对象类型,则只会显示 id;
- dump 出来的 OC 方法包含了 .h .m 文件里面的。
2、通过视图堆栈找出对应文件
从视图堆栈里面可以很方便找出播放器相关的文件,从 class-dump 出来的文件中找到相关文件,在文件中找出相关方法。
比如我需要实现自动播放下一个视频的话,分为两个步骤:1.监听播放完一个视频的事件;2.播放下一个视频。
找到“播放下一个视频”的方法:
- 我从视图堆栈里定位到
AWEFeedTableViewController
类; - 从 class-dump 出来的文件中打开
AWEFeedTableViewController.h
; - 在文件中搜索
NextVideo
,很容易可以找到- (void)scrollToNextVideo;
方法。
类似的方法找出“播放完一个视频的事件”。
3、快速验证
从上一步找到的类还有对应方法是否真的可以实现“播放下一个视频”呢?我们可以在代码中 Hook 对应方法验证,但是这样验证的方法比较低效。
使用 Cycript 可以动态调试 App,这里简单介绍如何通过 Cycript 快速验证:
- 越狱手机上通过 Cydia 安装 Cycript;
- 通过 SSH 连接手机;
- 找到进程:
root# ps -e | grep 'TikTok'
; - 依附到进程:
cycript -p 进程号
; - 打印视图堆栈,输入命令:
UIApp.keyWindow.recursiveDescription()
; - 找到
AWEFeedTableViewController
内存地址并执行[#0x1118da200 scrollToNextVideo]
(内存地址前需要加 # 号)
此时发现 App 真的切换到了下一个视频,证明这个方法就是我们需要找的方法。
4、实现
CHDeclareClass(AWEAwemePlayVideoViewController)
CHDeclareClass(AWEFeedTableViewController)
CHOptimizedMethod1(self, void, AWEAwemePlayVideoViewController, playerWillLoopPlaying, id, arg1) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"DSScrollToNextVideo" object:nil];
CHSuper1(AWEAwemePlayVideoViewController, playerWillLoopPlaying, arg1);
}
CHOptimizedMethod0(self, void, AWEFeedTableViewController, _addNotifications) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scrollToNextVideo) name:@"DSScrollToNextVideo" object:nil];
CHSuper0(AWEFeedTableViewController, _addNotifications);
}
CHConstructor {
CHLoadLateClass(AWEAwemePlayVideoViewController);
CHLoadLateClass(AWEFeedTableViewController);
CHHook1(AWEAwemePlayVideoViewController, playerWillLoopPlaying);
CHHook0(AWEFeedTableViewController, _addNotifications);
}
5、优化
编译运行后即可以实现自动播放下一个视频了,但是还存在一些问题,比如短视频列表中可能存在广告、直播,这两个场景就不会触发“播放完一个视频的事件”,但是我们也可以使用类似的方法去解决。