代碼注入過(guò)程
1、新建一個(gè)工程;
2、將微信Payload文件夾放入新建的工程中的APP文件夾里面;
$zip -ry WeChat.ipa Payload
3、在Build Phases里面添加New Run Script phase,將自動(dòng)化腳本路徑添加進(jìn)去;

4、給自動(dòng)化腳本權(quán)限;
$chmod +x XcodeApp.sh
5、編譯下工程,能正常通過(guò);
6、在工程中添加一個(gè)target framework并添加一個(gè)ColinHook類;
@implementation ColinHook
+ (void)load {
NSLog(@"????????????????????????????????????????????????????????");
}
@end
7、將工程target和framework target關(guān)聯(lián);

這時(shí)編譯運(yùn)行是沒問(wèn)題的,但是沒有不會(huì)打印我們寫的代碼的。
8、將注入的framework庫(kù)添加到MachO文件里面;
這時(shí)需要用到一個(gè)工具yololib,并將它放到Mac電腦的/usr/local/bin里面。

$yololib WeChat Frameworks/colinHookFrameWork.framework/colinHookFrameWork
9、用MachOView工具查看WeChat的MachO文件,查看加入的framework路徑;

10、將第9步的WeChat的MachO文件放到工程根目錄的APP文件夾/Payload/WeChat.app里面,執(zhí)行第2步,并編譯運(yùn)行工程,到此代碼就注入成功了;

Dylib庫(kù)注入過(guò)程
1、新建一個(gè)工程;
2、將微信Payload文件夾放入新建的工程中的APP文件夾里面;
$zip -ry WeChat.ipa Payload
3、在Build Phases里面添加New Run Script phase,將自動(dòng)化腳本路徑添加進(jìn)去;

4、添加Dylib庫(kù)

a、這個(gè)是在Mac里面使用的動(dòng)態(tài)庫(kù)

b、證書也是Mac Developer證書

c、在Debug模式下Build后,Dylib動(dòng)態(tài)庫(kù)的路徑和App包放的路徑不一樣

5、新建的工程和Dylib庫(kù)進(jìn)行關(guān)聯(lián)
關(guān)聯(lián)的意義就是為了后續(xù)在工程Build的時(shí)候?qū)ylib庫(kù)添加到app里面去。

6、修改Build Setting -> Per-configuration Intermediate Build Files Path

7、修改Dylib庫(kù)的架構(gòu)配置(Base SDK改成iOS配置即可)


8、將Dylib注入到MachO文件
# 7\. 注入我們編寫的動(dòng)態(tài)庫(kù)
echo "開始注入"
# 需要注入的動(dòng)態(tài)庫(kù)的路徑 這個(gè)路徑我就寫死了!
INJECT_FRAMEWORK_RELATIVE_PATH="Frameworks/libColinHook.dylib"
#
## 通過(guò)工具實(shí)現(xiàn)注入
yololib "$TARGET_APP_PATH/$APP_BINARY" "$INJECT_FRAMEWORK_RELATIVE_PATH"
echo "注入完成"

9、在Dylib中寫注入代碼,并編譯運(yùn)行
[圖片上傳中...(1373790-69cc9df55b22e128.png-6787b2-152645511906
Method Swizzle
MethodSwizzleManager.h
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface MethodSwizzleManager : NSObject
+(void)HookClass:(Class)class withOldMethod:(SEL)oldMethod withNewMethod:(SEL)newMethod;
@end
MethodSwizzleManager.m
#import "MethodSwizzleManager.h"
@implementation MethodSwizzleManager
+(void)HookClass:(Class)class withOldMethod:(SEL)oldMethod withNewMethod:(SEL)newMethod {
Method old = class_getInstanceMethod(class, oldMethod);
Method new = class_getInstanceMethod(class, newMethod);
method_exchangeImplementations(old, new);
}
@end
Hook自己工程中交換實(shí)例方法和類方法的實(shí)現(xiàn)
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//交換實(shí)例方法實(shí)現(xiàn)
// [MethodSwizzleManager HookClass:self.class withOldMethod:@selector(oldMethod) withNewMethod:@selector(newMethod)];
//交互類方法實(shí)現(xiàn)
[MethodSwizzleManager HookClass:object_getClass(self.class) withOldMethod:@selector(oldClassMethod) withNewMethod:@selector(newClassMethod)];
}
+ (void)newClassMethod {
NSLog(@"newClassMethod被調(diào)用");
}
+ (void)oldClassMethod {
NSLog(@"oldClassMethod被調(diào)用");
}
- (void)newMethod {
NSLog(@"newMethod被調(diào)用");
}
- (void)oldMethod {
NSLog(@"oldMethod被調(diào)用");
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// [self oldMethod];
[ViewController oldClassMethod];
}
Hook微信的注冊(cè)方法
1、使用注入Framework庫(kù)的工程來(lái)做這份案例
2、修改shell腳本,將Framework庫(kù)添加到MachO文件
# ---------------------------------------------------
# 7\. 注入我們編寫的動(dòng)態(tài)庫(kù)
echo "開始注入"
# 需要注入的動(dòng)態(tài)庫(kù)的路徑 這個(gè)路徑我就寫死了!
INJECT_FRAMEWORK_RELATIVE_PATH="Frameworks/colinHookFrameWork.framework/colinHookFrameWork"
#INJECT_FRAMEWORK_RELATIVE_PATH="Frameworks/libColinHook.dylib"
#
## 通過(guò)工具實(shí)現(xiàn)注入
# yololib MachO名稱
yololib "$TARGET_APP_PATH/$APP_BINARY" "$INJECT_FRAMEWORK_RELATIVE_PATH"
echo "注入完成"
3、運(yùn)行工程,查看微信注冊(cè)按鈕
Target <WCAccountLoginControlLogic: 0x104de6930>
Action onFirstViewRegester

4、將微信的頭文件導(dǎo)出,查看WCAccountLoginControlLogic類
class-dump -H WeChat -o /Users/yaoqi/Desktop/Headers
將Headers文件夾拖到Sublime Text工具,使用快捷鍵Cmd+Shift+F查找WCAccountLoginControlLogic,雙擊進(jìn)入WCAccountLoginControlLogic.h文件

5、運(yùn)行工程,Hook微信注冊(cè)方法

自動(dòng)化Shell注入腳本
# ${SRCROOT} 為工程文件所在的目錄
TEMP_PATH="${SRCROOT}/Temp"
#資源文件夾,放三方APP的
ASSETS_PATH="${SRCROOT}/APP"
#ipa包路徑
TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa"
#新建Temp文件夾
rm -rf "$TEMP_PATH"
mkdir -p "$TEMP_PATH"
# --------------------------------------
# 1\. 解壓IPA 到Temp下
unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH"
# 拿到解壓的臨時(shí)APP的路徑
TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
# 這里顯示打印一下 TEMP_APP_PATH變量
echo "TEMP_APP_PATH: $TEMP_APP_PATH"
# -------------------------------------
# 2\. 把解壓出來(lái)的.app拷貝進(jìn)去
#BUILT_PRODUCTS_DIR 工程生成的APP包路徑
#TARGET_NAME target名稱
TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"
echo "TARGET_APP_PATH: $TARGET_APP_PATH"
rm -rf "$TARGET_APP_PATH"
mkdir -p "$TARGET_APP_PATH"
cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH/"
# -------------------------------------
# 3\. 為了是重簽過(guò)程簡(jiǎn)化,移走extension和watchAPP. 此外個(gè)人免費(fèi)的證書沒辦法簽extension
echo "Removing AppExtensions"
rm -rf "$TARGET_APP_PATH/PlugIns"
rm -rf "$TARGET_APP_PATH/Watch"
# -------------------------------------
# 4\. 更新 Info.plist 里的BundleId
# 設(shè)置 "Set :KEY Value" "目標(biāo)文件路徑.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"
# 5.給可執(zhí)行文件上權(quán)限
#添加ipa二進(jìn)制的執(zhí)行權(quán)限,否則xcode會(huì)告知無(wú)法運(yùn)行
#這個(gè)操作是要找到第三方app包里的可執(zhí)行文件名稱,因?yàn)閕nfo.plist的 'Executable file' key對(duì)應(yīng)的是可執(zhí)行文件的名稱
#我們grep 一下,然后取最后一行, 然后以cut 命令分割,取出想要的關(guān)鍵信息。存到APP_BINARY變量里
APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
#這個(gè)為二進(jìn)制文件加上可執(zhí)行權(quán)限 +X
chmod +x "$TARGET_APP_PATH/$APP_BINARY"
# -------------------------------------
# 6\. 重簽第三方app Frameworks下已存在的動(dòng)態(tài)庫(kù)
TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks"
if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ];
then
#遍歷出所有動(dòng)態(tài)庫(kù)的路徑
for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"*
do
echo "????????????FRAMEWORK : $FRAMEWORK"
#簽名
/usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK"
done
fi
# ---------------------------------------------------
# 7\. 注入我們編寫的動(dòng)態(tài)庫(kù)
echo "開始注入"
# 需要注入的動(dòng)態(tài)庫(kù)的路徑 這個(gè)路徑我就寫死了!
INJECT_FRAMEWORK_RELATIVE_PATH="Frameworks/colinHookFrameWork.framework/colinHookFrameWork"
#INJECT_FRAMEWORK_RELATIVE_PATH="Frameworks/libColinHook.dylib"
#
## 通過(guò)工具實(shí)現(xiàn)注入
# yololib MachO名稱
yololib "$TARGET_APP_PATH/$APP_BINARY" "$INJECT_FRAMEWORK_RELATIVE_PATH"
echo "注入完成"
總結(jié)
- 利用動(dòng)態(tài)庫(kù)注入(Framework庫(kù)、Dylib庫(kù))
- 注入進(jìn)APP(工程和動(dòng)態(tài)庫(kù)有關(guān)聯(lián)關(guān)系)
- 修改MachO文件的Load Commands
- 在注入的動(dòng)態(tài)庫(kù)中,寫上自己想要注入的代碼