修改真机debuggable值
使用RenderDoc在真机环境进行调试,需要项目:debuggable=true。除了每个apk中指定的debuggable外,这个值还可以在系统中全局指定。换句话说,只要把系统值设为true,那么不管apk是什么值都可以被调试了。
Ps:Android 真机环境需要进行Root,并且解锁System分区
方案一:使用mprop工具
mprop 工具,是安卓8及以下修改debuggable为1的方案
使用方法,通过adb命令修改:
-adb push (mprop文件路径) /data/local/tmp
-adb shell su
-chmod 755 /data/local/tmp/mprop
-data/local/tmp/mprop debuggable 1
-stop;start
重启之后,使用adb命令查看debuggable的值:
-adb shell su
-getprop ro.debuggable
若值为1 ,则修改成功。
方案二:使用Magisk工具
Magisk(面具),是安卓8以上修改debuggable为1的方案。
Magisk下载:https://github.com/topjohnwu/Magisk
Magisk安装:https://sspai.com/post/53043
在设置—应用管理—授权管理—root权限中授权给magisk
在Magisk中安装MagiskHide Props Config模块
通过adb命令行修改
-adb shell su
-props
-3 (-Edit MagiskHide props)
-1 (-ro.debuggable)
重启之后,使用adb命令查看debuggable的值:
-adb shell su
-getprop ro.debuggable
若值为1 ,则修改成功。
Fake dlopen 加载 renderdoc.so
前一种方案已经适用于很多项目了,但有一些项目会检测运行时额外加载dll的行为,仍然会闪退。所以需要通过其他的方案绕过检测。思路来自:知乎Blog
流程
注入 libOpenNativeLibrary.so 到 zygote(64) 进程中, 此时libOpenNativeLibrary.so 触发onload函数。该函数作用是 Hook libnativeloader 模块内的 OpenNativeLibrary 函数。
游戏运行时会调用OpenNativeLibrary函数打开系统so ,这时位于白名单中的app会执行Hook函数,加载libOpenNativeLibrary.so ,从而达到 RenderDoc 启动时注入libVkLayer_GLES_RenderDoc.so 的效果。
编译renderdoc.so
编译用于加载的Renderdoc.so,其中有部分源码需要修改:
修改通过编译,该部分修改内容可参考:知乎Blog
//=>renderdoc/Core/resource_manager.cpp
.............
FrameRefType ComposeFrameRefsFirstKnown(FrameRefType first, FrameRefType second)
{
=> //if(eFrameRef_Minimum <= first && first <= eFrameRef_Maximum)
if(first <= eFrameRef_Maximum)
return first;
else
return second;
}
//=>renderdoc/Core/resource_manager.h
inline InitReqType InitReq(FrameRefType refType, InitPolicy policy, bool initialized)
{
=>//if(eFrameRef_Minimum > refType || refType > eFrameRef_Maximum)
if(refType > eFrameRef_Maximum)
return eInitReq_Copy;
修改模块名称:
//=>renderdoc/Common/globalconfig.h
//#define RENDERDOC_ANDROID_LIBRARY "libVkLayer_GLES_RenderDoc.so"
#define RENDERDOC_ANDROID_LIBRARY "libvkEGL.so"
//CMakeLists.txt
set_target_properties(renderdoc PROPERTIES LINK_FLAGS "${RDOC_LINK_FLAGS}")
# rename output library
set_target_properties(renderdoc PROPERTIES OUTPUT_NAME "vkEGL")
编译之后生成文件:libvkEGL.so,该文件在RDC使用时会被加载到应用中。
Hook OpenNativeLibrary
接下来通过Hook OpenNativeLibrary函数的方式加载libvkEGL.so。在这里我们采用 inline hook 框架:
int HookOpenNativeLibrary()
{
LOGD("Hook OpenNativeLibrary");
void* HelperLibraryHandle = NULL;
if ((LibraryHandle = fake_dlopen("libnativeloader.so", RTLD_NOW)) == NULL) {
LOGD("LibraryHandle is null : %s", dlerror());
}
//mi 5x
OpenNativeLibrary = (OpenNativeLibraryFunc)fake_dlsym(LibraryHandle, "_ZN7android17OpenNativeLibraryEP7_JNIEnviPKcP8_jobjectP8_jstring");
//mi 8
if (OpenNativeLibrary == NULL)
{
OpenNativeLibrary = (OpenNativeLibraryFunc)fake_dlsym(LibraryHandle, "_ZN7android17OpenNativeLibraryEP7_JNIEnviPKcP8_jobjectP8_jstringPbPNSt3__112basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEE");
}
LOGD("OpenNativeLibrary is null : %d", OpenNativeLibrary == NULL);
int result = hook((void*)OpenNativeLibrary, (void*)&new_OpenNativeLibrary, (void **)(&old_OpenNativeLibrary));
return result;
}
- 从Android 7.0 开始,Android 系统将阻止应用动态链接非公开NDK库,可以通过开源库:dlfcn_compat,制作fake_dlopen、fake_dlsym函数来获取libnativeloader模块中的OpenNativeLibrary函数地址
- 注意对于不同的手机来说该函数的函数名是不同的,需要将libnativeloader.so去IDA中进行反编译,得到具体的函数名:
编译得到libOpenNativeLibrary.so。
注入方案
注入 libOpenNativeLibrary.so 到 zygote(64) 进程中, zygote(64)进程是Android系统进程,注入完成后,会执行该libOpenNativeLibrary.so的onload函数,从而执行Hook OpenNativeLibrary。这样打开应用程序时就会先进入新定义new_OpenNativeLibrary函数,该函数会加载libvkEGL.so,进而完成RDC的启动。
- 安卓7及以下
参考注入方案:https://github.com/mustime/Adrill/blob/main/README.zh-CN.md
adb 命令:
adb shell
su
adrill --pname zygote/zygote64 --libpath libOpenNativeLibrary.so
(注意使用具体位置)
注入成功会有相关提示
例如,米8:
/data/RDC/lib64/adrill_arm64-v8a --pname zygote64 --libpath /data/RDC/lib64/libOpenNativeLibrary.so
- 安卓8及以上
参考注入方案:https://github.com/Chainfire/inject-hook-cflumen
adb命令:
adb shell
su
inject (pid of zygote64) libOpenNativeLibrary.so
(注意使用具体位置和具体进程号)
注入成功会有相关提示
【adb shell ps】
例如,米8:
/data/RDC/lib64/inject 652 /data/RDC/lib64/libOpenNativeLibrary.so
PS:有时候此方案会失败,需要先运行以下安卓7的方案,再运行此方案即可
白名单维护
Hook代码中,会去检查位于/data/RDC/renderdoc.cfg文件中的具体包名,在名单中的程序,会在启动的时候执行Hook,加载libvkEGL.so