代码注入
一般修改原始的程序,是利用代码注入的方式,注入代码就会选择利用FrameWork或者Dylib等第三方库的方式注入
注入步骤
Framework 注入
- 通过Xcode新建Framework,将库安装进入App包
- 通过yololib注入Framework库路径,命令:$yololib MachO文件路径 库路径
所有的famework加载都是由DYLD加载进入内存被执行的
注入成功的库路径会写入到MachO文件的LC_LOAD_DYLIB字段中
Framework 实操
-
先下载yololib二进制到/usr/local/bin 目录下
Snip20200424_74.png
-
新建Xcode工程,目录结构如下
Snip20200424_75.png
-
建立Framework(TestHook)
Snip20200424_76.png
Snip20200424_77.png
Snip20200424_78.png
+ (void)load{
NSLog(@"test InjectCode");
}
@end
- 将需要注入代码的ipa放入到APP目录下
-
配置Run Script脚本
Snip20200424_79.png
# ${SRCROOT} 它是工程文件所在的目录
TEMP_PATH="${SRCROOT}/Temp"
#资源文件夹,我们提前在工程目录下新建一个APP文件夹,里面放ipa包
ASSETS_PATH="${SRCROOT}/APP"
#目标ipa包路径
TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa"
#清空Temp文件夹
rm -rf "${SRCROOT}/Temp"
mkdir -p "${SRCROOT}/Temp"
#----------------------------------------
# 1. 解压IPA到Temp下
unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH"
# 拿到解压的临时的APP的路径
TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
# echo "路径是:$TEMP_APP_PATH"
#----------------------------------------
# 2. 将解压出来的.app拷贝进入工程下
# BUILT_PRODUCTS_DIR 工程生成的APP包的路径
# TARGET_NAME target名称
TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"
echo "app路径:$TARGET_APP_PATH"
rm -rf "$TARGET_APP_PATH"
mkdir -p "$TARGET_APP_PATH"
cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH"
#----------------------------------------
# 3. 删除extension和WatchAPP.个人证书没法签名Extention
rm -rf "$TARGET_APP_PATH/PlugIns"
rm -rf "$TARGET_APP_PATH/Watch"
#----------------------------------------
# 4. 更新info.plist文件 CFBundleIdentifier
# 设置:"Set : KEY Value" "目标文件路径"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"
#----------------------------------------
# 5. 给MachO文件上执行权限
# 拿到MachO文件的路径
APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
#上可执行权限
chmod +x "$TARGET_APP_PATH/$APP_BINARY"
#----------------------------------------
# 6. 重签名第三方 FrameWorks
TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks"
if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ];
then
for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"*
do
#签名
/usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK"
done
fi
#注入(这一步是注入核心)
yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/TestHook.framework/TestHook"
- 编译安装
如果出现Unable to install .... 可能是Framework的版本高于手机版本,或者是没有embed & sign
如果脚本中没有执行yololib这条指令的话,动态库是没有被注入的,虽然安装的app的Framework目录下包含来我们自定义的动态库TestHook
Snip20200424_83.png
但是其实是没有加载到的,我们可以通过MachOView这个工具,查看这个重签名的ipa的二进制文件
Snip20200424_8.png
Snip20200424_9.png
Snip20200424_10.png
可以看到TestHook其实并没有加载到里面,所以终端也并没有输出;
另外使用yololib注入的
Snip20200424_7.png
是可以看到TestHook是已经注入的,并且终端也是有打印输出的
Snip20200424_4.png
Dylib 实操
Dylib注入
- 通过Xcode新建Dylib库(注意:Dylib属于MacOS所以需要修改属性)
- 添加Target依赖,让Xcode将定义Dylib文件打包进入APP包。
- 利用yololib进行注入
其实操作和Framework注入的操作差不多的,区别的不同仅仅在于形式而已
#注入
yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/TestHook.dylib"
Method Swizzle
利用OC的Runtime特性,动态改变SEL(方法编号)和IMP(方法实现)的对应关系,达到OC方法调用流程改变的目的。主要用于OC方法
在OC中,SEL和IMP之间的关系,就好像一本书的目录。SEL是方法编号,就像标题一样,IMP是方法实现的真是地址,就像页码一样,两者之间是一一对应关系,Runtime提供了交换两个SEL和IMP对应关系的函数
OBJC_EXPORT void method_exchangeImplementations(Method _Nonnull m1,Method _Nonull m2) OBJC_
AVAILABLE(10.5,2.0,9.0,1.0,2.0);
通过这个函数交换两个SEL和IMP丢应关系的技术,我们称之为Method Swizzle
image.png
例子说明
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/中文"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//发请求
NSLog(@"%@",request);
}
这种情况下,终端打印出来的结果会是MethodSwizzle[3940:1232344] <NSURLRequest: 0x15fdad630> { URL: (null) },因为中文没有经过转义,针对这个情形,我们可以对URL方法进行hook,添加一个分类如下
+(void)load
{
Method URLWithStr = class_getClassMethod(self, @selector(URLWithString:));
Method HKURL = class_getClassMethod(self, @selector(HKURLWithStr:));
//交换
method_exchangeImplementations(URLWithStr, HKURL);
}
+(instancetype)HKURLWithStr:(NSString *)str{
//调用系统原来的方法
NSURL * url = [NSURL HKURLWithStr:str];
if (url == nil) {
str = [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
}
url = [NSURL HKURLWithStr:str];
return url;
}
可以看到输入结果:2020-04-26 10:41:53.522 MethodSwizzle[3954:1233403] <NSURLRequest: 0x125e5ab50> { URL: https://www.baidu.com/%E4%B8%AD%E6%96%87 }
多种HOOK方式
- class_addMethod方式:
利用AddMethod方式,让原始方法可以被调用,不至于因为找不到SEL而奔溃
- class_replaceMethod方式:
利用class_replaceMethod,直接改原始的方法替换IMP
- method_selImplementation方式:
利用method_setImplementation,直接重新赋值给原始的新的IMP













网友评论