上一篇我们利用终端,xcode以及脚本完成了应用重签名,接下来我们看看如何将代码注入。
动态库注入
- 之前构建工程的步骤相同。
- 在工程中创建一个FYHook动态库,添加+load代码
- 编译将wechat可执行文件通过
yololib
工具注入动态库
./yololib WeChat Frameworks/FYHook.framework/FYHook
- 压缩为ipa包
zip -ry WeChat.ipa Payload/
-
放入工程中
-
cmd + shift + k清空 ,运行,结果如下
dylib注入
1、通过Xcode新建Dylib库(注意:Dylib属于MacOS所以需要修改相关属性配置)
2、添加Target依赖,让Xcode将自定义Dylib文件打包进入APP包。
3、利用yololib进行注入。
脚本注入
通过脚本使用yololib注入
在脚本中添加
./yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/FYHook.framework/FYHook"
通过methodswizzing修改执行流程
通过LLDB可以看到注册按钮调用了<WCAccountLoginControlLogic: 0x283fd48c0>对象的onFirstViewRegister方法
破坏注册:
获取登录密码:
class-dump可以根据macho生成所有的头文件
./class-dump -H WeChat -o ./headers/
使用sublime或者vscode打开
可以看到所有的成员和方法
可以看到密码控件的基类里面有m_textField类型的成员变量,所以我们可以通过kvc的形式获取
这里可以看到的确获取到了密码,但是会挂掉,这也是MethodSwizzing的问题,这里可以看我之前写的谈谈Method-Swizzing的那些坑点
这里我分析一下崩溃的原因:因为当前我们使用的是类进行方法交换,而不是分类,所以原有类里面没有myOnNext 的selector,所以会挂掉。
可以这么写
+ (void)load {
//原始Method
Method onNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(onNext));
//WCAccountMainLoginViewController添加函数
class_addMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(myOnNext), myOnNext, "v@:");
method_exchangeImplementations(onNext, class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(myOnNext)));
}
void myOnNext(id self, SEL _cmd) {
UITextField * pwd = (UITextField *)[[self valueForKey:@"_textFieldUserPwdItem"] valueForKey:@"m_textField"];
NSLog(@"密码是%@", pwd.text);
[self performSelector:@selector(myOnNext)];
}
也可以这么写
+ (void)load {
//原始Method
Method onNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(onNext));
//WCAccountMainLoginViewController添加函数
old_onNext = class_replaceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector((onNext)), myOnNext, "v@:");
}
IMP(*old_onNext)(id self, SEL _cmd);
void myOnNext(id self, SEL _cmd) {
UITextField * pwd = (UITextField *)[[self valueForKey:@"_textFieldUserPwdItem"] valueForKey:@"m_textField"];
NSLog(@"密码是%@", pwd.text);
old_onNext(self,_cmd);
}
还可以这么写
+(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);
//objc_msgSend();
}
结果: