各种Hook开发代码集锦

2020-07-14  本文已影响0人  D_8270

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

上一篇下一篇

猜你喜欢

热点阅读