1庸论,fishhook的執(zhí)行原理
C語言函數通常是靜態(tài)的职辅,編譯之后棒呛,從匯編代碼變成了內存地址。iOS系統(tǒng)實現了一個動態(tài)緩存庫技術域携,一些公共的系統(tǒng)庫放進內存中的某個地方簇秒,當某個iOS項目啟動后,machO文件會在Data段創(chuàng)建一個指針秀鞭,dyld動態(tài)將machO中Data段中這個指針指向外部函數趋观,這里的指針指向內部函數的調用,指向外部函數的地址锋边,而這個指針也就是我們通常說的符號皱坛;這也是為什么fishhook中函數名為rebind_symbols(重新綁定符號),實際上是修改這個指針指向外部函數的地址豆巨,這也就是為什么修改不了內部函數和自定義函數剩辟,只能修改machO外部函數(在符號表中能找到的函數)。由于蘋果實現了ASLR技術(不了解ASLR,看這篇逆向學習筆記8——ASLR)往扔,所以這些動態(tài)緩存庫函數在APP項目的內存地址不確定贩猎,每次啟動APP的時候都會有相應的變化,這是C語言的動態(tài)表現萍膛。
下載fishhook
-
1.1交換方法
準備如下代碼
#import "ViewController.h"
#import "fishhook.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"123");//之所以這里打印下吭服,因為NSLog是懶加載列表,如果不添加蝗罗,內存中無法找到NSLog內存地址
struct rebinding nslogBind;
nslogBind.name = "NSLog";
nslogBind.replacement = myNSLog;
nslogBind.replaced = (void *)&old_nslog;
struct rebinding rebs[] = {nslogBind};
rebind_symbols(rebs, 1);
}
static void (*old_nslog)(NSString *format, ...);
void myNSLog(NSString *format, ...){
NSString * str = [NSString stringWithFormat:@"%@\n??哈哈??",format];
old_nslog(str);
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"hello fish hook");
}
先運行一下艇棕,點擊屏幕,打印結果如下:
2018-05-15 16:44:01.289126+0800 FishHook[5266:1450255] hello fish hook
??哈哈??
很明顯串塑,根據結果可以知道沼琉,fishhook交換方法成功了。
-
1.2驗證fishhook綁定
接下來拟赊,我們探索下fishHook的流程刺桃,在rebind_symbols(rebs, 1);
加一個斷點。從machO的懶加載列表中拿出NSLog
的地址偏移值吸祟,如下圖
然后通過lldb拿到
ASLR
瑟慈,通過下面操作,拿到內存中的NSLog函數屋匕。斷點單步走葛碧,過掉rebind_symbols(rebs, 1);
,也就是讓fishHook交換成功后,再重新打印过吻,地址內存偏移0x8018
的值进泼,如下圖
根據結果蔗衡,很明顯看出,fishhook確實修改了符號綁定乳绕。
-
1.3驗證fishhook無法修改自定義函數
代碼如下
- (void)viewDidLoad {
[super viewDidLoad];
struct rebinding rebing;
rebing.name= "func";
rebing.replacement = newFunc;
rebing.replaced = (void *)&newFuncP;
struct rebinding rebs[] = {rebing};
rebind_symbols(rebs, 1);
}
static void (*newFuncP)(void);
void newFunc(){
NSLog(@"這是新的newFunc 函數");
}
void func(){
NSLog(@"這是自定義func 函數");
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
func();
}
點擊屏幕绞惦,打印結果如下:
2018-05-16 10:08:09.350558+0800 FishHook[6722:1744594] 這是自定義func 函數
很明顯,這里方法沒有替換成功洋措。也說明fishhook無法修改自定義函數济蝉。
2,利用fishhook防護
-
2.1 防護代碼
新建一個antiHookDemo菠发,并在target添加一個xxxFramework王滤,在xxxFramework導入fishhook
,創(chuàng)建一個HookManager類,添加如下代碼
+(void)load{
Method oldMethod = class_getInstanceMethod(objc_getClass("ViewController"), @selector(clickLeftBtn:));
Method newMethod = class_getInstanceMethod(self, @selector(clickLeftBtn:));
method_exchangeImplementations(newMethod, oldMethod);
struct rebinding exchangebinding;
exchangebinding.name = "method_exchangeImplementations";
exchangebinding.replacement = myExchange;
exchangebinding.replaced = (void *)&exchangeP;
struct rebinding getIMPbinding;
getIMPbinding.name = "method_getImplementation";
getIMPbinding.replacement = myExchange;
getIMPbinding.replaced = (void *)&getIMP;
struct rebinding setIMPbinding;
setIMPbinding.name = "method_setImplementation";
setIMPbinding.replacement = myExchange;
setIMPbinding.replaced = (void *)&setIMP;
struct rebinding rebs[] = {exchangebinding,getIMPbinding,setIMPbinding};
rebind_symbols(rebs, 3);
}
static void (*exchangeP)(Method _Nonnull m1, Method _Nonnull m2);
IMP _Nonnull (*setIMP)(Method _Nonnull m, IMP _Nonnull imp);
IMP _Nonnull (*getIMP)(Method _Nonnull m);
void myExchange(Method _Nonnull m1, Method _Nonnull m2){
NSLog(@"外部hook 不給過");
//這里可以做些讓程序崩潰的事情
exit(0);//閃退滓鸠,只要發(fā)現你hook我雁乡,我就閃退
}
-(void)clickLeftBtn:(id)sender{
NSLog(@"原始hook打印");
}
viewController中代碼如下
- (IBAction)clickLeftBtn:(id)sender {
NSLog(@"點擊按鈕1");
}
- (IBAction)clickRightBtn:(id)sender {
NSLog(@"點擊按鈕2");
}
-
2.2Hook代碼
新建一個hookDemo,拿到剛剛創(chuàng)建的antiHookDemo的app糜俗,創(chuàng)建一個xxframework踱稍,添加如下代碼
+(void)load
{
Method oldMethod = class_getInstanceMethod(objc_getClass("ViewController"), @selector(clickRightBtn:));
Method newMethod = class_getInstanceMethod(self, @selector(hookMethod));
method_exchangeImplementations(oldMethod, newMethod);
}
-(void)hookMethod{
NSLog(@"我hook到你了");
}
利用重簽和代碼注入方法直接運行到真機,程序閃退吩跋,打印結果為
2018-05-16 10:28:09.350558+0800 hookDemo[6722:1744594] 外部hook 不給過
從打印結果出來和程序閃退可以看出防護成功了??寞射。
(不了解重簽的童鞋,逆向學習筆記9——代碼重簽名和逆向學習筆記10——代碼注入)