美文网首页
iOS 逆向开发13:代码注入

iOS 逆向开发13:代码注入

作者: differ_iOSER | 来源:发表于2021-08-20 09:57 被阅读0次

iOS 逆向开发 文章汇总

目录



相关资料下载链接: https://pan.baidu.com/s/1MKKYtjasGPblXDSWGwjz6w 密码: c3so

一、代码注入

一般修改原始的程序,是利用代码注入的方式,注入代码就会选择利用FrameWork或者Dylib等三方库的方式注入。

  • Framwork注入

    • 通过Xcode新建Framwork,将库安装进入APP包
    • 通过yololib注入Framwork库路径。命令:$yololib(空格)MachO文件路径(空格)库路径
      • 所有的Framwork加载都是由DYLD加载进入内存被执行的
      • 注入成功的库路径会写入到MachO文件的LC_LOAD_DYLIB字段中
  • Dylib注入

    • 通过Xcode新建Dylib库(注意:Dylib属于MacOS所以需要修改属性)
    • 添加Target依赖,让Xcode将自定义Dylib文件打包进入APP包。
    • 利用yololib进行注入。

1.1 Framwork注入演示

接着上一篇文章将WeChat重签名安装到了真机上:

项目-->Products-->Show in Finder-->显示包内容-->将WeChat可执行文件拷贝出来-->将WeChat 拖入到MachOView

MachO通过Load Commands告诉dyld需要加载的各种库以及库的位置(@rpath)参考:iOS-开发进阶05:动态库

1.1.1 创建动态库MyHook

1.1.2 添加Inject类

Build项目既可在包内容中看到MyHook添加到WeChat的Frameworks中了

Inject.m中添加如下代码并重新Build、安装到手机

+ (void)load {
    NSLog(@"\n\n注入成功!\n\n");
}

现在运行项目Inject.m中的load方法是不能执行的。虽然WeChat的Frameworks中加入了MyHook,但WeChat的MachO中没有MyHook 相关的Load Command。因此需要修改MachO才能让dyld加载MyHook。

1.1.3 修改MachO
yololib:专门用来修改MachO文件的(添加Load Command字段)
修改appSign.sh脚本,最后一行添加修改MachO的命令

./yololib "$TARGET_APP_PATH/$APP_BINARY"  "Frameworks/MyHook.framework/MyHook"

拷贝yololib到appSign.sh同级目录-->Command + Shift + K --->Command + R直接安装到真机

可以看到MachO中已经添加了MyHook 相关的Load Command

1.2 Dylib注入演示

新建项目Dylib注入--->安装项目到真机--->拷贝Shell脚本、ipa包、yololib--->Build Phase添加脚本执行命令--->将重签名的包安装到真机上

1.2.1 创建Dylib:MyHooK

1.2.2 修改Base SDK和签名

1.2.3 Copy Files

1.2.4 MyHooK.m添加代码

+ (void)load {
    NSLog(@"\n\n注入成功!!!\n\n");
}

1.2.5 编译MyHooK和项目(Dylib注入),将libMyHooK.dylib添加进Frameworks中

1.2.6 修改appSign.sh脚本,最后一行添加修改MachO的命令

./yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/libMyHooK.dylib"

1.2.7 安装项目到真机
Command + Shift + K --->Command + R直接安装到真机(不要先Build再安装不然会导致ibMyHooK.dylib无法添加进Frameworks中)

二、MethodSwizzle

利用OC的Runtime特性,动态改变SEL(方法编号)和IMP(方法实现)的对应关系,达到OC方法调用流程改变的目的。主要用于OC方法

多种HOOK方式

  1. class_addMethod方式:
    利用AddMethod方式,让原始方法可以被调用,不至于因为找不到SEL而崩溃

  2. class_replaceMethod方式:
    利用class_replaceMethod,直接给原始的方法替换IMP

  3. method_setImplementation方式:
    利用method_setImplementation,直接重新赋值原始的新的IMP

2.1 拿到注册方法

2.1.1 继续使用在上面1.1的WeChat项目,安装WeChat到真机,开启Debug调试

Target:WCAccountLoginControlLogic(控制器)
Action:onFirstViewRegister(注册方法)

2.1.2 添加MethodSwizzle方法

#import <objc/runtime.h>
+ (void)load {
    NSLog(@"\n\n注入成功!\n\n");
    
    Class class = objc_getClass("WCAccountLoginControlLogic");
    
    SEL originalSelector = @selector(onFirstViewRegister);
    SEL swizzledSelector = @selector(my_register);
    
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
    
    method_exchangeImplementations(originalMethod, swizzledMethod);
}

- (void) my_register {
    NSLog(@"my_register");
}

2.2 拿到登录密码

2.2.1 使用class-dump静态分析WeChat可执行文件

  • 将class-dump和WeChat可执行文件拷贝到同一目录下
  • 执行以下命令
./class-dump -H WeChat -o ./headers/
  • 将导出的headers拖入到Sublime Text打开

  • 参照2.1.1 拿到登录界面的控制器:WCAccountNewPhoneVerifyViewController 和登录方法:onNext

  • Command + Shift + F 查找@interface WCAccountNewPhoneVerifyViewController

  • 双击进入WCAccountNewPhoneVerifyViewController

由于onNext方法没有参数因此是通过控件传递的参数

  • 继续搜索可以看到m_textField属性
    @interface WCAccountTextFieldItem : WCBaseTextFieldItem
    @interface WCBaseTextFieldItem : WCBaseInfoItem
    {
    WCUITextField *m_textField;
    }
    @interface WCUITextField : UITextField

使用class-dump只能dump出OC相关的方法,不能dump Swift的方法。并且dump出的也不是头文件,可执行文件中本来也没有头文件,class-dump只是类似头文件形式的格式方便我们查看

  • 验证

2.2.2 代码中拿到登录密码
改变MethodSwizzle中交换的方法

  • 方法一:class_addMethod
#import <UIKit/UIKit.h>
+ (void)load {
    NSLog(@"\n\n注入成功!\n\n");
    
    Class class = objc_getClass("WCAccountNewPhoneVerifyViewController");
    
    SEL originalSelector = @selector(onNext);
    SEL swizzledSelector = @selector(my_onNext);
    
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    
    // VC中没有my_onNext(如果是在分类中操作就没有这个问题)
    class_addMethod(class, swizzledSelector, my_onNext, "v@:");

    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    method_exchangeImplementations(originalMethod, swizzledMethod);
}

// 新的IMP
void my_onNext(id self, SEL _cmd) {
    NSLog(@"my_onNext");
    
    UITextField *pwd = (UITextField *)[[self valueForKey:@"_textFieldPwdItem"] valueForKey:@"m_textField"];
    NSLog(@"密码是:%@", pwd.text);
    
    // 调回原来的方法
    [self performSelector:@selector(my_onNext)];
}
  • 方法二:class_replaceMethod
+ (void)load {
    NSLog(@"\n\n注入成功!\n\n");
    
    Class class = objc_getClass("WCAccountNewPhoneVerifyViewController");
    old_onNext  = class_replaceMethod(class, @selector(onNext), my_onNext, "v@:");
}

// 原来的IMP
IMP (*old_onNext)(id self, SEL _cmd);

// 新的IMP
void my_onNext(id self, SEL _cmd) {
    NSLog(@"my_onNext");
    
    UITextField *pwd = (UITextField *)[[self valueForKey:@"_textFieldPwdItem"] valueForKey:@"m_textField"];
    NSLog(@"密码是:%@", pwd.text);
    
    // 调回原来的方法
    old_onNext(self, _cmd);
}
  • 方法三:method_setImplementation
+ (void)load {
    NSLog(@"\n\n注入成功!\n\n");
    
    Class class = objc_getClass("WCAccountNewPhoneVerifyViewController");
    Method originalMethod = class_getInstanceMethod(class, @selector(onNext));
    old_onNext  = method_getImplementation(originalMethod);//原始的Method
    method_setImplementation(originalMethod, my_onNext);
}

// 原来的IMP
IMP (*old_onNext)(id self, SEL _cmd);

// 新的IMP
void my_onNext(id self, SEL _cmd) {
    NSLog(@"my_onNext");
    
    UITextField *pwd = (UITextField *)[[self valueForKey:@"_textFieldPwdItem"] valueForKey:@"m_textField"];
    NSLog(@"密码是:%@", pwd.text);
    
    // 调回原来的方法
    old_onNext(self, _cmd);
}

推荐使用方法二和方法三,更加安全

三、总结

  1. 代码注入
  • Framework注入、 Dylib注入
    • Xcode自动打包进入APP包
    • MachO中Load commonds里面需要有LC_LOAD_DYLIB字段
    • DYLD会加载我们的动态库!
  1. 案例:
  • 分析思路:
  • 动态调试:界面入手
  • 静态分析. class-dump: (头文件) 0C的类、方法列表。
  1. MethodSwizzle (Runtime) -重点! !
  • exchange函数去交换SEL 与IMP的对应关系(书的目录! ) .
    • 隐患:回不去了! ! ! (没法调用原来的实现!新方法写在分类中就不会出现这个问题)
    • 解决方法:
      • 添加方法列表,解决-过程比较复杂不推荐
      • replace函数替换IMP
      • getIMPsetIMP配合!推荐:逻辑清晰! ! (大部分HOOK框架使用的这个方式! ! )

参考

iOS-底层探索17:Method-Swizzling 方法交换

相关文章

网友评论

      本文标题:iOS 逆向开发13:代码注入

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