-
-
[原创]如何写一个Android inline hook框架_新增功能或修复bug_浮点相关的问题
-
发表于:
2020-1-8 12:24
7285
-
[原创]如何写一个Android inline hook框架_新增功能或修复bug_浮点相关的问题
之前的hook框架已经可以满足绝大多数需求,但是设计之初未详细的看完arm64下浮点相关的部分,以为和arm一样也是通过通用寄存器、栈传递,现在修复这一部分,这个bug只对dump读写寄存器相关的部分有影响,对replace部分(采用定义一个和被hook函数原型一致的函数)无影响。
目前来看arm浮点参数,float参数占用一个寄存器或者栈,double占用相邻的两个寄存器或栈;返回值float还是占用寄存器r0,double占用寄存器r0和r1。所以可以不考虑保存浮点寄存器s0-s31/d0-d31/q0-q15。如果有例外情况请告诉我,这些寄存器应该是NEON相关的,所以armv7-a/r以下的应该是不存在这些寄存器和指令的(好像有的资料说armv6也有类似的浮点指令)?
如上图,传参通过r0、r1,返回通过r0。
但是arm64传参使用的是float从s0开始为第一个浮点参数,double从d0开始为第一个浮点参数,返回值float为s0,double为d0,所以应该保存浮点寄存器和提供接口。
如上图,传参通过D0、D1,返回通过D0。
如上图,传参通过S0、S1,返回通过S0。
如上图,传参通过W0、S0、S1,返回通过S0。
按说把浮点寄存器存储在栈的最底部比较好,但是代码改动稍微有点大(其实是偏移都要改一遍),所以放在最顶层吧。
编译器貌似并不支持存储V0-V31,还是像armv7的neon一样使用Q0-Q31(armv7只有Q0-Q15,16个128位的寄存器)。Q0-Q31可以拆成D0-D31,D0占Q0的低64位,D1占Q1的低64位;同时也可以拆成S0-S31,S0占Q0的低32位,S1占Q1的低32位。不清楚为什么这么设计,感觉有些浪费。
为了方便这里定义一个联合体,qregs就是128位的Q0-Q31,dregs为了方便解析double,同理fregs为了方便解析float。
通过这样的方式操作浮点相关的寄存器,完成对double、float参数、返回值的读写。
例如这样操作。
在arm64下很多框架都是采用X16、X17,多是X17寄存器完成跳转,那么简单分析下这个流程:
1、跳板/shellcode类似如下:
2、hook函数内调用原函数,那么执行完备份/修复的几条指令后,还要使用X17跳回被hook的函数。
x16、x17一般只在plt中使用,那么x17一般都是保存的一个函数的地址。
但是上面的步骤2肯定不是跳到函数的起始地址,而是函数起始地址+16(或者更大,看修复指令的情况)。那么根据自身的业务场景在容易被hook的函数内检测X17寄存器的值是不是就是当前函数的地址+(16到32),如果在这个范围内,那么就可以认为当前函数被hook了。实现方式多种多样,例如内嵌汇编获取X17寄存器的值。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)