luckfollowme arm 学习篇 08 - dobby function inline hook

查看 24|回复 0
作者:2016976438   
luckfollowme arm 学习篇 08 - dobby function inline hook
接下来才是真正的进入主题,也是最关键的地方。
查看 dobby inline hook 变化
首先,我们得分析 它在我们 sum 方法做了什么,导致跳转到 fake_sumhook 方法。
又能够通过 orig_sum 执行到原方法。
1.首先我们启动下项目,卡在 没有hook 的地方
adb shell "/data/local/tmp/dobby_test"
输入任意键开始hook...
2.然后用ida pro 先分析一遍没有 hook 时候的字节码


01.png (75.29 KB, 下载次数: 0)
下载附件
2023-5-1 12:28 上传

摘抄出来是这样的,由于之前是分析过了的,您直接看我的注释就可以了
# 开辟局部变量空间
SUB             SP, SP, #0x40
# 取出 a9 a10
LDR             X9, [SP,#0x40]
LDR             X8, [SP,#0x48]
# 将 a1 - a8 放入局部变量中
STR             W0, [SP,#0x3C]
STR             W1, [SP,#0x38]
STR             W2, [SP,#0x34]
STR             W3, [SP,#0x30]
STR             W4, [SP,#0x2C]
STR             W5, [SP,#0x28]
STR             W6, [SP,#0x24]
STR             W7, [SP,#0x20]
STR             X9, [SP,#0x18]
STR             X8, [SP,#0x10]
# sum = a1 + a2 + a3 + a4 + a5 + a6 + a7+ a8
LDR             W8, [SP,#0x3C]
LDR             W9, [SP,#0x38]
ADD             W8, W8, W9
LDR             W9, [SP,#0x34]
ADD             W8, W8, W9
LDR             W9, [SP,#0x30]
ADD             W8, W8, W9
LDR             W9, [SP,#0x2C]
ADD             W8, W8, W9
LDR             W9, [SP,#0x28]
ADD             W8, W8, W9
LDR             W9, [SP,#0x24]
ADD             W8, W8, W9
LDR             W9, [SP,#0x20]
ADD             W8, W8, W9
# 储存 sum 变量
STR             W8, [SP,#0xC]
# sum2 = a9 + a10
LDR             X8, [SP,#0x18]
LDR             X9, [SP,#0x10]
ADD             X8, X8, X9
STR             X8, [SP]
# if (sum > 10)
LDR             W8, [SP,#0xC]
SUBS            W8, W8, #0xA
# if (sum > 10) 条件不成立
B.LE            loc_753EDCE934
# if (sum > 10) 条件成立
B               loc_753EDCE91C
; ---------------------------------------------------------------------------
loc_753EDCE91C
# 读取 并 转换 64 位 的 sum
LDRSW           X8, [SP,#0xC]
# 读取 sum2
LDR             X9, [SP]
# sum + sum2
ADD             X8, X8, X9
# 获取 _global_sum 全局变量
ADRP            X9, #_global_sum@PAGE
# _global_sum = sum + sum2
STR             X8, [X9,#_global_sum@PAGEOFF]
B               loc_753EDCE934
; ---------------------------------------------------------------------------
loc_753EDCE934                          
# 读取 全局变量
ADRP            X8, #_global_sum@PAGE
LDR             X8, [X8,#_global_sum@PAGEOFF]
# 放入 x0 转换 int32
MOV             W0, W8
# 释放局部变量空间
ADD             SP, SP, #0x40 ; '@'
# 返回 x0
RET
接下来我们输入任意键 完成 hook
输入任意键开始hook...
hook sum:0x753edce888
进入到 hook 方法,参数:1,2,3,4,5,6,7,8,10,20
调用 原方法获取的结果:66
sum:66
您在看 ida pro  可能您并不会看到改变,但是您如果在 sum 方法的 0xC 字节后下个断点


02.png (87.19 KB, 下载次数: 0)
下载附件
2023-5-1 12:28 上传

此时您就可以发现到变化了
可以发现它修改了我们的 0XC 个字节。
其余的并没有任何的变化。
所以我们分析下这 12 个字节
11 00 00 90 31 A2 28 91       ADRL            X17, _ZL8fake_sumiiiiiiiimm
20 02 1F D6                   BR              X17
Dobby inline asm 分析
dobby 生成的 ADRL 明显是个伪指令 。 因为他有着 8个 字节的长度 ,ida pro 给我们分析成了符号 _ZL8fake_sumiiiiiiiimm
所以这明显就是将 fake_sum hook 的方法的 地址 赋值给了 X17
后面的BR 是一个绝对跳转。 相较于 B #立即数          绝对跳转指令         BR(branch register)  可以根据寄存器中的地址 跳转到任意地方,寻址更大。
稍微翻译一下就是
# 后期 pc 当前内存对齐的地址
adrp         x17, =当前PC内存对齐地址
# 添加 fake_sum 的偏移
add         x17, x17, #0xa28
# 绝对跳转
BR          X17
fake_sum arrch64
我们通过 ADRL            X17, _ZL8fake_sumiiiiiiiimm 进去看看 fake_sum 生成的汇编指令:
FF 83 01 D1                   SUB             SP, SP, #0x60
FD 7B 05 A9                   STP             X29, X30, [SP,#0x50]
FD 43 01 91                   ADD             X29, SP, #0x50 ; 'P'
A9 0B 40 F9                   LDR             X9, [X29,#0x10]
A8 0F 40 F9                   LDR             X8, [X29,#0x18]
A0 C3 1F B8                   STUR            W0, [X29,#-4]
A1 83 1F B8                   STUR            W1, [X29,#-8]
A2 43 1F B8                   STUR            W2, [X29,#-0xC]
A3 03 1F B8                   STUR            W3, [X29,#-0x10]
A4 C3 1E B8                   STUR            W4, [X29,#-0x14]
A5 83 1E B8                   STUR            W5, [X29,#-0x18]
A6 43 1E B8                   STUR            W6, [X29,#-0x1C]
A7 03 1E B8                   STUR            W7, [X29,#-0x20]
E9 17 00 F9                   STR             X9, [SP,#0x28]
E8 13 00 F9                   STR             X8, [SP,#0x20]
A1 C3 5F B8                   LDUR            W1, [X29,#-4]
A2 83 5F B8                   LDUR            W2, [X29,#-8]
A3 43 5F B8                   LDUR            W3, [X29,#-0xC]
A4 03 5F B8                   LDUR            W4, [X29,#-0x10]
A5 C3 5E B8                   LDUR            W5, [X29,#-0x14]
A6 83 5E B8                   LDUR            W6, [X29,#-0x18]
A7 43 5E B8                   LDUR            W7, [X29,#-0x1C]
AB 03 5E B8                   LDUR            W11, [X29,#-0x20]
EA 17 40 F9                   LDR             X10, [SP,#0x28]
E8 13 40 F9                   LDR             X8, [SP,#0x20]
E9 03 00 91                   MOV             X9, SP
2B 01 00 B9                   STR             W11, [X9]
2A 05 00 F9                   STR             X10, [X9,#8]
28 09 00 F9                   STR             X8, [X9,#0x10]
C0 FF FF 90 00 08 3B 91       ADRL            X0, unk_753EDC6EC2
8B 79 00 94                   BL              unk_753EDED0D0
08 01 00 F0                   ADRP            X8, #_ZL8orig_sumhome.php?mod=space&uid=1953840  ; orig_sum
08 11 47 F9                   LDR             X8, [X8,#_ZL8orig_sum@PAGEOFF] ; orig_sum
A0 C3 5F B8                   LDUR            W0, [X29,#-4]
A1 83 5F B8                   LDUR            W1, [X29,#-8]
A2 43 5F B8                   LDUR            W2, [X29,#-0xC]
A3 03 5F B8                   LDUR            W3, [X29,#-0x10]
A4 C3 5E B8                   LDUR            W4, [X29,#-0x14]
A5 83 5E B8                   LDUR            W5, [X29,#-0x18]
A6 43 5E B8                   LDUR            W6, [X29,#-0x1C]
A7 03 5E B8                   LDUR            W7, [X29,#-0x20]
EB 17 40 F9                   LDR             X11, [SP,#0x28]
E9 13 40 F9                   LDR             X9, [SP,#0x20]
EA 03 00 91                   MOV             X10, SP
4B 01 00 F9                   STR             X11, [X10]
49 05 00 F9                   STR             X9, [X10,#8]
00 01 3F D6                   BLR             X8
E0 1F 00 B9                   STR             W0, [SP,#0x1C]
E1 1F 40 B9                   LDR             W1, [SP,#0x1C]
C0 FF FF 90 00 EC 27 91       ADRL            X0, unk_753EDC69FB
76 79 00 94                   BL              unk_753EDED0D0
E0 1F 40 B9                   LDR             W0, [SP,#0x1C]
FD 7B 45 A9                   LDP             X29, X30, [SP,#0x50]
FF 83 01 91                   ADD             SP, SP, #0x60 ; '`'
C0 03 5F D6                   RET
代码有点多,我们逐步分析,在此之前你先记住 fake_name 方法体内部是啥样子,到时候我们一一对比。
install_hook_name(sum,int, int a1, int a2,int a3,int a4,int a5,int a6,int a7,int a8,uint64_t a9,uint64_t a10){
    printf("进入到 hook 方法,参数:%d,%d,%d,%d,%d,%d,%d,%d,%llu,%llu \n",a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);
    int ret =   orig_sum(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);
    printf("调用 原方法获取的结果:%d\n",ret);
    return ret;
}

首先第一行指令是 SUB             SP, SP, #0x60 表示 局部变量使用的空间
|-60                        
STP
STP (Store Pair) 用于储存一对寄存器到 寄存器中
所以 下面这条指令执行后
STP             X29, X30, [SP,#0x50]
栈应该是这样的:
|-60                        
x29 和 x30 是两个 关键的寄存器。
它们分别代表着 帧指针 FP  和 链接指针 LR
LR 各位肯定是知道的。 FP 按照网上的意思是说 它代表着栈低  SP 代表着栈顶
参数
下面就是传过来的参数 保存在 栈中,只不过要注意的是,它并不是直接使用 SP 而是从  栈的 -10 的地方开始计算。 这样可以很方便获取栈中 a9-a10 的参数
# 从 sp -10 的地方开算
FD 43 01 91                   ADD             X29, SP, #0x50 ; 'P'
# 根据调用约定 x0-x7 额外的参数放入栈中
# 所以 x9 = a10
A9 0B 40 F9                   LDR             X9, [X29,#0x10]
# x8 = a9
A8 0F 40 F9                   LDR             X8, [X29,#0x18]
# stur 貌似是有符号的 str 指令
# 所以下面储存  a1-a8 的参数
A0 C3 1F B8                   STUR            W0, [X29,#-4]
A1 83 1F B8                   STUR            W1, [X29,#-8]
A2 43 1F B8                   STUR            W2, [X29,#-0xC]
A3 03 1F B8                   STUR            W3, [X29,#-0x10]
A4 C3 1E B8                   STUR            W4, [X29,#-0x14]
A5 83 1E B8                   STUR            W5, [X29,#-0x18]
A6 43 1E B8                   STUR            W6, [X29,#-0x1C]
A7 03 1E B8                   STUR            W7, [X29,#-0x20]
# 储存 a10 和 a9
E9 17 00 F9                   STR             X9, [SP,#0x28]
E8 13 00 F9                   STR             X8, [SP,#0x20]
那么现在换算栈中的样子:
|-60                        
调用方法
之前的指令应该都只是对标着传参
int fake_sum(sum,int, int a1, int a2,int a3,int a4,int a5,int a6,int a7,int a8,uint64_t a9,uint64_t a10)
后面的代码是:
printf("进入到 hook 方法,参数:%d,%d,%d,%d,%d,%d,%d,%d,%llu,%llu \n",a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);
来看看对应的 arm
# 首先准备  x1 ~ x7 的参数 也就是 a1,a2,a3,a4,a5,a6,a7
LDUR            W1, [X29,#-4]
LDUR            W2, [X29,#-8]
LDUR            W3, [X29,#-0xC]
LDUR            W4, [X29,#-0x10]
LDUR            W5, [X29,#-0x14]
LDUR            W6, [X29,#-0x18]
LDUR            W7, [X29,#-0x1C]
# x11 = a8
LDUR            W11, [X29,#-0x20]
# 获取 a9 和 a10
LDR             X10, [SP,#0x28]
LDR             X8, [SP,#0x20]
# 获取栈顶 x9 = sp
MOV             X9, SP
# 多余的参数储存在栈中
# [sp] = a8
STR             W11, [X9]
# [sp + 0x8] = a9
STR             X10, [X9,#8]
# [sp + 0x10] = a10
STR             X8, [X9,#0x10]
# 获取 字符串的地址 (进入到 hook 方法,参数...)
ADRL            X0, aHookDDDDDDDDLl     ; "进入到 hook 方法,参数:%d,%d,%d,%d,%d,%d,%d,%d,"...
# 调用 printf 并 记录 LR
BL              printf
此时调用后栈应该变成了:
|-60                a8        
orig_sum
接下来是重点。我们分析下 orig_sum 是如何调用原有的方法。
首先我们看下传参调用的过程:
# 获取 orig_sum 方法地址放入到 x8 中
ADRP            X8, #_ZL8orig_sum@PAGE  ; orig_sum
LDR             X8, [X8,#_ZL8orig_sum@PAGEOFF] ; orig_sum
# 准备 x0-x7 的参数
LDUR            W0, [X29,#-4]
LDUR            W1, [X29,#-8]
LDUR            W2, [X29,#-0xC]
LDUR            W3, [X29,#-0x10]
LDUR            W4, [X29,#-0x14]
LDUR            W5, [X29,#-0x18]
LDUR            W6, [X29,#-0x1C]
LDUR            W7, [X29,#-0x20]
# 其余的参数放入到 栈中
# x11 = a9
LDR             X11, [SP,#0x28]
# x9 = a10
LDR             X9, [SP,#0x20]
# x10 = sp
MOV             X10, SP
# [sp] = a9
STR             X11, [X10]
# [sp + 8] = a10
STR             X9, [X10,#8]
# 调用 orig_sum
BLR             X8
接下来我们进入 orig_sum 看看它做了什么:


03.png (40.39 KB, 下载次数: 0)
下载附件
2023-5-1 12:28 上传

不知道各位熟悉这个代码么?
如果大伙不记得看下面的图, (只看前12个字节)
这个图就是之前 没有hook前 sum方法的图。
由于之前的忘记 按 Q转换 并且没有显示字节码。 但我可以肯定告诉你,它们是一样的
我把 orig_sum 截取出来大伙看看
FF 03 01 D1                   SUB             SP, SP, #0x40 ; '@'
E9 23 40 F9                   LDR             X9, [SP,#0x40]
E8 27 40 F9                   LDR             X8, [SP,#0x48]
                              _753EDCE894
51 00 00 58                   LDR             X17, =0x753EDCE894
20 02 1F D6                   BR              X17
前面12 个字节都好说,就是之前 sum 被替换成 跳转指令之前的样子
下面是目前被替换成的代码:
# 获取 fake_sum 地址 放入 x17
11 00 00 90 31 A2 28 91       ADRL            X17, _ZL8fake_sumiiiiiiiimm
# 绝对地址跳转 到 fake_sum                                       
20 02 1F D6                   BR              X17
那后面的两条指令是跳到哪里呢?
51 00 00 58                   LDR             X17, =0x753EDCE894
20 02 1F D6                   BR              X17
我们在 ida proG 跳转下:


04.png (75.15 KB, 下载次数: 0)
下载附件
2023-5-1 12:28 上传

可以很明显的发现  =0x753EDCE894 地址就是 原来 sum  的 12字节 后面的地方。
那么当执行完 sum 方法后,又如何跳到 我们的 fake_sum 接着往下执行呢?
之前说过 , RET 指令会根据 x30(LR) 链接寄存器的值来跳转。
所以这也是为什么 fake_sum 在调用 orig_sum 的时候 选择了 BLR 指令。
orig_sum 则只使用 BR 指令
下面是摘取的 fake_sumorig_sum 的片段:
# fake_sum 调用 orig_sum 的片段
ADRP            X8, #_ZL8orig_sum@PAGE  ; orig_sum
LDR             X8, [X8,#_ZL8orig_sum@PAGEOFF] ; orig_sum
.....
BLR             X8
# orig_sum 跳到 sum 的片段
LDR             X17, =0x753EDCE894
BR              X17
RET
剩余 fake_sum 的返回也没啥好说的。 就是正常返回。
# 将返回值 放入 x0
E0 1F 00 B9                   STR             W0, [SP,#0x1C]
# 通过 printf 打印下返回值
E1 1F 40 B9                   LDR             W1, [SP,#0x1C]
C0 FF FF 90 00 EC 27 91       ADRL            X0, unk_753EDC69FB
76 79 00 94                   BL              printf
E0 1F 40 B9                   LDR             W0, [SP,#0x1C]
# 还原 x29 x30 寄存器
FD 7B 45 A9                   LDP             X29, X30, [SP,#0x50]
# 还原堆栈
FF 83 01 91                   ADD             SP, SP, #0x60 ; '`'
# 返回 x0
C0 03 5F D6                   RET
总结
基于 dobby 对于 function inline hook 所做的事情简单来说就 2个 步骤
[ol]

  • 创建 orig_sum 的内存 储存 sum 前12个 字节 并携带 BR 跳回到后12个字节的地方

  • 修改 sum 的前 12 个字节 跳到 fake_sum 中
    [/ol]

    方法, 字节

  • 您需要登录后才可以回帖 登录 | 立即注册

    返回顶部