监控内存的方法之一就是hook malloc,监控其内存分配,ios允许使用c++语法,但是fishhook无法hook new操作符,从而无法监控new的内存分配。接下来介绍一种可以监控new操作符的内存分配方法。
1、查找new操作符的汇编实现
首先在demo上打一个断点,如下图所示
运行代码,会发现断点停留在如下位置
可以发现new操作符的地址是 0x1047fa70c
然后我们查看app在内存中的偏移地址,使用image list
命令
可以看到app在内存中的偏移值为0x104658000
new操作符在MachO中的偏移值 = new操作符真实的内存地址 - app在内存中的偏移值
0x1047fa70c
- 0x104658000
= 0x1A270C
0x1A270C
就是new操作符在MachO中的偏移值。
通过MachOView查看MachO中的Indirect Symbol Table,找到value为0x1A270C
的符号,发现符号是__Znwm
__Znwm
是什么呢?文章malloc与new的区别里解释说
new则不然,是c++的关键字,它本身不是函数。 new不依赖于头文件,c++编译器就可以把new编译成目标代码(g++4.6.3会向目标中插入_Znwm这个函数,另外,编译器还会根据参数的类型,插入相应的构造函数)
2、使用fishhook hook符号__Znwm
使用fishhook hook符号__Znwm
就很简单,使用如下代码:
struct rebinding znwmBind;
znwmBind.name = "_Znwm";
znwmBind.replacement = (void *)MyZnwm;
znwmBind.replaced = (void **)&old_znwm;
struct rebinding rebs[1] = {znwmBind};
rebind_symbols(rebs, 1);
static void* (*old_znwm)(unsigned long);
void *MyZnwm(unsigned long size){
NSLog(@"hook operate new") ;
void*ptr = old_znwm(size) ;
return ptr ;
}
首先在测试demo和hook打上断点,看一下两个指针地址是否一样,如果一样,就表示hook成功
运行代码,进入到hook代码,如下所示
指针地址是0x283e2d590
,并且old_znwm
指向的也是operate new
。继续运行代码
返回的指针地址仍然是0x283e2d590
,表示new操作符的内存地址,我们已经成功的进行了hook了
参考文章
1、https://www.jianshu.com/p/b6a72aa6c146
2、https://yq.aliyun.com/articles/399198
3、https://blog.csdn.net/fengbingchun/article/details/82947673