iOS逆向-16:Fishhook原理

fishhook

fishhook是如何通过字符串找到符号表的呢?
先来看看如何通过符号找到字符串:


image.png

image.png

可以看到懒加载符号表的顺序和间接符号表(undefine)的顺序是一样的,这个间接符号表和symbols是有关联的,比如NSLog在间接符号表的data 为0x000000CC十进制为204,这个204就是符号表中的角标,如下图:


image.png

在图中可以看到,在字符表中的偏移量为0xCE,我们在看看String table中的偏移的0xce是什么(即0x11378+0xce=0x11446),如图:
image.png

所以fishhook正好和这个过程是相反的。

去符号Strip

去掉符号的作用:安全,减小包体积,优化
全局符号 、本地符号

  • app : 去掉所有的
  • 动态库: 保留全局符号

symbols 最下面,本地的保存的imp, 间接符号找桩,所以为0


image.png

去符号 断点短不住

Strip Style

  • 去全局符号
  • 去非全局符号
  • 去debug符号

Deployment Postprocessing

  • 改成YES编译阶段就会脱符号


    image.png

    编译


    image.png

    这个是上线后bitcode恢复符号用的
    image.png

    image.png

    这里是imp,因为间接符号的调用是找桩去执行的,所以为0,但是本地符号,和全局符号就是imp了

image.png

去掉符号时候都是unnamed_symbol,这里不好分析,所以可以通过restore-symbol重新恢复符号
./restore-symbol MachO -o NewMachO
image.png

image.png

可以看到符号恢复了,这里的恢复建立在runtime基础上,动态派发的必定保留了类名,方法名以及imp之间的关系,本质通过MachO下图这两个段重新创建了符号表,但是这个工具c函数以及swift静态调用的是无法恢复的
image.png

fishhook防护

这里是一种简单的防护,也有办法破解、
首先OC MethodSwizzle 使用系统函数,那么APP利用fishhook hook系统的MethodSwizzle,可以让他人hook不了
防hook代码最好在framework中写,framework中的load比主工程的load先加载,同时也在别人注入的framework之前
弊端:靠运行时,我只要比你早,找到fishhook ,对内部的fishhook进行hook,hook +load 然后不执行,也可以通过字符串就能定位修改字符串常量,导致防护失效
实例:

+(void)load
{
    //exchange
    struct rebinding exchange;
    exchange.name = "method_exchangeImplementations";
    exchange.replacement = my_exchange;
    exchange.replaced = (void *)&exchangeP;
    
    //setIMP
    struct rebinding setIMP;
    setIMP.name = "method_setImplementation";
    setIMP.replacement = my_exchange;
    setIMP.replaced = (void *)&setIMP_p;
    
    //getIMP
    struct rebinding getIMP;
    getIMP.name = "method_getImplementation";
    getIMP.replacement = my_exchange;
    getIMP.replaced = (void *)&getIMP_p;

    
    
    struct rebinding bds[] = {exchange,setIMP,getIMP};
    rebind_symbols(bds, 3);
    
}

//指针!这个可以暴露给外接!我自己的工程使用!!
void (*exchangeP)(Method _Nonnull m1, Method _Nonnull m2);

IMP _Nonnull (*setIMP_p)(Method _Nonnull m, IMP _Nonnull imp);
IMP _Nonnull (*getIMP_p)(Method _Nonnull m);


void my_exchange(Method _Nonnull m1, Method _Nonnull m2){
    NSLog(@"检测到了HOOK!");
}

给自己工程用,在.h中导出,同时将.h拖入public中,给外部用

CF_EXPORT void (*exchangeP)(Method _Nonnull m1, Method _Nonnull m2);

本地使用:

#import 
exchangeP(class_getInstanceMethod(self.class, @selector(btnClick2:)),

你可能感兴趣的:(iOS逆向-16:Fishhook原理)