MonkeyDev的MonkeyApp模板的开发
fishhook Hook带符号的C函数
XXX.m文件
#include <mach-o/dyld.h>
#include "fishhook/fishhook.h"
/*以_dyld_get_image_name为例,该函数为获取当前应用的二进制文件中所有的镜像完整路径,配合_dyld_image_count函数使用*/
static char *(*dyld_get_image_name_old123)(uint32_t index);
char *dyld_get_image_name_mine(uint32_t index);
char *dyld_get_image_name_mine(uint32_t index)
{
char *imageName = dyld_get_image_name_old123(index);
printf("hook到了 \n%s",imageName);
return imageName;
}
CHConstructor{
MSHookFunction((void *)_dyld_get_image_name,(void *)dyld_get_image_name_mine, (void **)&dyld_get_image_name_old123);
struct rebinding bind;//要HOOK系统函数的函数名称
bind.name = "_dyld_get_image_name";
bind.replacement = (void *)dyld_get_image_name_mine;//新的函数去替换系统的函数
bind.replaced = (void **)&dyld_get_image_name_old123;//把真正的系统函数地址保存到dyld_get_image_name_old123
struct rebinding rebs[] = {bind};
rebind_symbols(rebs, 1);
}
Theos开发
MSHookFunction Hook带符号的C函数
XXX.m文件
#include <mach-o/dyld.h>
#import <CydiaSubstrate/CydiaSubstrate.h>
/*以_dyld_get_image_name为例,该函数为获取当前应用的二进制文件中所有的镜像完整路径,配合_dyld_image_count函数使用*/
static char *(*dyld_get_image_name_old123)(uint32_t index);
char *dyld_get_image_name_mine(uint32_t index);
char *dyld_get_image_name_mine(uint32_t index)
{
char *imageName = dyld_get_image_name_old123(index);
printf("hook到了 \n%s",imageName);
return imageName;
}
CHConstructor{
MSHookFunction((void *)_dyld_get_image_name,(void *)dyld_get_image_name_mine, (void **)&dyld_get_image_name_old123);
}
MSHookFunction Hook无符号的C函数
XXX.m文件
#include <mach-o/dyld.h>
#import <CydiaSubstrate/CydiaSubstrate.h>
//偏移量
intptr_t g_slide;
//保存模块偏移基地址的值
static void _register_func_for_add_image(const struct mach_header *header, intptr_t slide) {
Dl_info image_info;
int result = dladdr(header, &image_info);
if (result == 0) {
NSLog(@"load mach_header failed");
return;
}
//获取当前的可执行文件路径
NSString *execName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"];
NSString *execPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingFormat:@"/%@", execName];
if (strcmp([execPath UTF8String], image_info.dli_fname) == 0) {
g_slide = slide;
}
//如果需要获取可执行文件中引入的某一个模块(如你加入的XXX.dylib)在内存中的偏移量
//则需要判断image_info.dli_fname中是否h包含字符串XXX.dylib
// NSString *fname = [NSString stringWithUTF8String:image_info.dli_fname];
// if ([fname containsString:@"XXX.dylib"]) {
// g_slide = slide
// }
}
void (*orig_testMethod)(void);
void hook_testMethod(void);
//hook后会来到这里
void hook_testMethod(void) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"hook了我" message:@"message" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"other", nil];
[alert show];
}
CHConstructor{
//注册添加镜像回调,应用每加载一个模块时都会产生一个回调,此处我们提供这样一个回调函数,以接收每个模块的信息
_dyld_register_func_for_add_image(_register_func_for_add_image);
//通过 模块偏移前的基地址 + ASLR偏移量 找到函数真正的地址进行hook
/*解释:一个应用的可执行文件也属于一个模块,也会被加载进内存中,其内部引入的所有系统库或者是第三方库都会被加载进内存中,每个可执行文件或是dylib在IDA/Hopper中打开地址都是从0开始的,注意要正确选择在IDA/Hopper中打开时选择的armv7或arm64架构类型,当这些模块被加载进内存时,这些模块中的所有方法的地址都会改变,改变的就是这个ASLR偏移量,所以我们定位到某个函数的地址时,只需找到其在IDA/Hopper中对应的地址再加上ASLR偏移量就是该函数最终真正在内存中的地址*/
//这个0x1000065f0就是testMethod在Hopper中打开时显示的地址,注意选择正确的架构
MSHookFunction((void *)(0x1000065f0+g_slide), (void *)hook_testMethod, (void **)&orig_testMethod);
}
如何处理sub_xxx函数(非越狱环境)?
如果分析到目标sub_xxx函数之后,可以直接静态修改二进制文件,用Hopper打开目标二进制文件,注意选择正确的架构,然后定位到调用sub_xxx函数的地方(一般是bl sub_xxx这样的),在要修改的语句上按Alt + A,将当前汇编指令修改为nop(nop是arm汇编里的一条空指令,即什么也不做)即可,但这样只能完全阻止调用sub_xxx,如果只是需要在sub_xxx函数中插入一点逻辑,则需另外想办法,然后Hopper->File->Produce New Executable... 保存为新的二进制文件或lib,现在大部分只有arm64,如果还需要armv7的,则将原二进制文件以armv7的架构打开,找到sub_xxx执行上述的操作并保存, 将上面两个得到的二进制文件合并lipo
网友评论