1、inlineHook概述
所谓InlineHook
(内联钩⼦),就是直接修改⽬标函数的头部代码。让它跳转到⾃定义函数中执⾏代码,从⽽达到Hook
的⽬的。这种Hook
技术⼀般用于静态语⾔。
Dobby
,是一个全平台的inlineHook
(内联钩子)框架。Dobby
是通过插入 __DATA
段和__TEXT
段到 Mach-O
中。
-
__DATA
用来记录Hook
信息(Hook
数量、每个Hook
方法的地址)、每个Hook
方法的信息(函数地址、跳转指令地址、写Hook
函数的接口地址)、每个Hook
的接口(指针)。 -
__Text
用来记录每个Hook
函数的跳转指令。
Dobby
通过 mmap
把整个 Mach-O
文件映射到用户的内存空间,写入完成保存本地。所以 Dobby
并不是在原 Mach-O
上进行操作,而是重新生成并替换。
2、Dobby
2.1、编译Dobby
1、git clone
源码
#depth用于指定克隆深度,为1即表示只克隆最近一次commit.
git clone https://github.com/jmpews/Dobby.git --depth=1
2、Dobby
是跨平台的,使用cmake
将这个工程编译成为Xcode
工程。编译命令如下:
cd Dobby && mkdir build_for_ios_arm64 && cd build_for_ios_arm64
cmake .. -G Xcode \
-DCMAKE_TOOLCHAIN_FILE=cmake/ios.toolchain.cmake \
-DPLATFORM=OS64 -DARCHS="arm64" -DCMAKE_SYSTEM_PROCESSOR=arm64 \
-DENABLE_BITCODE=0 -DENABLE_ARC=0 -DENABLE_VISIBILITY=1 -DDEPLOYMENT_TARGET=9.3 \
-DDynamicBinaryInstrument=ON -DNearBranch=ON -DPlugin.SymbolResolver=ON -DPlugin.Darwin.HideLibrary=ON -DPlugin.Darwin.ObjectiveC=ON
3、编译完成后进入目录 build_for_ios_arm64
打开 Xcode
编译,设置 CODE_SIGNING_ALLOWED=NO
、Enable Bitcode=YES
编译 DpbbyX.framework
或者 dobby.dylib
2.2、使用Dobby
1、将 DobbyX.framework
拖入新建的工程中,新建 Copy Files
,将 DobbyX.framework
添加进入
编译运行成功
[*] ================================
[*] Dobby
[*] ================================
[*] dobby in debug log mode, disable with cmake flag "-DDOBBY_DEBUG=OFF"
2.2.1、直接函数符号替换
@implementation ViewController
int sum(int a,int b){
return a + b;
}
- (void)viewDidLoad {
[super viewDidLoad];
//HOOK sum -- 修改的Text段实际上是替换!
DobbyHook((void *)sum, mySum, (void *)&sum_p);
}
//函数指针用于保留原来的执行
static int (*sum_p)(int a,int b);
//新函数地址
int mySum(int a,int b){
NSLog(@"HOOK 成功了!%d,",sum_p(a,b));
return a - b;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"sum:%d",sum(10, 20));
}
执行结果
2022-01-09 18:07:45.376665+0800 InlineProject[6934:1301584] HOOK 成功了!30,
2022-01-09 18:07:45.376974+0800 InlineProject[6934:1301584] sum:-10
1、直接调用 sum
和使用 Dobby
后调用 sum
的汇编对比
1)、直接调用 sum
InlineProject`sum:
0x10432de04 <+0>: sub sp, sp, #0x10 ; =0x10
0x10432de08 <+4>: str w0, [sp, #0xc]
0x10432de0c <+8>: str w1, [sp, #0x8]
-> 0x10432de10 <+12>: ldr w8, [sp, #0xc]
0x10432de14 <+16>: ldr w9, [sp, #0x8]
0x10432de18 <+20>: add w0, w8, w9
0x10432de1c <+24>: add sp, sp, #0x10 ; =0x10
0x10432de20 <+28>: ret
和普通的函数调用相同,在函数内栈平衡操作
2)、使用 Dobby
后
InlineProject`sum:
0x102ec9dd0 <+0>: adrp x17, 0
0x102ec9dd4 <+4>: add x17, x17, #0xe50 ; =0xe50
0x102ec9dd8 <+8>: br x17
-> 0x102ec9ddc <+12>: ldr w8, [sp, #0xc]
0x102ec9de0 <+16>: ldr w9, [sp, #0x8]
0x102ec9de4 <+20>: add w0, w8, w9
0x102ec9de8 <+24>: add sp, sp, #0x10 ; =0x10
0x102ec9dec <+28>: ret
通过汇编查看 x17
寄存器存储的是mySum的函数地址
2.2.1、直接函数地址替换
1、通过
MachOView
查看 sum
函数的偏移为 0x5D68
函数偏移
2、函数
sum
的真实地址 addr = aslr + offset
@implementation ViewController
int sum(int a,int b){
return a + b;
}
//版本不修改的情况下,写死没问题!!
static uintptr_t sumP = 0x100005d68;
- (void)viewDidLoad {
[super viewDidLoad];
//获取ASLR 相当于rebase
uintptr_t aslr = _dyld_get_image_vmaddr_slide(0);
sumP += aslr;
NSLog(@"sumP:%p\n sum:%p",(void *)sumP,sum);
//HOOK sum -- 修改的Text段实际上是替换!
DobbyHook((void *)sumP, mySum, (void *)&sum_p);
}
//函数指针用于保留原来的执行
static int (*sum_p)(int a,int b);
//新函数地址
int mySum(int a,int b){
NSLog(@"HOOK 成功了!%d,",sum_p(a,b));
return a - b;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"sum:%d",sum(10, 20));
}
@end
最终运行结果同上
网友评论