作为逆向的巩固练习 利用后摄像头获取视频流 实现微信聊天界面的背景透视

18181IMG_0018.PNG

*后置摄像头对着大广州塔*


项目源代码放在了我的Github仓库

1. 概述

前两天逆向了微信实现伪装定位,想着想再实现一个好玩的 trick 作为巩固,然后向下一个阶段推进。自动抢红包,不太感兴趣,并且已经有人实现了;文章阅读界面的的新消息预览,这个倒是我的刚需,不过也有人实现了,留着过段时间自己也实践一遍。最后想来想去,干脆就做一个之前手Q曾经有过的功能吧 —— 聊天页面背景透视,走路聊天防摔。


流程还是那样:砸壳 -> class-dump -> Hopper 反编译 -> 定位想要 hook 住的类以及函数 -> 编写 tweak。砸壳跟 class-dump 之前已经实践过了,这里就不再废话,直接从定位 hook 点开始。

2. hook 点定位

这里有个小建议,可以将系统的语言改成英文,程序员都知道,功能的英文名称一般跟工程中的类名相近,这样可以帮助我们更加快速地定位到相对应的类。例如微信中附近的人对应的英文名称为 People Nearby,而实际上源文件名称也包含了这个关键字。

2.1 Reveal 分析

对于聊天详情页面,没有地方可以看到对应的“功能英文名”,于是我们借助利器“Reveal”,注入 Reveal 之后(注入的方法在上一篇伪装微信定位的文章有提到),来分析一下微信的界面,这个过程如褪去少女轻薄衣裳般让我兴奋:
18347views.png
进入聊天详情页,在视图层级中选中 controller 对应的 view,然后右侧的 Identify Inspector 中可以看到它对应的 controller:
43768inspector.png
79113class_name.png
一下子就定位到了我们需要 hook 的类了。

2.2 hook 方法猜想

先大致分析一下我们需要实现的功能:

  1. 聊天详情页背景替换成后置摄像头的实时图像
  2. NavigationBar 右方增加一个按钮控制透视的开关

易证,我们需要在下面这些函数里面做 hook:

  • **viewWillAppear: **添加控制按钮,在 viewDidLoad 中第二次进入时会失效,原因暂时未想明白
  • **viewDidAppear: **一个小优化:让进入详情页时透视的开启状况与上一次一致
  • **viewWillDisappear: **如果是要退出详情页,就把透视关闭,同时释放相关的资源
  • **willRotateToInterfaceOrientation: **页面旋转会导致 previewer 布局异常,因此当页面即将旋转时需要停止 previewer,旋转完成之后再次开启。这里微信仍然使用的是 desperated 的旧方法,并没有使用苹果的建议,这点可以通过 class-dump 出的头文件或者 hopper 反编译可以知道
  • **didRotateFromInterfaceOrientation: **同上

代码就不贴了,没什么意思,要看源码可以到 Github 上查看

3. Theos

Theos 的工程中我使用了一个 Manager 来为我管理 AVFoundation 相关的操作,需要在 Makefile 中为它指定 arc 特性(更详细的 logos 语法可以在 wiki 中找到):

1
AVManager.m_CFLAGS = -fobjc-arc

完整的 Makefile 文件贴一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
THEOS_DEVICE_IP = 192.168.0.137
ARCH = arm64
TARGET = iphone:9.3

include $(THEOS)/makefiles/common.mk

TWEAK_NAME = WeTransparentChat
WeTransparentChat_FILES = Tweak.xm AVManager.m
WeTransparentChat_FRAMEWORKS = UIKit AVFoundation
AVManager.m_CFLAGS = -fobjc-arc

include $(THEOS_MAKE_PATH)/tweak.mk

after-install::
install.exec "killall -9 WeChat"

另外有一点也需要注意下,看了很多文章,对 %log 的使用都是直接抄的原书中的描述,不知道是否因为系统差异,原书中提到的 /var/logs/syslog 默认并不存在,需要自己做一些配置,或者直接用另一种的方法来实时获取 syslog。


先到 cydia 中搜索安装 socat 这个插件,socat 也是 linux 上的一个强大的利器,算是 netcat 的替代产品或者加强版,可以在两个流之间机那里一个双向的通道。用下面命令实时获取 syslog:

1
socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
1
> watch

然后会输出一堆有的没的信息,我们的 %log 数据也会包含在里面,不过目标进程幸好输出的信息在 iTerm 中会高亮。另外我暂时没有找到能够过滤输出的方法,用 * 过滤获取到的貌似是历史数组,并非实时。


最后剩下的事情就是 make package install 的往复循环测试了。