1. 程式人生 > IOS開發 >iOS 應用簽名原理及重籤技術

iOS 應用簽名原理及重籤技術

一、應用簽名原理

(一)程式碼簽名

  • 程式碼簽名是對可執行檔案或指令碼進行數字簽名.用來確認軟體在簽名後未被修改或損壞的措施。和數字簽名原理一樣,只不過簽名的資料是程式碼而已.
    • 1、簡單的程式碼簽名
      • 1.蘋果官方生成非對稱加密的一對公私鑰,在iOS的系統中內建一個公鑰,私鑰由蘋果後臺儲存;
      • 2.開發者上傳APP到AppStore時,蘋果後臺用私鑰對APP資料進行簽名(即先進行Hash得到hash值,再用私鑰加密hash值得到“RSAHash”);
      • 3.iOS系統下載這個APP後,用公鑰驗證這個簽名,若簽名正確,這個APP肯定是由蘋果後臺認證的,並且沒有被修改過,也就達到了蘋果的需求:保證安裝的每一個APP都是經過蘋果官方允許的。(公鑰解密“RSAHash”得到hash,在對應用包進行相同演算法的Hash得到hash1,驗證兩次Hash的值是否相同);
    • 2、蘋果實際需求
      • 1.安裝包不需要上傳到App Store,可以直接安裝到手機上.
        • 開發APP時直接真機除錯安裝
        • 企業內部分發的渠道,企業證書籤名的APP也是需要順利安裝的
      • 2.蘋果為了保證系統的安全性,又必須對安裝的APP有絕對的控制權
        • 經過蘋果允許才可以安裝
        • 不能被濫用導致非開發APP也能被安裝

(二)雙層程式碼簽名

  • 為了實現蘋果驗證應用的一些需求,iOS簽名的複雜度也就開始增加了,蘋果給出的方案是雙層簽名.
    雙層簽名原理圖
  • iOS的雙層程式碼簽名流程這裡簡單梳理一下,這也不是最終的iOS簽名原理,iOS的最終簽名在這個基礎上還要稍微加點東西。首先這裡有兩個角色,一個是iOS系統,還有一個就是我們的Mac系統,因為iOS的APP開發環境在Mac系統下,所以這個依賴關係成為了蘋果雙層簽名的基礎;
    • 1.蘋果自己有固定的一對公私鑰,跟之前AppStore原理一樣,私鑰在蘋果後臺,公鑰在每個iOS系統中.這裡稱為公鑰A,私鑰A;在Mac系統中生成非對稱加密演算法的一對公鑰\私鑰(你的Xcode幫你代辦了).這裡稱為公鑰M和私鑰M; A=Apple M = Mac
    • 2.把公鑰M以及一些你開發者的資訊,傳到蘋果後臺(這個就是CSR檔案);
    • 3.用蘋果後臺裡的私鑰A去簽名公鑰M。得到一份資料包含了公鑰M以及其簽名,把這份資料稱為證書。
    • 4.在開發時,編譯完一個APP後,用本地的私鑰M(今後你匯出的P12)對這個APP 進行簽名,同時把第三步得到的證書一起打包進 APP 裡,安裝到手機上;
    • 5.在安裝時,iOS系統取得證書;
    • 6.通過系統內建的公鑰A解籤,去驗證證書的數字簽名是否正確;
    • 7.驗證證書後確保公鑰M是蘋果認證過的;
    • 8.再用公鑰M去驗證APP的簽名,這裡就間接驗證了這個APP的安裝行為是否經過蘋果官方允許。(這裡只驗證安裝行為,不驗證APP是否被改動,因為開發階段 APP 內容總是不斷變化的,蘋果不需要管。)

(三)描述檔案

  • 描述檔案(Provisioning profile)一般包括三樣東西:證書、AppID、裝置。當我們在真機執行或者打包一個專案的時候,證書用來證明我們程式的安全性和合法性。
  • 蘋果為了解決應用濫用的問題,所以蘋果又加了兩個限制.
    • 在蘋果後臺註冊過的裝置才可以安裝.
    • 制籤名只能針對某一個具體的APP.
  • 並且蘋果還想控制App裡面的iCloud/PUSH/後臺執行/偵錯程式附加這些許可權,所以蘋果把這些許可權開關統一稱為Entitlements(授權檔案).並將這個檔案放在了一個叫做Provisioning Profile(描述檔案)檔案中.
  • 描述檔案是在AppleDevelop網站建立的(在Xcode中填上AppleID它會代辦建立),Xcode執行時會打包進入APP內.所以我們使用CSR申請證書時,我們還要申請一個東西!! 就是描述檔案!
  • 在開發時,編譯完一個APP後,用本地的私鑰M對這個APP進行簽名,同時把從蘋果伺服器得到的 Provisioning Profile檔案打包進APP裡,檔名為embedded.mobileprovision,把 APP 安裝到手機上.最後系統進行驗證。

二、應用重簽名

(一)codesign手動重籤

  • Xocde提供了簽名工具,codesign,我們通過幾個命令就可以完成重簽名。
  • 重簽名步驟:
    • 前期準備:
      • $codesign -vv -d WeChat.app 檢視應用簽名信息
      • $security find-identity -v -p codesigning 列出鑰匙串裡可簽名的證書
      • $otool-l "檔名" | grep cry 檢視machO檔案是否加密(cryptid 0/1)
    • 1.刪除外掛和帶有外掛的.app包(比如Watch,PlugIns)
    • 2.對Frameworks裡面的庫進行重簽名
      • $Codesign –fs “證書串” 檔名 強制替換籤名
    • 3.給可執行檔案 +x(可執行)許可權
      • $Chmod +x 可執行檔案 給檔案新增許可權
    • 4.新增描述檔案(新建工程,真機編譯得到)
      • $security cms -D -i ../embedded.mobileprovision 檢視描述檔案
    • 5.替換BundleID,info.plist 檔案內的BundleID修改
    • 6.通過授權檔案(Entilements)重籤.app包
      • $codesign -fs “證書串” --no-strict --entitlements=許可權檔案.plist APP包
      • $Zip –ry 輸出檔案 輸入檔案 將輸入檔案壓縮為輸出檔案
    • 7.cmd + shift + 2 直接安裝.app包,然後Attach to Process 可以將正在執行的應用附加到Xcode上,動態除錯;

(二)利用 Xode 重簽名

  • 重簽名步驟:
    • 1.新建同名工程,編譯出.app包,並替換為需要重籤的.app包;
    • 2.刪除外掛和帶有外掛的.app包(比如Watch,PlugIns)
    • 3.對Frameworks裡面的庫進行重簽名
      • $Codesign –fs “證書串” 檔名 強制替換籤名
    • 4.運行同名工程,重籤成功;
  • 注:1.非同名工程不會執行重籤包內容,machO檔案不能隨便修改,包括檔名;
    • 2.斷點除錯時,image list 可以檢視當前映象列表;

(三)SHELL指令碼

  • shell是一種特殊的互動式工具,它為使用者提供了啟動程式、管理檔案系統中檔案以及執行在系統上的程序的途徑。Shell一般是指命令列工具。它允許你輸入文字命令,然後解釋命令,並在核心中執行。
  • Shell指令碼,也就是用各類命令預先放入到一個文字檔案中,方便一次性執行的一個指令碼檔案

指令碼執行相關檔案

  • $source FileName

    • 意思:在當前shell環境中讀取並執行FileName中的命令
    • 特點:
      • 命令可以強行讓一個指令碼去立即影響當前的環境(一般用於載入配置檔案)。
      • 命令會強制執行指令碼中的全部命令,而忽略檔案的許可權。
  • $bash/zsh FileName

    • 意思:重新建立一個子shell,在子shell中執行腳本里面的句子。
  • $./FileName

    • 意思:讀取並執行檔案中的命令。但有一個前提,指令碼檔案需要有可執行許可權。

(四)使用者組&檔案許可權

  • Unix和Linux都是多使用者、多工的系統,所以這樣的系統裡面就擁有了使用者、組的概念。那麼同樣檔案的許可權也就有相應的所屬使用者和所屬組了。
1、Mac 檔案屬性

2、檔案型別與許可權(permission)
  • 檔案型別:(常見)
    • [d] 目錄(資料夾)(directory)
    • [-] 檔案
  • 檔案許可權:
    • [r]:read,讀 [w]:write,寫 [x]:execute,執行。
    • 注意:這三個許可權的位置不會變,依次是rwx,出現減號[-]在對應位置,代表沒有此許可權。
    • 一個檔案的完整許可權,總共分為三組:
      • 第一組:檔案所有者的許可權
      • 第二組:這一組其他使用者的許可權
      • 第三組:非本組使用者的許可權
3、改變許可權:chmod
  • 檔案許可權的改變使用chmod命令。設定方法有兩種:數字型別改變符號型別改變
    • 由於檔案許可權分為三種身份:[user][group][other]
    • 三個許可權:[read] [write] [execute]
  • 1.數字型別:
    • 各個許可權數字對照:r:4 w:2 x:1
    • 如果一個檔案許可權為 [–rwxr-xr-x ]
      • User : 4+2+1 = 7
      • Group: 4+0+1 = 5
      • Other: 4+0+1 = 5
      • 命令:chmod 755 檔名
    • 各種身份對應許可權計算
  • 2.符號型別:chmod [u、g、o、a][+(加入)/-(除去)/=(設定)][r、w、x] 檔名稱
    • eg. chmod a-w README.md

(五)shell指令碼自動重簽名

1、Xcode 新增執行指令碼的入口
2、shell檔案準備
# ${SRCROOT} 它是工程檔案所在的目錄
TEMP_PATH="${SRCROOT}/Temp"
#資原始檔夾,我們提前在工程目錄下新建一個APP資料夾,裡面放ipa包
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"
# 拿到解壓的臨時的APP的路徑
TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
# echo "路徑是:$TEMP_APP_PATH"

#----------------------------------------
# 2. 將解壓出來的.app拷貝進入工程下
# 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
#  設定:"Set : KEY Value" "目標檔案路徑"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"

#----------------------------------------
# 5. 給MachO檔案上執行許可權
# 拿到MachO檔案的路徑WeChat
APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
#上可執行許可權
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

#注入
yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/HankHook.framework/HankHook"
複製程式碼