美文网首页iOS逆向工程
逆向学习笔记11——fishhook执行原理及简单防护

逆向学习笔记11——fishhook执行原理及简单防护

作者: 危险地带_浅笑 | 来源:发表于2018-05-16 10:53 被阅读74次

    1,fishhook的执行原理

    C语言函数通常是静态的,编译之后,从汇编代码变成了内存地址。iOS系统实现了一个动态缓存库技术,一些公共的系统库放进内存中的某个地方,当某个iOS项目启动后,machO文件会在Data段创建一个指针,dyld动态将machO中Data段中这个指针指向外部函数,这里的指针指向内部函数的调用,指向外部函数的地址,而这个指针也就是我们通常说的符号;这也是为什么fishhook中函数名为rebind_symbols(重新绑定符号),实际上是修改这个指针指向外部函数的地址,这也就是为什么修改不了内部函数和自定义函数,只能修改machO外部函数(在符号表中能找到的函数)。由于苹果实现了ASLR技术(不了解ASLR,看这篇逆向学习笔记8——ASLR),所以这些动态缓存库函数在APP项目的内存地址不确定,每次启动APP的时候都会有相应的变化,这是C语言的动态表现
    下载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的地址偏移值,如下图

    image.png
    然后通过lldb拿到ASLR,通过下面操作,拿到内存中的NSLog函数。
    image.png

    断点单步走,过掉rebind_symbols(rebs, 1);,也就是让fishHook交换成功后,再重新打印,地址内存偏移0x8018的值,如下图

    image.png
    根据结果,很明显看出,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,创建一个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);//闪退,只要发现你hook我,我就闪退
    }
    
    
    -(void)clickLeftBtn:(id)sender{
       NSLog(@"原始hook打印");
    }
    

    viewController中代码如下

    - (IBAction)clickLeftBtn:(id)sender {
        NSLog(@"点击按钮1");
    }
    
    - (IBAction)clickRightBtn:(id)sender {
        NSLog(@"点击按钮2");
    }
    
    
    • 2.2Hook代码

    新建一个hookDemo,拿到刚刚创建的antiHookDemo的app,创建一个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——代码注入)

    相关文章

      网友评论

        本文标题:逆向学习笔记11——fishhook执行原理及简单防护

        本文链接:https://www.haomeiwen.com/subject/kfcydftx.html