上一篇文章介紹到了logos在逆向中的原理,今天來簡單介紹一下logos的語法。
hook.x
代表支持logos語法和c語法hhh.xm
代表支持logos語法,c,c++ ,oc語法%group groupName -- %end
這個是分組,我們可能會做一些條件判斷,不同的情況使用不同的分組%ctor{} 、 %dtor{}
構造函數(shù),析構函數(shù)%init
初始化方法 ,如果定義了group 那么一定要寫%init(group),這個構造方法還可以用來初始化摸個類%init(someClass = objc_getClass(someClass))%hook className -- %end
這個代表你要hook哪個類,這一段可以寫在group里面,在hook里直接實現(xiàn)那個方法,如果編譯器報錯,就直接寫一個類的聲明%orig
執(zhí)行原來的方法 ,
它也可以有返回值 id value = %orig;
也可以用來調(diào)用原來的方法 id value= %orig(arg1)%log
輸出參數(shù),我們可以用來看方法的參數(shù)%new
新增一個方法%c
獲取某個類 %c(ViewController)
我們以Monkey的工程為例,假如我們需要hook一個類里的所有方法,
可以在MethodTraceConfig.plist 里 ,將ENABLE_METHODTRACE 字段改成YES,然后在TARGET_CLASS_LIST里新增一個子item,將類型改成string
#import <UIKit/UIKit.h>
@interface ViewController
+(void)zsh_classMethod;
@end
//代碼分組
%group group1
%hook ViewController
- (void)viewDidLoad{
NSLog(@"??????????????");
%orig;
}
%end
%end
%group group2
%hook ViewController
- (void)viewDidLoad{
NSLog(@"??????????????");
[%c(ViewController) zsh_classMethod];
%orig;
}
%new
+(void)zsh_classMethod{
NSLog(@"??????????????");
}
%end
%end
//創(chuàng)建了group就要寫構造函數(shù),后寫的構造函數(shù)會覆蓋一開始的構造函數(shù)
//構造函數(shù)
%ctor{
NSString * version = [UIDevice currentDevice].systemVersion;
if(version.doubleValue >= 11.3){
%init(group1)
}else{
%init(group2)
}
}
后續(xù)遇到logos語法還會更新
/**********************分割線**********************/
- FLEX
這個可以嵌入到工程里直接看層級,大家用cocoapod導入FIEX就好,然后在 CHConstructor 方法中加上[[FLEXManager sharedManager] showExplorer];就好
/********************* 分割線*************************/
- 簡單應用
目的: 在weixin首頁導航欄左邊也添加一個按鈕,點擊和右邊點擊一樣
下面講一下分析
步驟
1.首先通過mokeyDev運行起來工程,進入首頁
2.我們需要在導航欄新增一個我們自己item
3.通過viewDebug查看界面,查看點擊事件調(diào)用的方法
4.我們新增item調(diào)用上面查找出來的點擊事件。新增一個item,通過viewDebug可以看到當前的控制器,直接hook這個控制器里的
viewDidLoad方法,在里面設置左邊導航欄的item
%hook NewMainFrameViewController
- (void)viewDidLoad{
%orig;
UIButton * leftBtn = [UIButton buttonWithType:UIButtonTypeContactAdd];
[leftBtn addTarget:self action:@selector(zshClick) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithCustomView:leftBtn];
[self.navigationItem setLeftBarButtonItem:item];
}
%end
然而,然并卵。。。。。
我們猜想,viewDidLoad之后應該還有別的函數(shù)設置了leftItem,so,我們重寫一個leftItem的get方法,同時根據(jù)生命周期,重寫view展示的幾個方法,大家可以通過打印判斷最后調(diào)用的地方。
-(UINavigationItem *)navigationItem{
NSLog(@"????????????????");
return %orig;
}
通過查看log日志,我們發(fā)現(xiàn),在- (void)viewDidAppear:(_Bool)arg1原方法結(jié)束后沒有再獲取leftItem。因此我們修改item的方法可以放在這個方法的最后
- (void)viewDidAppear:(_Bool)arg1{
%orig;
NSLog(@"=====viewDidAppear=======");
UIButton * leftBtn = [UIButton buttonWithType:UIButtonTypeContactAdd];
[leftBtn addTarget:self action:@selector(zshClick) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithCustomView:leftBtn];
[self.navigationItem setLeftBarButtonItem:item];
}
*查看點擊導航欄右邊Item執(zhí)行的方法
可以看到那個方法是哪個類調(diào)用的哪個方法,但是通過層級關系圖我們也沒有看到這個類,那就只能上內(nèi)存中找了
- 通過cycript動態(tài)查看內(nèi)存。首先通過cycript 連接上應用,這一部分后續(xù)補個別人的連接
cy# UIApp
....
cy# choose(NewMainFrameRightTopMenuBtn)
可以看到一個對象輸出。接下來根據(jù)我們的經(jīng)驗,這個按鈕應該在導航欄上,先獲取到當前的控制器
cy# var mainFrame = UIApp.keyWindow.rootViewController.selectedViewController.topViewController
查看當前控制器的rightItem
cy# mainFrame.navigationItem.rightBarButtonItem
結(jié)果是一個MMBarButtonItem,到頭文件中查看一下這個類的定義(用class-dump導出頭文件的方法之前的文章有提到)
看一下類的定義,好像并沒有什么,接著看cycript中輸出的信息,item里面又個view,我們輸出一下view看看
cy# mainFrame.navigationItem.rightBarButtonItem.view
結(jié)果非常的感人,找到這個對象了?。?!
接下來就是調(diào)用了,附上代碼,之所以新定義幾個類的聲明是為了騙過編譯器,不這樣編譯器小姐姐會報錯的。
#import <UIKit/UIKit.h>
@interface zshView
-(void)showRightTopMenuBtn;
@end
@interface zshBar:UIBarButtonItem
@property(nonatomic,weak)zshView * view;
@end
@interface NewMainFrameViewController:UIViewController
@end
%hook NewMainFrameViewController
-(UINavigationItem *)navigationItem{
NSLog(@"????????????????");
return %orig;
}
- (void)viewDidAppear:(_Bool)arg1{
%orig;
NSLog(@"=====viewDidAppear=======");
UIButton * leftBtn = [UIButton buttonWithType:UIButtonTypeContactAdd];
[leftBtn addTarget:self action:@selector(zshClick) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithCustomView:leftBtn];
[self.navigationItem setLeftBarButtonItem:item];
}
%new
-(void)zshClick{
NSLog(@"hello world");
zshBar * btn =self.navigationItem.rightBarButtonItem;
[btn.view showRightTopMenuBtn];
}
%end
最后運行,界面左邊會有一個自定義的按鈕(抱歉有點丑),點擊左邊菜單欄也會顯示喲。