代码注入(11)
framework注入
假工程里写代码不会走,是因为APP(MachO)文件整个都被替换了
- 通过Xcode新建Framwork,将库安装进入APP包
- 通过yololib注入Framwork库路径。命令:$yololib(空格)MachO文件路径(空格)库路径
- 所有的Framwork加载都是由DYLD加载进入内存被执行的
- 注入成功的库路径会写入到MachO文件的LC_LOAD_DYLIB字段中
Tips
- 注意: MachView(烂苹果) -> 拖拽打不开,右键打开文件可解决
- MachOView
流程
- 可执行文件 -> dyld加载 -> Load Commands -> LC_MAIN -> LC_LOAD_DYLIB加载动态库 (通过路径加载) -> 将自己的代码, 包装在一个动态库里面, 再让IPA加载 (以动态库的形式注入)
- framework里面的代码也要加载, framework里面也是可执行文件
yololib使用
需要修改MachO -> ./yololib WeChat framework路径
dylib也可以
- 通过Xcode新建Dylib库(注意:Dylib属于MacOS所以需要修改属性)
- 添加Target依赖,让Xcode将自定义Dylib文件打包进入APP包。
- 利用yololib进行注入。
添加lib -> 更改配置
用脚本yololib
shell脚本
./yololib "$TARGET_APP_PATH/$APP_BINARY" "framework路径"
Method Swizzle
framework注入
破坏微信, 窃取密码 -> 界面事件相应链,慢慢找
静态分析!!! -> class-dump (获取类,方法列表)
./class-dump -H WeChat -o ./headers/
Sublime Text -> onNext没有参数(self, _cmd)
第一种Hook
Method Swizzle 方法交互修正
//第一种 /** +(void)load{ //原始的Method Method onNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(onNext)); //添加新方法! class_addMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(new_onNext), new_onNext, "v@:"); //交换 method_exchangeImplementations(onNext, class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(new_onNext))); } //新的IMP void new_onNext(id self,SEL _cmd){ UITextField * pwd = (UITextField *)[[self valueForKey:@"_textFieldUserPwdItem"] valueForKey:@"m_textField"]; NSLog(@"密码是:%@",pwd.text); //调用回原来的逻辑!! //调用原来的方法! [self performSelector:@selector(new_onNext)]; }
隐患: 回不去了!!!(没法调用原来的实现!, 因为不是在该类的分类去交换的)
第二种
class_replaceMethod
/* +(void)load{ //原始的Method Method onNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(onNext)); old_onNext = class_replaceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(onNext), new_onNext, "v@:"); } //原来的IMP IMP (*old_onNext)(id self,SEL _cmd); //新的IMP void new_onNext(id self,SEL _cmd){ UITextField * pwd = (UITextField *)[[self valueForKey:@"_textFieldUserPwdItem"] valueForKey:@"m_textField"]; NSLog(@"密码是:%@",pwd.text); //调用回原来的逻辑!! //调用原来的方法! old_onNext(self,_cmd); //objc_msgSend(); }
第三种, 最好的, 推荐
大部分HOOK框架
method_getImplementation
method_setImplementation
+(void)load{ //原始的Method old_onNext = method_getImplementation(class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(onNext))); method_setImplementation(class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(onNext)), new_onNext); } //原来的IMP IMP (*old_onNext)(id self,SEL _cmd); //新的IMP void new_onNext(id self,SEL _cmd){ UITextField * pwd = (UITextField *)[[self valueForKey:@"_textFieldUserPwdItem"] valueForKey:@"m_textField"]; NSLog(@"密码是:%@",pwd.text); //调用回原来的逻辑!! //调用原来的方法! old_onNext(self,_cmd); }