美文网首页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