Skip to content

更新说明

Ruikai Liu edited this page Apr 1, 2020 · 3 revisions

ce83f47 更新说明

之前处理hotness_count_禁止JIT编译,只针对目标方法,hook方法如果运行次数多,仍然可能被JIT编译。但如果hook方法中还调用了backup方法,则可能存在编译错误的情况。所以现在对hook方法也禁止JIT编译

而又发现可以通过添加kAccCompileDontBother这个flag,来告诉系统该方法不要编译。相比之前在trampoline中每次清空hotness_count_,这样做更为简洁,所以删除了hotness_count_相关代码。

a929fce 更新说明

主要进行了以下修复和更改:

  1. 解决了Android 8.0上hook失效问题。感谢 @svengong 及其同事的发现和建议,Android 8.0上debug包会强制走解析执行,而release不会存在问题;或者将目标方法改为native属性,目前YAHFA采用了这种方式

  2. 调整了一些方法名称的约定。为避免理解混乱,现在hook插件中定义的方法名改为hook()backup()(可选)。hook()仍然是要替换成的执行内容,backup()则是原方法的备份,其只是作为一个占位,在进行hook时backup()会被覆盖成原方法。

    这里多说一句,如果要调用原方法,直接执行backup()即可,在backup()之前和之后的部分,自然对应于所谓的beforeafter。有些人被Xposed影响的太深,总是想着通过类似于beforeafter的方式来进行hook,殊不知那只是Xposed的封装。

    如果用过Cydia Substrate,自然对YAHFA的这种hook及调用原方法的模式不会感到陌生。

  3. 回退到了之前显式设定cached methods的方式。这是由于以下原因:

    • 该issue及修复说明,必须将原方法整体复制到备份方法中,只修改备份方法的entrypoint跳转回原方法,在某些情况下会由于ToDexPc错乱的问题崩溃

    • 上述修复通过malloc()的方式创建新的ArtMethod,而非定义Java方法,但在垃圾回收时会有问题

    • 为解决上述malloc()的问题,曾经添加一个Java方法来保存原方法的完整备份,但这又会显得很冗余

    • 于是现在是将原方法整体复制到backup()中,但这样就不能在backup()通过trampoline2清除其hotness_count了,所以这部分操作被合并到trampoline1中

    • 由于backup()被整体替换,其方法signature被更改,所以在hook()中首次调用静态的backup()时,会解析失败。为解决该问题,回退到了之前显式设定cached methods的方式,从而绕过了解析静态方法backup()的过程

66397a3 更新说明

显式设定cached methods中的backup(),在高版本系统上会出现找不到backup方法NoSuchMethodError的问题。因为cached methods是一个长度有限的数组,所以设定好的内容可能会被覆盖。

于是改变思路,不再把目标方法全部复制到backup()的结构体中,而是采用类似hook的方式,把backup()的entrypoint替换为trampoline,在其中设置寄存器并跳转回到原始的目标方法执行。不过原始的目标方法结构体中的entrypoint已经被替换为hook()了,所以backup()所使用的trampoline是把入口地址硬编码而非从ArtMethod结构体中读取。

Clone this wiki locally