應用代碼注入

瞭解了對砸殼應用重簽名之後,發現在一些應用中做了對bundle identifier的校驗,自定的bundle identifer並不能通過校驗,這時候就需要嘗試添加一些代碼了.以下討論接着應用重簽名中QQ的重簽名繼續.

準備

在iOS的應用中,每個應用都會有一個elf(excutable and linkable file)類型的可執行文件,這個文件屬於apple獨有的mach O文件.這個文件保存在xxx.app路徑中,與應用同名.所以自定的代碼和系統函數的調用,都是通過這個文件來進行查找的.通過查看工具(例如MachOView).通過查看工具可以看到文件的內部組織形式:

每一個實現都會有一個路徑,來告訴系統該去哪裏加載這個庫文件的具體實現.所以如果可以將自定義的類庫寫入到這個文件中,系統就會主動加載自定義的實現文件,這樣就有機會對原始的實現做一些自定義的事情.假設你已經瞭解了:

  • Mach O文件的基本組織形式;
  • DYLD的基本工作原理;
  • 瞭解yololib的實現機制.

不瞭解也沒關係,幹就完了.

開始

在之前創建的myQQDemo項目裏,

  • 添加自定義的類庫(這裏使用framework爲例):

取名叫做EWInject.

  • 替換獲取bundle identifier的實現代碼:

創建一個繼承自NSObject的類,hook方法(實現有很多種方法,可以參考動態交換方法實現):

BOOL (*ori_application_didFinishLaunchingWithOptions)(id, SEL,UIApplication *, NSDictionary *);
BOOL ericy_application_didFinishLaunchingWithOptions(id self, SEL _cmd, UIApplication * application, NSDictionary *options) {
    NSDictionary *infoDictionary =  [[NSBundle mainBundle] infoDictionary];
    [infoDictionary setValue:@"com.tencent.mqq" forKey:@"CFBundleIdentifier"];
    ori_application_didFinishLaunchingWithOptions(self, _cmd, application, options);
    NSLog(@"infoDictionary == %@", infoDictionary);
    return true;
}
+ (void)load {
    //替換啓動方法
    NSLog(@"開始進行方法替換");
    Class class = objc_getClass("QQAddressBookAppDelegate");
    SEL sel = sel_registerName("application:didFinishLaunchingWithOptions:");
    Method method = class_getInstanceMethod(class, sel);
    ori_application_didFinishLaunchingWithOptions = (BOOL(*)(id, SEL, UIApplication *,NSDictionary *))method_setImplementation(method, (IMP)ericy_application_didFinishLaunchingWithOptions);
    
}
  • 使用Xcode進行編譯(cmd+B),獲取到生成的EWInject.framework文件,放入QQ.app/Frameworks路徑中;
  • 使用yololib寫入EWInject.framework的實現文件路徑:
yololib  Payload/QQ.app/QQ Frameworks/EWInject.framework/EWInject

不出意外的話,你可以看到:

不放心的話,可以使用

tool -l QQ | grep "EWInject"

或者MackOView進行確認:

  • 退回到QQ.app目錄,對QQ.app進行重新簽名
codesign -fs $certificate QQ.app --entitlements=ent.plist 
  • 退回Payload目錄,將整個目錄所有文件壓縮爲QQ.ipa
zip -ry QQ.ipa Payload
  • 使用Xcode安裝到手機.

不出意外的話,就可以正常安裝打開了. 

使用shell腳本重簽名

除了手動進行簽名外,還可以使用Xcode進行一部分工作.這樣的話,QQ.app的簽名就可以由Xcode來完成,減少了手動的工作.大致的步驟如下:

  • 使用Xcode創建一個新的工程,名字隨便取(例如WeChatDemo);
  • 在項目功能文件同級目錄
    • 創建APP文件夾,並將下載的ipa文件放入文件夾中;
    • 將腳本resign.sh放入工程文件同級目錄;
  • 在Target--->XXX--->Build Phases,點擊 "+",選擇 "New Run Script Phases" 創建一個Phases; 

  • 然後在新創建的Phases中;

  • 運行項目到手機.

附腳本代碼

#!/bin/sh

#  Resign.sh
#  WeChat
#
#  Created by Ericydong on 2020/1/7.
#  Copyright © 2020 EricyDong. All rights reserved.

#臨時存放解壓後文件的目錄
TEMP_PATH=${SRCROOT}/Temp
#存放原始ipa文件的目錄
ASSETS_PATH=${SRCROOT}/APP
#原始ipa文件的路徑
TARGET_IPA_PATH=${ASSETS_PATH}/*.ipa
if [ -d $TEMP_PATH ];then
rm -rf $TEMP_PATH
else
mkdir -p $TEMP_PATH
fi

#解壓ipa到Temp文件夾
unzip -oqq $TARGET_IPA_PATH -d $TEMP_PATH
#獲取解壓之後的app文件
TEMP_APP_PATH=`find ./Temp -maxdepth 2 -iname *.app`
echo "HERE $TEMP_APP_PATH"
if [ -d $TEMP_APP_PATH ];then
echo ".app文件存在:$TEMP_APP_PATH"
else
echo ".app不存在,請檢查原始ipa文件是否存在"
exit 0;
fi



#將.app移動到BUILT_PRODUCTS_DIR

TARGET_APP_PATH=$BUILT_PRODUCTS_DIR/${TARGET_NAME}.app
#獲取簽名證書
if [ -z $EXPANDED_CODE_SIGN_IDENTITY ]; then
    echo "$EXPANDED_CODE_SIGN_IDENTITY 變量爲空"
    EXPANDED_CODE_SIGN_IDENTITY=`codesign -d -vv $TARGET_APP_PATH 2>&1 | grep --after-context=1 "Signature size="`
    EXPANDED_CODE_SIGN_IDENTITY=${EXPANDED_CODE_SIGN_IDENTITY##*=}
fi



#拷貝文件中的描述文件進行保存
cp "$TARGET_APP_PATH/embedded.mobileprovision"  "$TARGET_APP_PATH/../embedded.mobileprovision"




rm -rf $TARGET_APP_PATH
cp -rf $TEMP_APP_PATH $TARGET_APP_PATH

#拷貝之前保存的描述文件到文件夾中
cp "$TARGET_APP_PATH/../embedded.mobileprovision" "$TARGET_APP_PATH/embedded.mobileprovision"
##刪除Plugin和Watch中的插件
rm -rf $TARGET_APP_PATH/Watch
rm -rf $TARGET_APP_PATH/PlugIns

#修改bundleidentifier
PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"

#echo "EXECUTABLE_NAME == $EXECUTABLE_NAME"
#二進制文件添加可執行權限

EXECUTABLE_NAME_REAL=`PlistBuddy -c "Print :CFBundleExecutable" "$TARGET_APP_PATH/Info.plist"`
chmod u+x $TARGET_APP_PATH/$EXECUTABLE_NAME_REAL

#簽名frameworks
TARGET_APP_FRAMEWORKS_PATH=$TARGET_APP_PATH/Frameworks
echo "TARGET_APP_FRAMEWORKS_PATH == $TARGET_APP_FRAMEWORKS_PATH"
if [ -d $TARGET_APP_FRAMEWORKS_PATH ];then
    cd $TARGET_APP_FRAMEWORKS_PATH
    allFrameworks=`ls $TARGET_APP_FRAMEWORKS_PATH`
    for framework in ${allFrameworks[@]}
    do
        codesign -fs "$EXPANDED_CODE_SIGN_IDENTITY" "$framework"
    done
fi

# 5. 添加自定義framework加載
    #獲取可執行文件的名稱
    EXECUTABLEFILE=`PlistBuddy -c "Print :CFBundleExecutable" "$TARGET_APP_PATH/Info.plist"`
#    echo "EXECUTABLEFILE == $EXECUTABLEFILE"
    
yololib  $TARGET_APP_PATH/$EXECUTABLEFILE Frameworks/EWInject.framework/EWInject

注意事項:

  • 腳本中,爲了方便使用,將PlistBuddy,yololib等工具均做了全局配置.如果你不知道相關的工具在本機上否存在,可以使用以下命令進行全局查找,如果查找到了相關文件,只需要將拷貝在/usr/local/bin目錄下即可.如果本機上沒有相關文件,需要進行下載安裝.
find / -iname PlistBuddy -type f
  • 腳本中,如果將新添加的framework名字固定了名字爲EWInject,如果使用了不同的自定義framework名稱,請自行修改代碼.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章