日志分析
典型的NE问题,而且该crash集中在 <=android9 的版本上,可以粗估一下该问题属于系统bug,在android10上得到了官方修复
一般碰到这种疑似系统bug的,可以去issueTracker里 搜索一下关键字 issue
堆栈分析
这里看ne的crash 可以推测出,是libhwui.so 这个库发生了异常,关键就是看 在哪里挂掉的 根据函数的信息可以得出
调用链路是 libhwui.so 调用了 libegl.so中的某个关键函数 挂掉了
到这里其实就有希望解决了, plt-hook 方案是较为适合这种场景的
源码分析
hwui 这个so中 在某种情况下 会抛出fatal异常,其实就是create了一个空的surface
这里其实就是返回值是个null,写法比较绕
#define EGL_NO_SURFACE EGL_CAST(EGLSurface,0)
#define EGL_CAST(type, value) (static_cast<type>(value))
到这里解决思路就有了, 可以hook eglCreateWindowSurface这个函数, 发现他是null的时候 就修改一下返回值 为我们自己写死的一个地址值, 这样至少不会让他走进fatal 异常里
另外因为我们是写死的一个地址值,这里eglSurfaceAttrib 函数也要hook,判断第二个参数值为我们的地址值时 就直接返回,否则可能会引发其他故障
android10的修复代码如下
关键代码
// 创建虚假地址 来欺骗 低版本的 eglSurfaceAttrib
static void *getFakeAddr() {
if (fakeAddr == NULL) {
fakeAddr = malloc(1);
}
return fakeAddr;
}
static void *hacker_eglCreateWindowSurface_automatic(void *a, void *b, void *c, const void *d) {
BYTEHOOK_STACK_SCOPE();
void *ret = BYTEHOOK_CALL_PREV(hacker_eglCreateWindowSurface_automatic, a, b, c, d);
if (ret == NULL) {
ret = getFakeAddr();
}
return ret;
}
static void *hacker_eglSurfaceAttrib_automatic(void *a, void *b, void *c, void *d) {
BYTEHOOK_STACK_SCOPE();
// 如果是虚假地址,直接返回
if (b == getFakeAddr()) {
return (void *) 1;
}
return BYTEHOOK_CALL_PREV(hacker_eglSurfaceAttrib_automatic, a, b, c, d);
}
void *k = (void *) hacker_eglCreateWindowSurface_automatic;
void *t = (void *) hacker_eglSurfaceAttrib_automatic;
bytehook_hook_single(
"libhwui.so",
NULL,
"eglCreateWindowSurface",
k,
NULL,
NULL);
bytehook_hook_single(
"libhwui.so",
NULL,
"eglSurfaceAttrib",
t,
NULL,
NULL);