瞭解了對砸殼應用重簽名之後,發現在一些應用中做了對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名稱,請自行修改代碼.