上文转载YAHFA作者的原文熟悉了YAHFA的原理,但是由于比较笼统,所以本文针对代码细节,从流程上更加简明的介绍一下YAHFA的做了什么和怎么起效。
开篇前我们区分下方法的命名,防止文中被绕晕:
originMethod:文中指将要hook的方法,即target。
hookMethod:我们自定义的方法,用来替换originMethod,当调用originMethod时,执行我们的hookMethod。
backupMethod:用来备份originMethod的方法,这样一来hookMethod可以通过调用backupMethod来简介调用了originMethod。
根据大家对hook的了解,hook一般都是对目标方法originMethod进行修改替换,换成hookMethod,从而在程序执行到originMethod的时候,变成了执行hookMethod,从而完成了hook,但是有时候我们想在执行了我们自己的hookMethod之后,继续执行原来的originMethod方法,例如我们hook文件读写,为了修改文件路径,所以用我们的hookMethod修改完文件路径后,继续通过originMethod打开新的文件路径,所以这就需要一个数据区或者指针保存原来的originMethod,所以backupMethod来完成这个使命,这样hookMethod执行完之后,调用backupMethod就等于调用了originMethod。
一、YAHFA的主要代码实现
YAHFA的代码实现主要包含以下几部分:
1.把originMethod备份到backupMethod,此部分属于整体替换,即将backupMethod整体被originMethod覆盖掉。
2.originMethod的entry_point_from_jni_指向hookMethod的首地址
3.originMethod的entry_point_from_quick_compiled_code_指向一段汇编指令,汇编指令负责从originMethod的entry_point_from_quick_compiled_code_跳转到hookMethod的entry_point_from_quick_compiled_code_,
本部分只讲做了什么改变,下部分再讲为什么这么做。
1.把originMethod备份到backupMethod
主要代码如下:
void *dexCacheResolvedMethods = (void *)readAddr((void *)((char *)backupMethod+OFFSET_dex_cache_resolved_methods_in_ArtMethod));
int methodIndex = read32((void *)((char *)backupMethod+OFFSET_dex_method_index_in_ArtMethod));
//first update the cached method manually
memcpy((char *)dexCacheResolvedMethods+OFFSET_array_in_PointerArray+pointer_size*methodIndex,
(&backupMethod),
pointer_size);
//then replace the placeholder with original method
memcpy((void *)((char *)backupMethod+OFFSET_ArtMehod_in_Object),
(void *)((char *)originMethod+OFFSET_ArtMehod_in_Object),
ArtMethodSize-OFFSET_ArtMehod_in_Object);
首先要保证backupMethod
方法已经解析完成。在备份之前,手工更新dex_cache_resolved_methods_
数组对应项,确保hookMethod在调用backupMethod
时无需再进行方法解析。什么意思呢,就是如果backupMethod还没有装载到