
开发者逆向 iGameGod 触摸回放引擎,推出 iOS 触摸合成库 TouchSynth
来源标题:I reverse-engineered how iOS game tweaks fake touches
开发者从 iGameGod 0.8.3 的回放引擎逆向并重新实现了进程内触摸合成方案 TouchSynth:输入屏幕坐标即可生成真实 UITouch 和 UIEvent 对象并投递给对应视图。该库仅作用于所在进程的窗口,无法操控 SpringBoard 或其他应用,也不生成 HID 事件。它已在真机上通过 AutoTap 注入游戏验证,并提供 Swift Package Manager、预编译 dylib 和 Theos 三种集成方式。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
iOS 进程内触摸合成:根据 iGameGod 0.8.3 中的 replay engine 重新实现。只要给它屏幕坐标,它就会创建真实的 UITouch 和 UIEvent 对象,然后把它们投递给该坐标点下的 view。关于原始实现的工作方式,以及本实现与它的差异,详见 docs/REVERSING.md。
范围:它只能触达自己所在进程中的窗口,所以你要么把它链接进你的 app,要么把它注入目标进程。它无法操作 SpringBoard 或其他 app,也不会创建 HID 事件。
状态:它已在真机上跑通,也就是通过下面的 AutoTap 注入到一个游戏中。每次 push 时,GitHub Actions 都会用 Theos 构建它。已确认可用的功能见“已验证内容”。
Examples/AutoTap 是一个基于本库构建的可注入式自动点击器。它让你在屏幕上录制点按和滑动,设置延迟和滑动时长,并循环回放。
从最新 release 下载 AutoTap.dylib,然后用 Sideloadly 注入。安装与用法见 AutoTap README。
Swift Package Manager:用于 Xcode app 或 framework。添加该 package,然后 import TouchSynth:
.package(url: “https://github.com/Gladimore/TouchSynth.git”, from: “1.0.0”)
预构建 dylib:每个 release 都附带 libTouchSynth.dylib,分别针对 arm64 和 arm64e 构建。
Theos:用于 tweak 或独立的 dylib。在此目录运行 make 即可得到 libTouchSynth.dylib,或者把源码加进你自己的 tweak:
MyTweak_FILES += $(wildcard TouchSynth/Sources/TouchSynth/*.m) TouchSynth/Sources/TouchSynth/TSTouchLogic.c MyTweak_CFLAGS += -fobjc-arc -ITouchSynth/Sources/TouchSynth -ITouchSynth/Sources/TouchSynth/include
本库没有 Objective-C category,也没有 +load 方法,并且为其符号加了前缀。它不需要 -ObjC 标志;即使 iGameGod 或你旧版的 TouchSynthesis.dylib 加载在同一进程中,也不会与之冲突。
坐标点使用屏幕坐标(UIScreen.coordinateSpace)。所有调用都可以从任意线程安全发起;非主线程的调用会按顺序排队到主线程执行。
import TouchSynth let synth = TSTouchSynthesizer.shared synth.tap(at: CGPoint(x: 200, y: 400)) synth.swipe(from: CGPoint(x: 200, y: 600), to: CGPoint(x: 200, y: 200), duration: 0.3) { finished in print(“swipe finished: (finished)”) // 手动控制,每个手指一个 identifier synth.touchDown(withIdentifier: 1, at: CGPoint(x: 100, y: 100)) synth.touchMove(withIdentifier: 1, to: CGPoint(x: 150, y: 100)) synth.touchUp(withIdentifier: 1, at: CGPoint(x: 150, y: 100)) synth.cancelAllTouches()
#import “TouchSynth.h” [TSTouchSynthesizer.sharedSynthesizer tapAtPoint:CGPointMake(200, 400)];
// C,供引擎和 FFI 使用 TSTap(200, 400); TSSwipe(200, 600, 200, 200, 0.3); TSTouchDown(1, 100, 100); TSTouchUp(1, 100, 100);
上面这些 Swift 名称是 importer 应当从头文件中推导出来的。目前还没有针对它们编译过 Swift,所以如果某个名称无法解析,请在 Xcode 中检查。
若想让你自己的 overlay 不被打扰,设置 synth.excludedView = overlay。它永远不会参与 hit-test,而且在事件分发期间,它的交互会被关闭。
这依赖于 UIKit 的私有细节,所以请先检查它们:
TSTouchSynthesizer.runtimeDiagnostics().forEach { print($0.key, $0.value) } synth.verboseLogging = true
Diagnostic 为 NO 时
含义
event._initWithEvent:touches:
无法构建任何 UIEvent,因此会跳过 sendEvent:。直接投递仍会执行,但 event 为 nil。
touch._tapCount、_locationInWindow、_previousLocationInWindow、_phase、_touchFlags、_timestamp 中的任意一项
无法创建 touch,且 sendEvent 返回 NO。
touch.setWindow: 或 touch.setView:
回退到 _setWindow: / _setView: 风格的 setter,再退回到直接访问原始 ivar,最后回退到 KVC。
投递阶段
这些阶段按顺序执行,deliveryOptions 可以关闭其中任意一个:
可能重复投递:这来自 iGameGod。没有 control 祖先的 view 会同时收到 sendEvent: 和直接的 touches* 调用,前提是假设 sendEvent: 触达不到它。如果某个 view 把每次触摸注册了两次,可以试试 synth.deliveryOptions = TSDeliveryOptions.all.subtracting(.directTouches),或者改为去掉 .sendEvent。对于 Unity 风格的 view,这是首先要改的设置。
多点触控会拆成独立事件:每个 UIEvent 只包含一个 touch,因此一个 view 若通过 event.allTouches 查询两根手指,只会看到一个。
在任意装有 clang 的机器上运行 tools/check.sh <scratch-dir>。
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。