iOS-应用安全08 Hook

503 阅读3分钟

HOOK加单介绍

改变原始程序执行过程

HOOK技术种类

  • 1.Mehtod Swizzle

利用runtime的特性,改变SEL和IMP的对应方法;主要用于OC方法

  • fishhook

是由facebook提供的一个动态修改连接mach-O工具。利用MachO 文件加载原理,通过修改懒加载和非懒加载连个表的指针达到C函数hook的目的。

  • Cydia Substrate 原名 Mobile Substrate,它主要是针对OC方法、C函数以及函数地址进行Hook,当然它并不是仅仅针对iOS而设计的,安卓一样可以用。官方地址:www.cydiasubstrate.com/

fishhook

我们先看fishhook.h文件(github上有,自己下载)中的两个函数

//项目中所有的函数都能hook
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel);
//只针对某一个image的hook
int rebind_symbols_image(void *header,
                         intptr_t slide,
                         struct rebinding rebindings[],
                         size_t rebindings_nel);

使用示例 HOOK--NSLog函数

struct rebinding {
  const char *name;//需要HOOK的函数名称,C字符串
  void *replacement;//新函数的地址
  void **replaced;//原始函数地址的指针!
};

#########
- (void)viewDidLoad {
    [super viewDidLoad];
    //HOOK -- NSLog函数!
    NSLog(@"123");
    //指定交换的函数
    struct rebinding nslog;
    nslog.name = "NSLog";
    nslog.replacement = myNSLog;

    //fishhook 运行的时刻,动态的获取到NSLog的地址。
    nslog.replaced = (void *)&sys_nslog;

    //结构体数组
    struct rebinding rebs[1] = {nslog};

    /** 用于交换C函数
     * arg1:存放rebinding结构体的数组
     * arg2:rebinding结构体的数组的长度
     */
    rebind_symbols(rebs, 1);
}

//---------------NSLog--------------------
//函数指针,用来保存原始的函数地址
static void(*sys_nslog)(NSString * format,...);
//C函数的名称,就是函数的指针!
//定义一个新的函数
void myNSLog(NSString * format,...){
    format = [format stringByAppendingString:@"\n勾上了!"];

    //调用系统的函数
    sys_nslog(format);
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"点击了屏幕!");// 定位到哪个地址!
}

fishhook 原理

apple在数据段创建一份符号表,DYLD会在loadCommands中将函数的真实地址(eg :NSLog)赋值到数据段的符号表上-即将符号和真实地址绑定;而fishhook就是改变符号表上对应的函数地址;整个技术称为pic技术;所以fishhook无法交换自定义函数;

  • memory read:查看内存段情况;dis -s:查看汇编情况

初探防护

  • 1.使用fishhook,去hook核心代码(method_exchangeImplementations,setimp,getImp),让其他进攻代码找不到原方法
  • 2.如何我们自己工程里面要用到核心代码(method_exchangeImplementations,setimp,getImp),我们可以使用宏定义的去全局替换原来的方法,当然如果第三方也用到了核心方法,那么你得去做响应的适配
  • 3.但是如果进攻代码load在防护代码之前,就防护无效了
  • 4.针对于3这种破解,可以把防护代码也写在framework中,至于修改MachO中framework加载的顺序那就很难操作了。
#import "ViewController.h"
#import <objc/runtime.h>
#import "fishhook.h"

@interface ViewController ()

@end

@implementation ViewController

+(void)load
{
    //进攻的代码!
    // getIMP  setIMP
    Method old = class_getInstanceMethod(self, @selector(btnClick1:));
    Method newMethod = class_getInstanceMethod(self, @selector(click1Hook:));
    method_exchangeImplementations(old, newMethod);
    
    //防护代码!
    struct rebinding bd;
    bd.name = "method_exchangeImplementations";
    bd.replacement = myExchange;
    bd.replaced = (void *)&exchangeP;
    struct rebinding rebs[1] = {bd};
    rebind_symbols(rebs, 1);
    
   
}

//防护代码
//函数指针变量
void
(*exchangeP)(Method _Nonnull m1, Method _Nonnull m2);
void myExchange(Method _Nonnull m1, Method _Nonnull m2){
    NSLog(@"检测到HOOK!!");
}


-(void)click1Hook:(id)sender{
    NSLog(@"HOOK成功!!");
}


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (IBAction)btnClick1:(id)sender {
    NSLog(@"按钮1调用了!");
    
}

- (IBAction)btnClick2:(id)sender {
    NSLog(@"按钮2调用了!");
    
}

@end