代碼地址: github地址
如何預(yù)防此類代碼注入[IOS端監(jiān)測APP被代碼注入點(diǎn)擊查看
]
本文介紹的是ios的簡單代碼注入實現(xiàn)蓄坏,這次的APP用大千影視囤热,來實現(xiàn)代碼注入去廣告功能。這次代碼注入主要分為幾個部分:
使用一臺越獄手機(jī),通過frida-ios-dump砸殼大千影視.app獲得解密后的ipa包尿瞭。
通過mach-o view乾蛤,reveal,hopper-disassembler等軟件對該軟件進(jìn)行分析邑滨,找到相關(guān)方法日缨,進(jìn)行hook。
編寫sh腳本掖看,重新簽名app匣距。
如何通過rida-ios-dump砸殼面哥,網(wǎng)上有許多教程,十分簡單毅待,就不演示了尚卫。我們先編寫下sh腳本,來將導(dǎo)出的mach-o重新簽名變成自己的app尸红。代碼如下
# ${SRCROOT} 它是工程文件所在的目錄
TEMP_PATH="${SRCROOT}/Temp"
#資源文件夾吱涉,我們提前在工程目錄下新建一個APP文件夾,里面放ipa包
ASSETS_PATH="${SRCROOT}/APP"
#目標(biāo)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拷貝進(jìn)入工程下
# 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
# 設(shè)置:"Set : KEY Value" "目標(biāo)文件路徑"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"
#----------------------------------------
# 5. 給MachO文件上執(zhí)行權(quán)限
# 拿到MachO文件的路徑
APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
#上可執(zhí)行權(quán)限
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
將sh文件放到代碼根目錄下外里,再創(chuàng)建一個APP文件夾邑飒,然后將導(dǎo)出的app包放入APP文件夾下。如圖1:
接下來我們在BuildPhases內(nèi)添加腳本县匠,
然后添加腳本路徑风科,${SRCROOT}是本身代碼路徑的環(huán)境變量。
最后選擇真機(jī)運(yùn)行乞旦,代碼就會替換之前的app贼穆,將大千影視的app包重新簽名替換原來的mach-o文件。這樣我們的機(jī)子上就安裝了一個重簽了我們自己的證書的應(yīng)用
接下來我們通過xcode來調(diào)試下這個應(yīng)用
在這個播放頁面我們通過xcode 的view debug來查看廣告的窗口
通過class-dump導(dǎo)出頭文件
class-dump路徑 -H 需要導(dǎo)出的框架路徑 -o 導(dǎo)出的頭文件存放路
我們將這個導(dǎo)出的文件放到Sublime Text中
接下來我們需要新建一個動態(tài)庫framework和這個app包相關(guān)聯(lián)兰粉。
我們創(chuàng)建一個SQHook的framework故痊。
添加一個類InjectDelAD
#import "InjectDelAD.h"
@implementation InjectDelAD
+(void)load{
NSLog(@"你好!!~!!!!!!!!~~~~~~~");
}
@end
然后在腳本的最后添加
#注入
yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/SQHook.framework/SQHook"
yololib會將動態(tài)庫添的鏈接添加到mach-o的動態(tài)庫申明中玖姑。
現(xiàn)在load commands中沒有我們的動態(tài)庫聲明
保存好腳本重新編譯,這時候可以打印出來了愕秫。(注:要下載yololib源碼編譯出可執(zhí)行文件后放到/usr/local/bin下)
這時候再看mach-o文件,動態(tài)庫已經(jīng)掛載上去了焰络。
接下來我們開始調(diào)試戴甩,在廣告頁面我們點(diǎn)view debug
我們看到廣告頁面使用的是SaveAllSentientBeingsABeforeOrEndPlayADView,我們?nèi)倓倢?dǎo)出的.h文件中查找這個類
//
// Generated by class-dump 3.5 (64 bit) (Debug version compiled Sep 17 2017 16:24:48).
//
// class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2015 by Steve Nygard.
//
#import <UIKit/UIImageView.h>
@class GCDTimerTool, NewADModel, UIButton, UILabel;
@interface SaveAllSentientBeingsABeforeOrEndPlayADView : UIImageView
{
UILabel *_timerLabel;
UILabel *_noticeLabel;
NewADModel *_model;
GCDTimerTool *_timer;
UIButton *_fullScreenBtn;
UIButton *_backBtn;
UIImageView *_shadow;
}
+ (void)showWithPlayEndFlag:(_Bool)arg1 willPlayNext:(_Bool)arg2 PlayerView:(id)arg3 withModel:(id)arg4 closeHandler:(CDUnknownBlockType)arg5;
@property(retain, nonatomic) UIImageView *shadow; // @synthesize shadow=_shadow;
@property(retain, nonatomic) UIButton *backBtn; // @synthesize backBtn=_backBtn;
@property(retain, nonatomic) UIButton *fullScreenBtn; // @synthesize fullScreenBtn=_fullScreenBtn;
@property(retain, nonatomic) GCDTimerTool *timer; // @synthesize timer=_timer;
@property(retain, nonatomic) NewADModel *model; // @synthesize model=_model;
@property(retain, nonatomic) UILabel *noticeLabel; // @synthesize noticeLabel=_noticeLabel;
@property(retain, nonatomic) UILabel *timerLabel; // @synthesize timerLabel=_timerLabel;
- (void).cxx_destruct;
- (void)dealloc;
- (void)setBtnHidden;
- (void)layoutSubviews;
- (id)initWithCloseHandler:(CDUnknownBlockType)arg1;
@end
我們看到這個初始化方法- (id)initWithCloseHandler:(CDUnknownBlockType)arg1;這時候我們設(shè)置返回空闪彼,是不是就沒廣告呢甜孤。這個方法是oc方法可以用runtime方法交換進(jìn)行hook。
//
// InjectDelAD.m
// SQHook
//
// Created by Sem on 2020/8/26.
// Copyright ? 2020 SEM. All rights reserved.
//
#import "InjectDelAD.h"
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
@implementation InjectDelAD
+(void)load{
NSLog(@"你好畏腕!!~!!!!!!!!~~~~~~~");
Method initADView = class_getInstanceMethod(objc_getClass("SaveAllSentientBeingsABeforeOrEndPlayADView"), @selector(initWithCloseHandler:));
method_exchangeImplementations(initADView, class_getInstanceMethod(self, @selector(initWithCloseHandlerHook:)));
}
-(instancetype)initWithCloseHandlerHook:(id)arg{
NSLog(@"交換方法執(zhí)行~~~~~~~~~!!!");
return nil;
}
@end
再編譯下看下效果發(fā)現(xiàn)廣告沒了缴川。。描馅。
結(jié)束語:通過上述方法也可以去掉開機(jī)廣告等把夸,這部分的代碼注入只能hook掉oc方法,對于一些系統(tǒng)的函數(shù)什么的要使用其他的方式流昏,如fishhook什么的扎即,一些靜態(tài)函數(shù)需要更改mach-o文件等吞获。