0%

Magisk注入app并嵌入imgui

之前我在 52 上发了一个帖,Android 几种特殊绘制方框方法,其中有说到 Hook Surfaceflinger 进程的 eglSwapBuffers 函数.
实际上,在安卓 12 里,Surfaceflinger 进程已经没有 eglSwapBuffers 函数了,而且注入的模板也要改进.
需要关闭 selinux 并且要把 linker 和 libc 的路径分别改为

1
2
/apex/com.android.runtime/bin/linker64
/apex/com.android.runtime/lib64/bionic/libc.so

具体可以看这篇 github
https://github.com/SsageParuders/AndroidPtraceInject

说回正题,既然 Surfaceflinger 进程没有 eglSwapBuffers 函数,那么 eglSwapBuffers 肯定是在 app 内部调用的,直接 hook 了 app 内部 eglSwapBuffers 函数就行.

1
2
3
4
5
6
7
8
9
static void init_dobby()
{
void *sym_eglSwapBuffers = DobbySymbolResolver(NULL, "eglSwapBuffers");
if (NULL != sym_eglSwapBuffers)
{
LOGD("sym_eglSwapBuffers:%llx", (unsigned long long)sym_eglSwapBuffers);
DobbyHook(sym_eglSwapBuffers, (void *)new_eglSwapBuffers, (void **)&ori_eglSwapBuffers);
}
}

我这里选用 Dobby 的 hook 框架,参考了使用 Magisk+riru 实现全局改机的用法.

在 hook 后的 new_eglSwapBuffers 里完成 imgui 的初始化,显示即可。基本上不需要怎么改动 imgui 的代码.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();

// Disable loading/saving of .ini file from disk.
// FIXME: Consider using LoadIniSettingsFromMemory() / SaveIniSettingsToMemory() to save in appropriate location for Android.
io.IniFilename = NULL;

// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();

// Setup Platform/Renderer backends
ImGui_ImplAndroid_Init(nullptr);
ImGui_ImplOpenGL3_Init("#version 300 es");
g_Initialized = true;
.......

之后用 Zygisk-ModuleTemplate 模板编译,magisk 安装就行.

不足之处:

1. 由于和游戏共用 surface, 如果绘制异常游戏直接闪退.
2. 进行复杂绘制的时候会卡游戏画面,降低帧率.
3. 兼容性差,不支持大部分的 ue4 引擎的游戏.

完美的内部绘制方案参考
Magisk 注入 app 并嵌入 imgui (二)

最后效果如图