android inline hook 学习笔记

来源:互联网 发布:太原软件 编辑:程序博客网 时间:2024/05/02 02:58

hook种类

  • GOT表hook,通过更改GOT表offset来实现hook
  • inline hook,即内部跳转hook,替换函数开始处的地址为跳转指令,跳转到hook函数

    比较而言,
    1.GOT表对于本so文件中不经过GOT表
    2.dlsym来调用的函数不经过GOT表

android inline hook

难点
- ARM模式和Thumb存在区别,不像x86,需要区分处理.
- 跳转指令如何构造
- 替换函数的逻辑
- 指令修改之后如何修正

ARM和thumb的区别

ARM在V4之前没有THUMB指令,V4时无法切换,到V5开始可通过BX和BLX进行切换,而V6版本增加了THUMB2指令. THUMB使用2个字节,而THUMB2指令使用4个字节,ARM指令也是使用4个字节.

跳转指令构造

  • 通过跳转指令进行跳转,比如有B,BL,BX和BLX
  • 通过改写PC寄存器进行跳转

ARM的B和BL指令格式

B格式:
31——–28|27——–24|23———————————-0
—-条件—–|1–0—1—-0|———— 24位立即数

BL格式:
31———28|27——–24|23———————————0
—-条件——|1–0—1—-0|———— 24位立即数

1.由于ARM指令4位对齐,低两位为0,再除去符号位,所以可表示的跳转地址为2^(24+2-1) = 土32M 范围.
2,imm24_offset = ((destAddr - (curAddr + 8) >> 2)) & 0x00ffffff
3.destAddr = curAddr + 8 + (SignExtend(imm24_offset) << 2)
后两条为计算公式,用于计算偏移和目标地址

ARM LDR写PC寄存器指令

格式:
31——-28|27-26-25|24|23|22|21|20|19|18|17|16|15——–12|11——————————0|
—-条件—-|0—1—0—|-P-|-U|0-|W–|1–|-1—1—-1—1|—–Rt——–|——-12位立即数———

1.通过LDR更改PC寄存器可以实现任意地址跳转
2,offset大小为土4k
3.符号位U通过23位数值指定

Thumb B指令

B系列有4种格式,这里不再给出,也没有太大作用,总结来说,Thumb B的四种,T1, T2, T3, T4四种格式都达不到我们要求的跳转范围(4GB)

Thumb LDR写PC寄存器

T1格式无法达到任意地址跳转,T2可以达到.

总结

选择指令需要考虑:
1.兼容性,ARM和THUMB1 THUMB2下尽量都可以使用
2.指令代价最小,尽量更改最少的代码
3.尽量不更改原始寄存器,否则对后续逻辑造成影响

由此,实现可以采用:
1.ARM指令,通过LDR PC,[PC, #OFFSET]实现跳转,通过本跳转指令和后续跳转地址,共8个字节即可以跳转
2,THUMB指令,T1无法实现,T2 LDR同样可以做到

其实最终我们采用的方案是ARM指令,将thumb切换为ARM再进行LDR,这样兼容性更好.

ARM hook实现

更改目标地址为: LDR PC, [下一条指令想对于当前PC的偏移]后跟目的地址,共8字节.

需要注意的地方是,ARM的PC指向当前指令+8的位置,所以下一条的偏移应该为[PC - 4]

Thumb hook实现

通过BX PC指令从Thumb切换到ARM,再根据ARM方式进行hook.

需要注意的地方是
1.BX的目标地址4字节对齐,即为了4字节对齐,BX PC替换后需要增加NOP.
2.原始指令可能有4字节Thumb 2,替换时必须完整替换,不能分割
3.thumb 2指令高5位为11101/11110/11111,最高位F8,F0,E8即为Thumb2.

由于BX PC在THUMB下是两字节,为了4字节对齐,需要增加NOP.

替换函数逻辑

替换的函数需要完成的工作:
1.寄存器入栈
2.执行替换函数代码
3.寄存器出栈
4.执行原始目标被修改前代码
5.跳转到原始目标地址的被修改的下一条代码

指令修正

由于PC被改变,而ARM的一些指令是针对PC进行定位的,所以要对其进行相应的修正.包括:

ARM:
1.B BL BX BLX修正
无法直接使用原始目标地址,需要先计算真正地址.
通过

imm24_offset = ((destAddr - (curAddr + 8) >> 2)) & 0x00ffffff  destAddr = curAddr + 8 + (SignExtend(imm24_offset) << 2)

公式计算得到真实地址再通过LDR跳转回真实地址.
可以将原始地址放在PC+8的位置,在PC+4放上跳转指令,跳都后面,避免数据被当作指令执行.
2.LDR修正
将PC+offset相应的换算后放在PC+8位置,通过同样的手法进行跳转.
3.ADD修正

0 0
原创粉丝点击