iOS逆向編程第九篇:重簽名處理

為什么我們自己開發(fā)的App安裝包不能隨便安裝到任意的手機(jī)呢?App安裝包是自己的、手機(jī)是自己的,結(jié)果就是安裝失敗,有沒(méi)有想過(guò)這個(gè)問(wèn)題?下面我們來(lái)講講蘋果公司設(shè)計(jì)的對(duì)App安裝包的簽名機(jī)制,并重點(diǎn)的講解下怎么進(jìn)行重簽名以及反重簽名的做法。

一、代碼簽名原理

想要重簽名我們的APP安裝包,我們先來(lái)了解下APP原始包的簽名得到APP安裝包過(guò)程。先上整體的流程圖,然后再來(lái)解釋每一步操作的過(guò)程:

①:通過(guò)Mac電腦創(chuàng)建的CSR文件蘋果服務(wù)器申請(qǐng)證書CSR文件其實(shí)本質(zhì)是Mac電腦創(chuàng)建的一對(duì)RSA公私鑰中的公鑰M,我們把CSR文件傳給蘋果服務(wù)器蘋果服務(wù)器使用私鑰A對(duì)CSR文件進(jìn)行加密和hash簽名處理,生成一個(gè)證書文件。

②:我們從蘋果服務(wù)器下載證書描述文件并安裝到當(dāng)前的Mac電腦中,Mac電腦會(huì)將對(duì)應(yīng)的私鑰M證書綁定存放在一起。(在手動(dòng)管理證書的年代,為什么不能從蘋果服務(wù)器直接下載了證書使用,而是一定要從證書創(chuàng)建者的Mac電腦中導(dǎo)出證書呢?就是因?yàn)?code>私鑰M的存在,現(xiàn)在是不是就能理解了)

③:打包的過(guò)程中,Mac電腦會(huì)使用證書下的私鑰M對(duì)我們的原始APP包進(jìn)行簽名處理;并把證書以及描述文件都打包到APP的安裝包中。

④:當(dāng)我們的設(shè)備安裝APP時(shí),會(huì)先通過(guò)設(shè)備內(nèi)嵌的公鑰A對(duì)證書、描述文件做解密等處理,獲取其中的內(nèi)容,然后驗(yàn)證證書中的HASH值,來(lái)判斷證書是否合法;驗(yàn)證APP的簽名數(shù)據(jù),判斷APP是否被篡改過(guò);判斷當(dāng)前設(shè)備是否存在可安裝的設(shè)備列表中,判斷描述文件info.plist中的BundleID是否一致等等。

⑤:最后完成APP的安裝

Tips:提供一些查看或查找CSR文件、證書描述文件內(nèi)容使用到的命令

//查看CSR文件中的公鑰內(nèi)容
$cat CertificateSigningRequest.certSigningRequest

//查看CSR文件的其他信息(郵箱、加密方式、hash值算法)
$openssl asn1parse -i -in CertificateSigningRequest.certSigningRequest

//查看本機(jī)所有證書
$security find-identity -v -p codesigning

//查看描述文件的內(nèi)容
$security cms -D -i 描述文件路徑

二、通過(guò)終端命令手動(dòng)重簽名

我們?cè)谥睾灻?,需要提前?zhǔn)備一些重簽名必要的東西。

  • 砸過(guò)殼的IPA :可以去PP助手中下載越獄應(yīng)用,自己砸殼的文章之后再進(jìn)行分享;
  • 可正常使用證書 :重簽名IPA包,意思是指替換掉舊的簽名證書,使其能正常安裝;

有了以上準(zhǔn)備,我們就具體來(lái)試試手動(dòng)重簽名的操作。

第1步:解壓砸過(guò)殼的IPA包,刪除部分無(wú)法重簽名的文件

A:刪除`Payload` → `XXX.app` → `PlugIns`文件夾
B:刪除`Payload` → `XXX.app` → `Watch`文件夾

第2步:對(duì)PayloadXXX.appFramework文件夾下的XXX.framework進(jìn)行簽名。注意:如果IPA包中沒(méi)有Framework文件夾,則可以跳過(guò)這步

//進(jìn)入`XXX.app`目錄下,執(zhí)行如下命令(有很多`.framework`時(shí)需要多次執(zhí)行)
$codesign -fs "證書" 需要簽名的文件

第3步:App的可執(zhí)行文件讀寫權(quán)限。

//進(jìn)入`XXX.app`目錄下,執(zhí)行如下命令
$chmod +x 可執(zhí)行文件名稱

第4步:拷貝embedded.mobileprovision文件到Payload中,修改info.plist中的Bundle identifier

a. 將新證書的`embedded.mobileprovision`文件拷貝到`Payload`中
b. 將`info.plist`中的`Bundle identifier`值改為新證書對(duì)應(yīng)的`Bundle identifier`值

第5步:生成.plist的權(quán)限文件

a. 進(jìn)入`XXX.app`目錄下,使用命令查看描述文件:$security cms -D -i 描述文件路徑
b. 拷貝`Entitlements`鍵下的字典內(nèi)容,將字典內(nèi)容存儲(chǔ)在新建的`XX.plist`文件
c. 把新建的`XX.plist`文件拷貝到`Playload`文件夾中

第6步:簽名整個(gè)APP

//進(jìn)入`Payload`文件夾下,執(zhí)行如下命令
$codesign -fs "證書名稱"  --no-strict --entitlements=XX.plist XXX.app

//查看APP的簽名信息
$codesign -vv -d APP路徑

//查看可執(zhí)行文件的加密信息
$otool -l 可執(zhí)行文件名稱 | grep crypt

第7步:將已簽名的APP包打包成IPA文件

//進(jìn)入`Payload`的上級(jí)文件夾下,執(zhí)行如下命令
$zip -ry XXX.ipa Payload

注意:手動(dòng)重簽名會(huì)出現(xiàn)很多安裝異常的問(wèn)題,因?yàn)榭赡苡泻芏嘈〖?xì)節(jié)沒(méi)有處理或出現(xiàn)問(wèn)題,所以一般都使用Xcode進(jìn)行重簽名處理。

三、通過(guò)Xcode進(jìn)行重簽名

蘋果簽名的所有細(xì)節(jié)處理都已經(jīng)封裝在Xcode中,所以我們可以使用Xcode來(lái)替我們做簽名處理,只要替換Xcode簽名的目標(biāo)原文件達(dá)到欺騙Xcode的目的,使其對(duì)我們想要的原文件進(jìn)行簽名處理。

1、新建一個(gè)名為`AAA`的空工程,編譯、運(yùn)行使其安裝到真機(jī)中。
2、解壓砸過(guò)殼的`IPA`包,拷貝`Payload` → `XXX.app`到工程的`Products`下,重命名并替換`AAA.app`。
3、給`App`的可執(zhí)行文件讀寫權(quán)限,進(jìn)入`AAA.app`目錄下執(zhí)行命令:`$chmod +x 可執(zhí)行文件名稱`
4、刪除部分無(wú)法重簽名的文件;`①、刪除Payload→AAA.app→PlugIns文件夾;②、刪除Payload→AAA.app→Watch文件夾`
5、對(duì)`Payload`→`AAA.app`→`Framework`文件夾下的`XXX.framework`進(jìn)行簽名,進(jìn)入`AAA.app`目錄下執(zhí)行命令:`$codesign -fs "證書" 需要簽名的文件`
6、修改`AAA.app`→`info.plist`中的`Bundle identifier`值與當(dāng)前工程的`Bundle identifier`值一致。
7、使用快捷鍵`command+R`運(yùn)行當(dāng)前的工程,此時(shí)Xcode已經(jīng)完成了重簽名處理。

最后注意:如果`IPA`包中沒(méi)有`Framework`文件夾,則直接跳過(guò)第5步。

相比第一種手動(dòng)重簽名的方式,Xcode重簽名就相對(duì)簡(jiǎn)單多了!

四、通過(guò)Run Script腳本進(jìn)行重簽名

相對(duì)手動(dòng)重簽名,Xcode重簽名已經(jīng)簡(jiǎn)單很多了,但是還不是最簡(jiǎn)單的

第1步:新建一個(gè)空工程,在工程目錄下新建APP文件夾,將IPA包拷貝到APP目錄下。
第2步:選擇空工程Build Phases+New Run Script Phase添加一個(gè)腳本的入口
第3步:將如下的腳本內(nèi)容,拷貝到Run Script

# ${SRCROOT} 它是工程文件所在的目錄
TEMP_PATH="${SRCROOT}/Temp"
#資源文件夾
ASSETS_PATH="${SRCROOT}/APP"
#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"
# 拿到解壓的臨時(shí)的APP的路徑
TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
# echo "路徑是:$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 "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.個(gè)人證書沒(méi)法簽名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

五、重簽名APP的用處

描述了這么多的重簽名方法,有什么用處呢?當(dāng)然不只是簡(jiǎn)單的在一個(gè)設(shè)備上安裝多個(gè)相同應(yīng)用這么簡(jiǎn)單。比如蘋果商店有很多需要付費(fèi)下載的應(yīng)用,通過(guò)重簽名后,就能免費(fèi)進(jìn)行安裝和使用了;類似國(guó)內(nèi)中的同步推91助手等平臺(tái)提供很多免費(fèi)應(yīng)用,而這些應(yīng)用在App Store中可能就需要付費(fèi)下載了。所以大概總結(jié)了以下幾點(diǎn)重簽名的用途:
1、破解需付費(fèi)下載的應(yīng)用,比如:同步推、91助手等平臺(tái)。
2、通過(guò)注入Framework來(lái)Hook重簽名APP中的方法,修改代碼的執(zhí)行順序,比如:制作微信搶紅包的外掛。
3、動(dòng)態(tài)調(diào)試重簽名的APP,查看界面布局等,比如:探究競(jìng)爭(zhēng)對(duì)象發(fā)布的APP的新功能。

六、防止重簽名的處理

在逆向編程中,重簽名是一個(gè)很常用的的動(dòng)態(tài)調(diào)試基本操作,所以做重簽名的防護(hù)是很必要的一個(gè)步驟,下面來(lái)講下防止別人重簽名你的APP需要怎么處理。

我們先查看下Xcode使用的證書APP描述文件的對(duì)應(yīng)關(guān)系:
第1步:進(jìn)入Mac電腦中的鑰匙串中,選擇證書,雙擊簽名使用的證書,查看并拷貝組織單位編號(hào)。
第2步:進(jìn)入XXX.app路徑下,使用命令security cms -D -i embedded.mobileprovision查看embedded.mobileprovision內(nèi)容,找到key = application-identifier對(duì)應(yīng)的value值。

結(jié)合文章開篇所述的重簽名步驟來(lái)思考,在任何必要的時(shí)候(例如:APP啟動(dòng)等),是否可以通過(guò)檢測(cè)APP簽名證書中的組織單位ID是否與Xcdoe工程中的內(nèi)容一致來(lái)判斷當(dāng)前APP是否已經(jīng)被重簽名過(guò)。

void checkAppCodesignReplaced(NSString *bundleId)
{
    //描述文件路徑
    NSString *embeddedPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
    //讀取application-identifier注意描述文件的編碼要使用:NSASCIIStringEncoding
    NSString *embeddedProvisioning = [NSString stringWithContentsOfFile:embeddedPath encoding:NSASCIIStringEncoding error:nil];
    NSArray *embeddedProvisioningLines = [embeddedProvisioning componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
    for (int i = 0; i < embeddedProvisioningLines.count; i ++) {
        if ([embeddedProvisioningLines[i] rangeOfString:@"application-identifier"].location != NSNotFound) {
            NSInteger fromPosition = [embeddedProvisioningLines[i+1] rangeOfString:@"<string>"].location+8;
            NSInteger toPosition = [embeddedProvisioningLines[i+1] rangeOfString:@"</string>"].location;
            NSRange range = NSMakeRange(fromPosition, (toPosition - fromPosition));
            NSString *fullIdentifier = [embeddedProvisioningLines[i+1] substringWithRange:range];
            NSArray *identifierComponents = [fullIdentifier componentsSeparatedByString:@"."];
            NSString *appIdentifier = [identifierComponents firstObject];
       
            //對(duì)比簽名ID
            if (![appIdentifier isEqual:bundleId])  {
                asm( //exit
                    "mov X0,  #0\n"
                    "mov w16, #1\n"
                    "svc #0x80"
                    );
            }
            break;
        }
    }
}

注意:使用內(nèi)聯(lián)匯編代碼(asm)是防止逆向工程師通過(guò)符號(hào)斷點(diǎn)來(lái)定位exit的調(diào)用位置。

七、后續(xù)

在APP中僅僅加入防止重簽名是遠(yuǎn)遠(yuǎn)不夠的,對(duì)于逆向開發(fā)工程師來(lái)說(shuō),這種操作很容易就破解了。比如說(shuō)使用HOOK,替換判斷組織單位編號(hào)是否一致的方法,亦或是修改匯編代碼,使用b指令直接跳過(guò)驗(yàn)證方法等等。所以我們還需要做很多其他的處理,才能達(dá)到APP安全防護(hù)的目的,比如說(shuō):反HOOK防護(hù)、ptrace防護(hù)混淆關(guān)鍵代碼、隱藏敏感方法調(diào)用等。此篇文章記錄到此,其他的安全防護(hù)處理,在之后的文章另做的技術(shù)記錄。

?著作權(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)容