0%

Android外部imgui绘制(二)--补充

前几天看到评论区有个小伙伴问我,ue4 游戏怎么寻找 android_app 和获取系统输入.
我在这说一下.

获取 android_app

基址偏移法

首先,需要找到 libUE4.so 的 android_main 函数.
android_main
ida 进入 android_main 函数后按 F5,
ida_f5
可以发现有一个全局变量保存了这个 android_app 变量.
那么它的地址就是

1
libUE4.so(基址)+A36E1D0

注入 Hook 法 (Magisk 注入 app 并嵌入 imgui)

参考了 Unity 全自动 hook 的实现
hook_each 等代码可以在这里找到:
https://github.com/kotori2/riru_unity_example.

直接 Hook libUE4.so 的 android_main 函数拿到 android_app 变量.
1.Hook dl_open.

1
2
void *loader_dlopen = DobbySymbolResolver(nullptr, "__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv");
hook_each((unsigned long)loader_dlopen, (void *)dlopen_, (void **)&dlopen_backup);

2. 在 dl_open 里拿到 libUE4.so 句柄并调用 dlsym 拿到 android_main 函数地址,然后 Hook android_main.

1
2
3
4
5
6
if (strstr(name, "libUE4.so"))
{
ue4_handle = handle;
LOGI("Got libUE4.so handle at %lx", (long)ue4_handle);
hook_each((unsigned long)dlsym(ue4_handle, "android_main"), (void *)new_android_main, (void **)&ori_android_main);
}

3. 在 Hook 后的 android_main 里保存 android_app.

1
2
3
4
5
6
7
8
9
10
11
void new_android_main(struct android_app *app)
{
// LOGD("new_android_main");
g_App = app; //这个g_App是一个全局变量,保存android_app.
if (NULL == ori_android_main)
{
LOGD("failed to get original android_main");
return;
}
return ori_android_main(app);
};

获取输入

先将原 android_app 的 onInputEvent 保存,然后替换为自己的 onInputEvent.

1
2
3
ori_onInputEvent = decltype(ori_onInputEvent)(g_App->onInputEvent);
LOGD("ori_onInputEvent:%llx", (long long)ori_onInputEvent);
g_App->onInputEvent = onInputEvent;

然后自己的 onInputEvent 就可以打印输入事件了.

1
2
3
4
5
6
7
int32_t onInputEvent(struct android_app *app, AInputEvent *inputEvent)
{
LOGD("onInputEvent");
int32_t event_action = AMotionEvent_getAction(inputEvent);
LOGD("event_action:%d", event_action);
return ori_onInputEvent(app, inputEvent);
}

log