日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

IOS 之FishHook原理及例子

發布時間:2023/12/3 综合教程 39 生活家
生活随笔 收集整理的這篇文章主要介紹了 IOS 之FishHook原理及例子 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、HOOK概述

? ? HOOK,中文為“鉤子”或“掛鉤”,在ios逆向中是指改變程序的運行流程的一種技術,通過hook可以讓別人的程序執行自己的代碼邏輯,在逆向中經常使用。所以就來看看HOOK的原理吧!

上圖很常見的微信搶紅包,hook原理就相當于程序本來收到紅包消息用戶應該點擊紅包之后點擊“搶”,才能領紅包,而通過HOOK既可以執行自己的代碼,用戶不需要點擊自動執行搶紅包代碼,這就是HOOK常見的應用。

1.ios中HOOK技術的幾種方式?

1、Method Swizzle

? ? 利用OC的Runtime特性,動態改變SEL(方法編號)和IMP(方法的實現)的對應關系,達到OC方法調用流程改變的目的,主要用在OC方法中。

2、fishhook

? ? 他是facebook提供的一個動態修改鏈接mach-o文件的工具。利用MachO文件加載原理,通過修改懶加載和非懶加載兩個表指針達到C函數HOOK的目的。

3、Cydia Substrate

? ? Cydia Substrate 原名為 Mobile Substrate,主要針對OC方法、C函數以及函數地址進行hook操作,他可以用于iOS,也可用于android 。官網:www.cydiasubstrate.com

?

Method Swizzle :

? ? 在OC中,SEL和IMP的關系好比標題和頁碼、接口和實現之間的關系,一個是標題,一個是對應的實現。Runtime提供了交換兩個SEL和IMP對應關系的函數:method_exchangeImplememtations(Method m1,Method m2) 這個函數交換兩個SEL和IMP之間的關系的技術,叫Method Swizzle(方法欺騙)。

例子:

//
//  ViewController.m
//  Demo
//
//  Created by yrl on 2019/7/26.
//  Copyright ? 2019 apple. All rights reserved.
//#import "ViewController.h"
#import <objc/runtime.h>@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];NSURL *url = [NSURL URLWithString:@"https://study.163.com/courses-search?keyword=邏輯教育"];//出現中文應進行編碼轉換,否則會為空NSLog(@"%@",url);}@end

運行結果:?

?

?我們可以用stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]轉碼

利用OC的Runtime進行方法交換,例子:

//
//  NSURL+HK_URL.m
//  Demo
//
//  Created by yrl on 2019/7/26.
//  Copyright ? 2019 apple. All rights reserved.
//#import "NSURL+HK_URL.h"
#import <objc/runtime.h>@implementation NSURL (HK_URL)
+(void)load{//類方法Method URLWithStr = class_getClassMethod(self, @selector(URLWithString:));//系統的Method HK_URLWithStr = class_getClassMethod(self, @selector(HK_URLWithString:));//自己的//changemethod_exchangeImplementations(URLWithStr, HK_URLWithStr);
}+(nullable instancetype)HK_URLWithString:(NSString *)URLString{NSURL * url = [NSURL HK_URLWithString:URLString];//應用HK_URLWithString系,URLWithString已經交換了,會造成死遞歸統if(url == nil){//如果為空則進行編碼轉換URLString = [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];}url = [NSURL HK_URLWithString:URLString];//將URLString賦值給UK_URLWithStringreturn url;
}@end

實現了HOOK 了NSURL類的URLWithString方法,在類方法load中交換了系統的URLWithString和自己定義的HK_URLWithString,在調用URLWithString時會調用HK_URLWithString,實現HOOK,將中文編碼,再運行程序:

可看到中文已經被編碼了,說明我們已經改變了程序的執行流程。?

Cydia Substrate

很強大的一個框架?

1.MoblieHooker

? ? 他有一系列的宏和函數,底層調用的objc的runtime和fishhook來替換系統或者目標應用,其中有兩個函數:

MSHookMessageEx 主要用于Objective-C方法 void MSHookMessageEx(Class class ,SEL selector ,IMP replacement ,IMP result)第一個參數是哪個類,第二個參數是哪個編號(方法),第三個新方法的實現,第四個參數舊方法的實現

MSHookFunction 主要用于C/C++函數 void MSHookFunction(voidfunction, void * replacement, void ** p_original) Logos語法的%HOOK就是對這個函數做了一層封裝。

2.MobileLoader

? ? 用于加載第三方dylib在運行的應用程序中。啟動MobileLoader會根據規則把指定的第三方動態庫加載進去,第三方動態庫也就是我們寫的破解程序。

3.Safe Mode

? ?破解程序本質是dylib,寄生在別人的進程里,系統進程一旦出錯,可能導致整個系統崩潰,Cydia Substrate提供安全模式,在安全模式下,所有的第三方dylib都會被禁止,便查錯與修復。

FishHook

? ? 不是一個框架,是一個工具,工具代碼可以在github上下載:https:/github.com/facebook/fishhook.git,勾不住自己定義的函數,只能勾系統函數。

其中只有一個.c和.h文件,代碼不長,有興趣可以看看源碼,代碼有很多關于MachO文件的東西,先了解一下MachO的API

fishhook.h就倆函數一個結構體:

例子:點擊屏幕觸發NSLog函數轉到myNSLog

將fishhook.c? ?fishhokk.h拖進項目

//
//  ViewController.m
//  fishhook
//
//  Created by yrl on 2019/7/26.
//  Copyright ? 2019 apple. All rights reserved.
//#import "ViewController.h"
#import "fishhook.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];NSLog(@"123");//NSLog屬于懶加載,調用才能看到//實現交換//定義rebinding結構體struct rebinding nslog;nslog.name = "NSLog";nslog.replacement = myNSLog;nslog.replaced = (void **)&sys_nslog;//定義結構體數組struct rebinding rebs[1] = {nslog};/* 用來重新綁定符號* arg1 存放rebinding結構體的數組* arg2 數組長度*/rebind_symbols(rebs, 1);//兩個參數 結構體數組、數組長度printf("修改完畢!!");
}
//-------------更改系統NSLOG函數-------------
//函數指針,用來保存原來的函數地址
static void(*sys_nslog)(NSString *format,...);
//定義一個新的函數
void myNSLog(NSString *format, ...){format = [format stringByAppendingString:@"\n勾上了!!"];sys_nslog(format);
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{//屏幕觸發事件NSLog(@"點擊屏幕!!");
}@end

運行函數,點擊屏幕:

二、FishHook的原理探究

? ? 仿照上面的工程再寫一個代碼,這回我們用來勾自己定義的newFunc()函數,當點擊屏幕時,func(str)應該被newFunc HOOK,轉而執行newFunc函數邏輯:

//
//  ViewController.m
//  fishhook2
//
//  Created by yrl on 2019/7/26.
//  Copyright ? 2019 apple. All rights reserved.
//#import "ViewController.h"
#import "fishhook.h"
@interface ViewController ()@end@implementation ViewControllervoid func(const char *str){NSLog(@"%s",str);
}- (void)viewDidLoad {[super viewDidLoad];//交換rebind_symbols((struct rebinding[1]){{"func",newRunc,(void **)&funcP}}, 1);}
//原始指針
static void (*funcP)(const char * str);
//新方法
void newRunc(const char * str){NSLog(@"勾住了");funcP(str);
}-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{func("hello");
}@end

運行后發現并沒有按照預想的來:

FishHook原理:

git上有介紹(英文):

dyld?binds lazy and non-lazy symbols by updating pointers in particular sections of the?__DATA?segment of a Mach-O binary.?fishhook?re-binds these symbols by determining the locations to update for each of the symbol names passed to?rebind_symbols?and then writing out the corresponding replacements.

For a given image, the?__DATA?segment may contain two sections that are relevant for dynamic symbol bindings:?__nl_symbol_ptr?and?__la_symbol_ptr.?__nl_symbol_ptr?is an array of pointers to non-lazily bound data (these are bound at the time a library is loaded) and?__la_symbol_ptr?is an array of pointers to imported functions that is generally filled by a routine called?dyld_stub_binder?during the first call to that symbol (it's also possible to tell?dyld?to bind these at launch). In order to find the name of the symbol that corresponds to a particular location in one of these sections, we have to jump through several layers of indirection. For the two relevant sections, the section headers (struct sections from?<mach-o/loader.h>) provide an offset (in the?reserved1?field) into what is known as the indirect symbol table. The indirect symbol table, which is located in the?__LINKEDIT?segment of the binary, is just an array of indexes into the symbol table (also in?__LINKEDIT) whose order is identical to that of the pointers in the non-lazy and lazy symbol sections. So, given?struct section nl_symbol_ptr, the corresponding index in the symbol table of the first address in that section is?indirect_symbol_table[nl_symbol_ptr->reserved1]. The symbol table itself is an array of?struct nlists (see?<mach-o/nlist.h>), and each?nlist?contains an index into the string table in?__LINKEDITwhich where the actual symbol names are stored. So, for each pointer?__nl_symbol_ptr?and?__la_symbol_ptr, we are able to find the corresponding symbol and then the corresponding string to compare against the requested symbol names, and if there is a match, we replace the pointer in the section with the replacement.

可執行文件MachO怎么進入內存的?是通過DYLD(動態鏈接器)加載進內存的,通過lldb(調試工具)的image list可以看到加載MachO文件的同時還加載了哪些庫,期間涉及到了ASLR(地址空間布局隨機化),每次加載的內存地址的偏移都不一樣。

拿上面的例子說,自己定義的func函數和NSLog函數在內存中的地址不一樣,位置也不一樣,func在MachO文件中,NSLog在系統動態庫(dylib共享的動態鏈接庫)中,那么func里面調用NSLog要找到NSLog的地址,MachO文件怎么找?怎么知道的?在程序啟動之前都不知道,不同手機的NSLog地址也是不一樣的,這就是DYLD的工作了,如圖:

所有的可執行文件都是由它加載的,dyld加載了MachO,一旦加載了MachO文件,蘋果采用了一種技術叫PIC(位置獨立代碼),當程序MachO調用其外部的函數的時候,比如說NSLog,他就會在DATA段創建一個指針,八個字節,用來放外部函數的地址,在調用之前這里是什么是不知道的,當func調用系統動態庫中NSLog時就通過dyld鏈接dylib找到NSLog函數的真實地址,寫入到DATA段,dyld就會綁定一個MachO里面的函數(符號),也就是寫到data段里的符號,所以這就是為什么fishhook的交換函數叫rebind_sybomls(綁定符號),也就是說這個函數只適用于系統的動態連接庫中的函數(系統C級別函數),因為只有系統函數在MachO調用的時候會有符號寫入data段,所以這就是為什么去HOOK自己定義的函數不起作用,因為自己定義的函數MachO運行的時候不需要去通過dyld獲取函數地址,自然就HOOK不到。

具體驗證:上一個fishhook例子

? ? 將例子build一下,提取fishhook.app里面的可執行文件,用MachOview打開,看看其二進制文件格式:我們就看DATA段

可以看到NSLog的地址0x100003028(現在這個值沒用,運行的時候dyld才給它賦值) 偏移0x3028,運行時保存NSLog的真實地址,而這個地址在MachO文件偏移的0x3028處,我們找一下,調試在此處下斷點:

通過lldb查看 輸入image list

我們查看NSLog文件地址(MachO文件地址記得后面加偏移才是NSLog地址):x 0x10b729000+0x3028

這個是NSLog地址(小端序)0x010bac20de,查看此處的匯編代碼:dis -s?0x010bac20de

往下走一步ni 再查看原來NSLog的地址:

?此處變為myNSLog了,可見,hook成功。

通過符號找字符

在MachO文件找字符,在Lazy Symbol Pointers表中NSLog在第一位,與之對應的有一個表Dynamic Symbol Table下的Indirect Symbols表

對比一下兩個表一一對應,Indirect Symbols指向了下一個Symbols表的第0x79個表項:

?

?他中的數據指向了String Table 的index下標:

?位置在0x4f1c+0x9b =0x4fb7,找到這個位置:

對應的就是NSLog的字符,每一個字符都是以“_”以“.”結束。

這個過程就是開頭那段英文所說的意思,官方給的圖:

Lazy Symbol和Indirect Symbol Table對應,Lazy Symbol的0x1061處的表項指向了?Indirect Symbol Table的對應0x1061處的表項,而Indirect Symbol Table0x1061處指向的是Symbol Table的16343處,Symbol Table的16343處指向的是String Table的70026處的字符,可以看到字符為"_close.",他用的是close()函數,而我們用的是NSLog函數。

后記:

? ? MachO文件很重要,在做防護,檢測app是否被修改,被注入,是否在越獄環境中,都需要不斷檢測MachO文件的字段是否被修改,如果MachO被修改說明app被修改了,那么app就會做出相應的防護措施,比如微信掃臉支付等功能禁用等,所以我們要了解MachO文件。

總結

以上是生活随笔為你收集整理的IOS 之FishHook原理及例子的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。