iOS逆向?qū)W習(xí)筆記 - 代碼注入

代碼注入過(guò)程

1、新建一個(gè)工程;
2、將微信Payload文件夾放入新建的工程中的APP文件夾里面;

$zip -ry WeChat.ipa Payload

3、在Build Phases里面添加New Run Script phase,將自動(dòng)化腳本路徑添加進(jìn)去;


1373790-4fb87d482fbc5747.png

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);

1373790-8ef43855f9bdbc09.png

這時(shí)編譯運(yùn)行是沒問(wèn)題的,但是沒有不會(huì)打印我們寫的代碼的。

8、將注入的framework庫(kù)添加到MachO文件里面;

這時(shí)需要用到一個(gè)工具yololib,并將它放到Mac電腦的/usr/local/bin里面。

1373790-892f31bef64c1d82.png
$yololib WeChat Frameworks/colinHookFrameWork.framework/colinHookFrameWork

9、用MachOView工具查看WeChat的MachO文件,查看加入的framework路徑;

1373790-85a700eeaac2968c.png

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

1373790-cd3791d587ee5c79.png

Dylib庫(kù)注入過(guò)程

1、新建一個(gè)工程;
2、將微信Payload文件夾放入新建的工程中的APP文件夾里面;

$zip -ry WeChat.ipa Payload

3、在Build Phases里面添加New Run Script phase,將自動(dòng)化腳本路徑添加進(jìn)去;

1373790-a322202306c0220a.png

4、添加Dylib庫(kù)

1373790-190466a2c193f479.png

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

1373790-99177d2735b5c902.png

b、證書也是Mac Developer證書

1373790-88685024aaf3068f.png

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

1373790-3fc820932b33c3df.png

5、新建的工程和Dylib庫(kù)進(jìn)行關(guān)聯(lián)

關(guān)聯(lián)的意義就是為了后續(xù)在工程Build的時(shí)候?qū)ylib庫(kù)添加到app里面去。

1373790-9b6ce7e680d20ebd.png

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

1373790-c6a691906623bc9c.png

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

1373790-61ca079b719b555a.png
1373790-fdec4262c8157474.png

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 "注入完成"

1373790-842f0a6142571012.png

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ù)中,寫上自己想要注入的代碼
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容