RenderDoc 学习使用(二):Android平台真机环境下对特殊项目进行截帧分析

修改真机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

posted @ 2023-01-12 11:41  VestLee  阅读(1913)  评论(0编辑  收藏  举报