各種Hook開發(fā)代碼集錦

MonkeyDev的MonkeyApp模板的開發(fā)

fishhook Hook帶符號的C函數(shù)

XXX.m文件

#include <mach-o/dyld.h>
#include "fishhook/fishhook.h"

/*以_dyld_get_image_name為例,該函數(shù)為獲取當(dāng)前應(yīng)用的二進(jìn)制文件中所有的鏡像完整路徑,配合_dyld_image_count函數(shù)使用*/
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系統(tǒng)函數(shù)的函數(shù)名稱
    bind.name = "_dyld_get_image_name";
    bind.replacement = (void *)dyld_get_image_name_mine;//新的函數(shù)去替換系統(tǒng)的函數(shù)
    bind.replaced = (void **)&dyld_get_image_name_old123;//把真正的系統(tǒng)函數(shù)地址保存到dyld_get_image_name_old123
    struct rebinding rebs[] = {bind};
    rebind_symbols(rebs, 1);
}

Theos開發(fā)

MSHookFunction Hook帶符號的C函數(shù)

XXX.m文件

#include <mach-o/dyld.h>
#import <CydiaSubstrate/CydiaSubstrate.h>

/*以_dyld_get_image_name為例,該函數(shù)為獲取當(dāng)前應(yīng)用的二進(jìn)制文件中所有的鏡像完整路徑,配合_dyld_image_count函數(shù)使用*/
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函數(shù)

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;
    }
    //獲取當(dāng)前的可執(zhí)行文件路徑
    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;
    }
    
    //如果需要獲取可執(zhí)行文件中引入的某一個(gè)模塊(如你加入的XXX.dylib)在內(nèi)存中的偏移量
    //則需要判斷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后會(huì)來到這里
void hook_testMethod(void) {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"hook了我" message:@"message" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"other", nil];
    [alert show];
}

CHConstructor{
  //注冊添加鏡像回調(diào),應(yīng)用每加載一個(gè)模塊時(shí)都會(huì)產(chǎn)生一個(gè)回調(diào),此處我們提供這樣一個(gè)回調(diào)函數(shù),以接收每個(gè)模塊的信息
    _dyld_register_func_for_add_image(_register_func_for_add_image);
    //通過 模塊偏移前的基地址 + ASLR偏移量 找到函數(shù)真正的地址進(jìn)行hook
  /*解釋:一個(gè)應(yīng)用的可執(zhí)行文件也屬于一個(gè)模塊,也會(huì)被加載進(jìn)內(nèi)存中,其內(nèi)部引入的所有系統(tǒng)庫或者是第三方庫都會(huì)被加載進(jìn)內(nèi)存中,每個(gè)可執(zhí)行文件或是dylib在IDA/Hopper中打開地址都是從0開始的,注意要正確選擇在IDA/Hopper中打開時(shí)選擇的armv7或arm64架構(gòu)類型,當(dāng)這些模塊被加載進(jìn)內(nèi)存時(shí),這些模塊中的所有方法的地址都會(huì)改變,改變的就是這個(gè)ASLR偏移量,所以我們定位到某個(gè)函數(shù)的地址時(shí),只需找到其在IDA/Hopper中對應(yīng)的地址再加上ASLR偏移量就是該函數(shù)最終真正在內(nèi)存中的地址*/
 //這個(gè)0x1000065f0就是testMethod在Hopper中打開時(shí)顯示的地址,注意選擇正確的架構(gòu)
    MSHookFunction((void *)(0x1000065f0+g_slide), (void *)hook_testMethod, (void **)&orig_testMethod);
}

如何處理sub_xxx函數(shù)(非越獄環(huán)境)?

如果分析到目標(biāo)sub_xxx函數(shù)之后,可以直接靜態(tài)修改二進(jìn)制文件,用Hopper打開目標(biāo)二進(jìn)制文件,注意選擇正確的架構(gòu),然后定位到調(diào)用sub_xxx函數(shù)的地方(一般是bl sub_xxx這樣的),在要修改的語句上按Alt + A,將當(dāng)前匯編指令修改為nop(nop是arm匯編里的一條空指令,即什么也不做)即可,但這樣只能完全阻止調(diào)用sub_xxx,如果只是需要在sub_xxx函數(shù)中插入一點(diǎn)邏輯,則需另外想辦法,然后Hopper->File->Produce New Executable... 保存為新的二進(jìn)制文件或lib,現(xiàn)在大部分只有arm64,如果還需要armv7的,則將原二進(jìn)制文件以armv7的架構(gòu)打開,找到sub_xxx執(zhí)行上述的操作并保存, 將上面兩個(gè)得到的二進(jìn)制文件合并lipo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容