DianQK / blog-comment

MIT License
0 stars 0 forks source link

TrampolineHook 学习笔记 | DianQK #58

Open DianQK opened 4 years ago

DianQK commented 4 years ago

https://blog.dianqk.org/2020/05/11/trampolinehook-study-notes/

zhangsuya commented 4 years ago

_th_dynamic_page:

_th_entry: 原文中这样的写法 为什么_th_dynamic_page对应的是: .rept 2032 mov x13, lr bl _th_entry; .endr

DianQK commented 4 years ago

@zhangsuya _th_dynamic_page:

_th_entry: 原文中这样的写法 为什么_th_dynamic_page对应的是: .rept 2032 mov x13, lr bl _th_entry; .endr

文章中 _th_dynamic_page: 放到底下是为了说明 .rept 部分是生成的动态页。但似乎会提高理解难度,是我写错了。晚些时候更正,感谢提醒。 PS. 写到底下也是可以正常运行的,似乎是 vm_remap 做了页对齐修正,结果会正常映射到设计的第二页起始地址。

DianQK commented 4 years ago

@zhangsuya _th_dynamic_page:

_th_entry: 原文中这样的写法 为什么_th_dynamic_page对应的是: .rept 2032 mov x13, lr bl _th_entry; .endr

图片、代码已更新,另外增加了标签的介绍。 PS. 网站应用了 PWA,点击右下角的刷新可能才能看到,对此我很后悔看着新鲜的技术就无脑用了。否则一个简单的浏览器刷新就可以看到更新了。

zhangsuya commented 4 years ago

给汇编代码加个注释😊

#if defined(__arm64__)

.text
.align 14
.globl _th_dynamic_page
//dataPage
interceptor:
.quad 0

.align 14
// codePage
_th_dynamic_page:

_th_entry:

nop
nop
nop
nop
nop

sub x12, lr,   #0x8
sub x12, x12,  #0x4000
mov lr,  x13 // 恢复 lr 恢复后的 lr 是返回的地址

ldr x10, [x12] // x10 保存的是原 imp
// q 寄存器入栈
stp q0,  q1,   [sp, #-32]!
stp q2,  q3,   [sp, #-32]!
stp q4,  q5,   [sp, #-32]!
stp q6,  q7,   [sp, #-32]!
// lr 和 x 寄存器入栈
stp lr,  x10,  [sp, #-16]!
stp x0,  x1,   [sp, #-16]!
stp x2,  x3,   [sp, #-16]!
stp x4,  x5,   [sp, #-16]!
stp x6,  x7,   [sp, #-16]!
str x8,        [sp, #-16]!

ldr x8,  interceptor // interceptor 是自定义 IMP 这里是 static void MTMainThreadChecker(id obj, SEL selector)
blr x8 // 跳转到自定义 IMP 执行 也就是 MTMainThreadChecker
// 恢复lr和x寄存器
ldr x8,        [sp], #16
ldp x6,  x7,   [sp], #16
ldp x4,  x5,   [sp], #16
ldp x2,  x3,   [sp], #16
ldp x0,  x1,   [sp], #16
ldp lr,  x10,  [sp], #16
// 恢复 q 寄存器
ldp q6,  q7,   [sp], #32
ldp q4,  q5,   [sp], #32
ldp q2,  q3,   [sp], #32
ldp q0,  q1,   [sp], #32

br  x10 // x10 保存的是原 imp 执行原 imp

.rept 2032 // 对应 codePage 的 jumpInstructions[slot] 一个 codePage 可以支持 2032 个 IMP 替换
mov x13, lr // 这是替换的新 IMP 地址,此时 lr 也是返回的地址,需要保存下来 lr 存入寄存器 x13 方便 _th_entry 使用
bl _th_entry;
.endr

#endif
zty0 commented 4 years ago

文中这段:[sp], #16 ;从 sp 地址取值,取值完后在把 sp 向高地址偏移 -16 字节,即释放一些栈空间 是不是写错了?出栈不应该是对sp做加法操作么?

zty0 commented 4 years ago

此外关于.align指令的那段也有没看明白的地方,我理解的align指令是将下一个指令的地址对齐到2^m整数倍的地方,align 2048就是把下一个指令对齐到后三位是800的地址上,可是反过来知道下一个指令的地址,就一定能计算出align指令前的那条指令的地址吗?读到文章中这一段的时候感到十分困惑,希望作者能解释一下

DianQK commented 4 years ago

文中这段:[sp], #16 ;从 sp 地址取值,取值完后在把 sp 向高地址偏移 -16 字节,即释放一些栈空间 是不是写错了?出栈不应该是对sp做加法操作么?

😭写顺手了,应该是 +16 字节。

DianQK commented 4 years ago

此外关于.align指令的那段也有没看明白的地方,我理解的align指令是将下一个指令的地址对齐到2^m整数倍的地方,align 2048就是把下一个指令对齐到后三位是800的地址上,可是反过来知道下一个指令的地址,就一定能计算出align指令前的那条指令的地址吗?读到文章中这一段的时候感到十分困惑,希望作者能解释一下

.align 伪指令前的地址做不到,但有两个 .align 的伪指令搭配就不一样了,参见: 在本文中,会有一个妙用点,我们在 func_1 加入 .align 10: 可以看到 0x8800 - 0x8400 = 0x400,0x400 刚好是 2^10,这说明我只要知道 func_2ret 指令内存地址,就可以得到 func_1ret 指令地址。

zty0 commented 4 years ago

此外关于.align指令的那段也有没看明白的地方,我理解的align指令是将下一个指令的地址对齐到2^m整数倍的地方,align 2048就是把下一个指令对齐到后三位是800的地址上,可是反过来知道下一个指令的地址,就一定能计算出align指令前的那条指令的地址吗?读到文章中这一段的时候感到十分困惑,希望作者能解释一下

.align 伪指令前的地址做不到,但有两个 .align 的伪指令搭配就不一样了,参见: 在本文中,会有一个妙用点,我们在 func_1 加入 .align 10: 可以看到 0x8800 - 0x8400 = 0x400,0x400 刚好是 2^10,这说明我只要知道 func_2ret 指令内存地址,就可以得到 func_1ret 指令地址。

嗯 这个我是可以理解的,我的意思是,这个图片里的代码让我感到困惑,源码中是先使用一个align指令将下一条指令的地址对齐到2^14整数倍的地址上,也就是64位系统虚拟内存一个page的起始位置,然后再用一个align指令再将下一条指令对齐到下一个page的起始位置。但是你这个图里align 2048我不知道该如何理解,只看图的话,应该指的是将下一条指令对齐到2^11整数倍的地址上。。。

DianQK commented 4 years ago

嗯 这个我是可以理解的,我的意思是,这个图片里的代码让我感到困惑,源码中是先使用一个align指令将下一条指令的地址对齐到2^14整数倍的地址上,也就是64位系统虚拟内存一个page的起始位置,然后再用一个align指令再将下一条指令对齐到下一个page的起始位置。但是你这个图里align 2048我不知道该如何理解,只看图的话,应该指的是将下一条指令对齐到2^11整数倍的地址上。。。

图片上似乎漏了点内容:

0000000100008044         align      1024

        ; ================ B E G I N N I N G   O F   P R O C E D U R E ================

                     func_1:
0000000100008400         ret
                        ; endp
0000000100008404         align      2048

        ; ================ B E G I N N I N G   O F   P R O C E D U R E ================

                     func_2:
0000000100008800         ret
                        ; endp

代码对应:

.align 10
_func_1:
ret
.align 10
func_2:
ret

图片的内容是 Hopper Disassembler 生成的,所以这个 align 2048 的含义目前我也不太清楚。

zty0 commented 4 years ago

嗯 这个我是可以理解的,我的意思是,这个图片里的代码让我感到困惑,源码中是先使用一个align指令将下一条指令的地址对齐到2^14整数倍的地址上,也就是64位系统虚拟内存一个page的起始位置,然后再用一个align指令再将下一条指令对齐到下一个page的起始位置。但是你这个图里align 2048我不知道该如何理解,只看图的话,应该指的是将下一条指令对齐到2^11整数倍的地址上。。。

图片上似乎漏了点内容:

0000000100008044         align      1024

        ; ================ B E G I N N I N G   O F   P R O C E D U R E ================

                     func_1:
0000000100008400         ret
                        ; endp
0000000100008404         align      2048

        ; ================ B E G I N N I N G   O F   P R O C E D U R E ================

                     func_2:
0000000100008800         ret
                        ; endp

代码对应:

.align 10
_func_1:
ret
.align 10
func_2:
ret

图片的内容是 Hopper Disassembler 生成的,所以这个 align 2048 的含义目前我也不太清楚。

这样就能理解了,align 2048在这里应该和align 1024是效果一样的,都是对齐到下一个2^10整数倍的地址上