應用的構建過程與簽名
一、引言
在逆向開發的過程中,一些常用逆向工具和逆向分析的技巧已經被我們所熟知和運用,但其中所用到的理論基礎往往容易被忽略。理論基礎的儲備能夠拓寬逆向分析的思路,並在遇到問題時很快的找到原因和應對的方法,從而使得逆向開發的過程變得輕鬆。下面從基礎的包結構、包構建以及包安裝進行解讀。
二、應用包的格式
蘋果的應用包主要是ipa格式的,其本身就是zip的壓縮包,右鍵“歸檔實用工具”即可解壓包內的內容,拿訊飛輸入法舉例,它的應用包內容結構如下:
AestheticdeMBP:應用 aesthetic$ tree 訊飛輸入法-8.0.2336 -L 2
訊?\236?\223?\205??\225-8.0.2336
├── META-INF
│ ├── com.apple.FixedZipMetadata.bin
│ └── com.apple.ZipMetadata.plist
├── Payload
│ └── iFlytekIME.app
├── iTunesArtwork
└── iTunesMetadata.plist
其中Payload目錄下就是iFlytekIME.app文件夾,爲應用包的主要成分,它的目錄下主要有如下幾類文件:
-
可執行文件: 它是應用的在iOS系統中的執行文件,是定義的MachO格式類型,就像ELF是Linux的可執行文件類型一樣,它最終由dyld進行加載運行。
逆向層面:運用Hopper可用於進行靜態代碼的分析,修改Load Commands段以加載注入的動態庫,運用懶加載符號綁定的特性進行函數的Hook等
-
Info.plist文件: 存儲應用的相關設置、BundleID以及Executable file等。
逆向層面:在重簽名的時候修改BundleID與新證書APPID一致以通過驗證,獲取該應用可執行文件名信息以對其進行操作,修改其他應用配置等
-
Frameworks文件夾: 當前應用使用的第三方Framework。
逆向層面:複製注入動態庫到該文件夾讓系統以@rpath相對路徑的方式進行查找
-
PlugIns&Watch文件夾: 當前應用使用的Extension以及Watch手錶相通的應用。
逆向層面:重簽名時由於簽名驗證的原因需要對這些文件夾的文件都進行重籤,因爲Extension的BundleID需要以主BundleID作爲suffix才能驗證通過
-
資源文件: 其他文件,包括圖片資源、PP配置文件、音視頻資源以及其他本地化相關的文件
三、應用的構建
首先應用的構建我們可以通過Xcode來進行,按“Command+B”快捷鍵編譯項目。接着,我們可以點擊查看Xcode在編譯時到底做了什麼,如下圖所示:
大體我們看到了整個編譯過程:
(1)編譯源文件:使用Clang編譯項目中所有參與編譯的源文件,生成目標文件。
(2)鏈接目標文件:將源文件編譯生成的目標文件鏈接成一個可執行文件。
(3)複製編譯資源文件:複製和編譯項目中使用的資源文件。例如將storyboard文件編譯成storyboardc文件。
(4)複製embedded.mobileprovision:將本地Provisioning\Profiles下的描述文件複製到生成的APP目錄下。
(5)生成Entitlements:生成簽名用的Entitlements文件。
(6)簽名:使用生成的Entitlements文件對生成的APP進行簽名
其實我們可以仿照Xcode通過makefile命令行的方式來自己構建一個App,具體如下:
compile:
#創建xxx.app文件
@rm -r -f xxx.app
@mkdir xxx.app
#Compile Objective-C file
@xcrun -sdk iphoneos clang -arch $(Architecture) -mios-version-min=8.0 -fmodules -fobjc-arc -c $(SRCROOT)/main.m -o xxx.app/main.o
...
link:
#鏈接目標文件
@xcrun -sdk iphoneos clang xxx.app/main.o -arch $(Architecture) -mios-version-min=8.0 -fobjc-arc -fmodules -o xxx.app/xxx
@rm xxx.app/main.o
...
storyboard:
#編譯storyboard文件
@mkdir xxx.app/Base.lproj
@ibtool --compilation-directory xxx.app/Base.lproj xxx.app/Base.lproj/Main.storyboard
...
plist:
#plist寫入信息 : App ID、name、version ...
@defaults write $(pwd)/xxx.app/Info CFBundleExecutable xxx
asset:
#複製圖片資源
@cp -a $(SRCROOT)/images/. xxx.app/
dsym:
#生成dSYM文件
@dsymutil -arch $(Architecture) xxx.app/xxx -o xxx.app.dSYM
codesign:
#簽名
@cp -f embedded.mobileprovision xxx.app
@codesign -fs $(CertificateName) --entitlements entitlements.plist xxx.app
package:
#打包ipa
@mkdir -p Payload @cp -r -f xxx.app Payload
@zip -r -q xxx.ipa Payload
@rm -f -r Payload/ @rm -f -r xxx.app
從makefile文件中可以看到,整個過程分爲compile link storyboard plist asset dsym codesign package
這幾個步驟,最終按順序執行構建;不過這只是簡單的列舉了一下幾個編譯的主要過程,通過Xcode編譯還涉及到其他的編譯參數和步驟。
從上述的構建過程我們可以發現簽名的過程也正在其中,這就給我們進行重簽名和注入包有所啓發;其實就是在Xcode構建的過程中,我們可以在簽名步驟之前對plist文件進行修改以及注入所依賴的framework,這也是MonkeyDev實現的原理。
三、應用簽名及安裝
爲了確保安裝到手機上的應用都是經過認證的合法應用,蘋果制定了一個簽名機制。其中涉及到如下這些文件:CertificateSigningRequest、.cer文件、Entitlements授權文件、PP配置文件。
(1)CertificateSigningRequest
該文件包含申請者信息、申請者公鑰、公鑰加密算法。
(2).cer文件
該文件包括申請者信息、申請者公鑰、通過蘋果私鑰加密的數字簽名,其中數字簽名是通過取出CertificateSigningRequest的公鑰,添加賬號信息,再通過hash算法生成一個信息摘要,使用蘋果的CA私鑰進行加密得到的。
在對應用進行簽名時,先使用證書所對應的私鑰對代碼和資源文件等進行簽名,蘋果系統會通過公鑰對應用的簽名合法性進行驗證。
(3)Entitlements授權文件
授權文件是一個沙盒的配置列表,其中列出了哪些行爲會被允許、哪些行爲會被拒絕。例如,在重籤應用時常常需要調試器自動髮夾,就會將文件裏面的get-task-allow改爲true。在簽名時Xcode會將這個文件作爲–entitlements參數的內容傳給codesign。
(4)配置文件(Provisioning Profiles)
前面提到的證書包含在該文件裏,配置文件在打包時會被複制到.app目錄下,其包含App ID,授權文件,證書以及可安裝的設備列表。
可以使用security cms -D -i embedded.mobileprovision
命令來查看。
當一個應用安裝啓動時,蘋果系統會對其進行驗證,其實主要就是檢查配置文件和當前運行App的信息是否匹配,檢查項大概如下所示:
BundleID(APP)–App ID、entitlements(APP)–entitlements、certificate(APP)–certificate、deviceID(系統)–device ID
在逆向開發中重簽名的過程也就是讓整個過程在驗證的時候能夠通過,在修改掉原來應用的代碼或資源時,重新用自己的證書對該應用進行簽名就可以了,唯一要做的就是需要將entitlements、BundleID這些檢驗項換成匹配新配置文件的內容就可以了。
四、總結
在重新梳理過這些基礎的知識之後,我們也就對整個蘋果安裝包從始至終的形態有了一定的瞭解,這同時也對逆向的開發提供了堅實的基礎。