iOS逆向 ipa包重簽名

[TOC]

先來學習下三個重要概念:
public/private keys, entitlements, and provisioning pro?les.

entitlements是嵌入在App里的XML字符串,表示App可以做什么不可以做什么

App里的provisioning pro?le文件包含entitlements、可以安裝到的真機列表、用來驗證簽名的public key

Public/private keys

Requesting a Certi?cate From A Certi?cate Authority
You created a public/private key, sent up the public key to Apple servers (by the .csr ?le).

You can view the names, or identities, of your public/private key pairs used for signing your applications with the following Terminal command:

security find-identity -p codesigning -v

This command queries the macOS system keychain, looking for valid identities that contain a private key (-v) and whose type can codesign (-p codesigning).

This ouput will display identities that are valid, which can produce a code signed application. If you look for identities that contain the phrase “iPhone Developer], it’s likely that this identity can be used to sign an iOS application on your device.

?  bin security find-identity -p codesigning -v
  1) D1F90756076CA6CD2495ED5798E146E2426300C0 "iPhone Distribution: Kun Li (2QNTW3GT23)"
  2) 6B9065E80E180DD48807C09F92E4D505812E029C "iPhone Developer: zhoujie_903@163.com (TCDLVFEQHJ)"
     2 valid identities found

Never, ever, delete a private key!

you can export the public certi?cates using the following command:

security find-certificate -c "iPhone Developer: Derek Selander (8AW8QLCX5U)" -p

This will output the public, x509 certi?cate of iPhone Developer: Derek Selander (8AW8QLCX5U) to stdout and format it in PEM format.

Use the Terminal command to cat this newly created ?le:

cat /tmp/public_cert.cer
-----BEGIN CERTIFICATE----MIIFnDCCBISgAwIBAgIIFMKm2AG4HekwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNV BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3 
...

This is how you can tell this certi?cate is in PEM.

From here, you can use the openssl Terminal command to query the public, x509 certi?cate:

openssl x509 -in /tmp/public_cert.cer -inform PEM -text -noout
  • The x509 option says that the openssl command should be able to work with a x509 certi?cate.
  • You provide the -in to the path of public_cert.cer with the decoding format of PEM (-inform PEM).
  • You specify you don’t want to output a certi?cate with the -noout param.
  • But instead, you do want the certi?cate in a (somewhat) readable “text” format with the -text option.

There’s two ways to display a certi?cate: DER and PEM.
PEM can be read by the Terminal (since it’s in base64 encoding)
while DER, in highly professional coding terms, will produce gobbledygook and make the Terminal beep a lot.

Entitlements

Embedded in (almost) every compiled application is a set of entitlements: again, this is an XML string embedded in the application saying what an app can and can’t do.

For example, App Groups, iCloud Services, Push Noti?cations, Associated Domains all will modify the entitlments to your app. These capabilities shown in Xcode are but a small piece of the entitlements on Apple platforms as the majority of them are private to Apple and enforced through code signing.

重點:
Probably the most important entitlement, at least in this book, is the get-task-allow entitlement, found on all your software compiled with a developer certi?cate. This allows the program in question to be attached to a debugger.

You can view the entitlements of an application through the codesign Terminal command.
Find the entitlements of the macOS Finder application:

codesign -d --entitlements :- /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
  • The -d option says to display the option immediately following in the command, which is the --entitlements.
  • The - says to print to stdout
  • The : says to omit the blob header and length.

Provisioning pro?les

A provisioning pro?le includes the public x509 certi?cate, the list of approved devices, as well as the entitlements all embedded into one ?le.

provisioning pro?les默認位置:

~/Library/MobileDevice/Provisioning Profiles/

你和Xcode創建的provisioning pro?les以UUID作為文件名,比如fe0c62fd-0f18-4974-821b-84b3337b0c12.mobileprovision

你可以通過security命令查看.mobileprovision文件的內容:

PP_FILE=$(ls ~/Library/MobileDevice/Provisioning\ Profiles/ *mobileprovision | head -1) 
security cms -D -i "$PP_FILE"

the security command which decodes (-D) the cryptographic message syntax (cms) format of the provisioning pro?le, specifying the input path via the -i option.

  • AppIDName This is the name of the Application ID that is tied to this provisioning pro?le
  • TeamIdenti?er the unique team ID Apple has given me for my team identity
  • Entitlements contains the Entitlements of what the app can and can’t do with this signature.
  • ProvisionedDevices contains an array of approved devices this provisioning pro?le can install on, given by a device’s UDID.
  • DeveloperCerti?cates is an array that contains base64-encoded x509 certi?cates.
  • IsXcodeManaged is a Boolean value that indicates if Xcode manages this provisioning pro?le.
  • Name which is the name of the provisioning pro?le that Apple displays to identify the provisioning pro?les on https:// developer.apple.com/account/ios/pro?le/limited.

探索WordPress app

apple商店上下載的ipa是經過加殼的,不能用于重簽名。
這里以開源App:Wordpress v10.9 來重簽名:
下載地址:https://github.com/wordpress-mobile/WordPress-iOS/releases/tag/10.9

也可以從像PP助手上下載越獄過的App來重簽名

The provisioning pro?le

APP_FILE="/full/path/to/WordPress.app"
security cms -D -i "$APP_FILE/embedded.mobileprovision"

在這個provisioning pro?le,包含了如下信息:

  • Apple給Automattic, Inc.公司的team identi?er為 3TMU3BH3NK.
  • Wordpress app使用了iCloud服務, 因為在entitlements dictionary可以看到com.apple.developer.icloud*等keys. It also looks to make use of certain extension like "App Groups".
  • get-task-allow 是 false, 調試器不能attach, 不能調試

DeveloperCerti?cates鍵的值為x509 證書base64編碼后的值

CERT_DATA=MIIFozCCBIu...

解碼后保存到/tmp/wordpress_cert.cer:

echo "$CERT_DATA" | base64 -D > /tmp/wordpress_cert.cer

通過openssl命令查看證書內容:

openssl x509 -in /tmp/wordpress_cert.cer -inform DER -text -noout

輸出如下:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 786948871528664923 (0xaebcdd447dc4f5b)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Apple Inc., OU=Apple Worldwide Developer Relations, CN=Apple Worldwide Developer Relations Certification Authority
        Validity
            Not Before: Jan 17 13:26:41 2018 GMT
            Not After : Jan 17 13:26:41 2019 GMT
        Subject: UID=PZYM8XX95Q, CN=iPhone Distribution: Automattic, Inc. (PZYM8XX95Q), OU=PZYM8XX95Q, O=Automattic, Inc., C=US

可以看出在“Automattic, Inc”工作的某人用“iPhone Distribution: Automattic, Inc. (PZYM8XX95Q)”簽名了這個App

Embedded executables

除主應用外,還包含extensions(share extension, today widgets, 和其它等),./Plugins文件夾里的每個extension都有自己的application identi?er和embedded.mobileprovision、簽名

_CodeSignature文件夾

在真機的app中有一個_CodeSignature文件夾,里面只包含一個叫CodeResources文件。
它是一個XML plist文件,內容為***.app內的每個非可執行文件的checksum值

可以通過openssl命令自己來計算文件的checksum值:

openssl sha1 -binary "$APP_FILE/AboutViewController.nib" | base64

Apple已開始為Xcode 10創建的ios app從SHA-1 checksums過渡到SHA-256 checksums

重點:
CodeResources文件自身的checksum被嵌入到可執行文件中。這意味著在xxx.app中修改任一文件,甚至增加一個文件夾,不重新簽名的話,app都會安裝失敗。

重簽名app

需要做如下的步驟:

  1. 復制有效的provisioning pro?le文件到xxx.app為embedded.mobileprovision文件
  2. 修改Info.plist的CFBundleIdenti?er鍵的值為provisioning pro?le文件中包含的application identi?er的值.
  3. 以合適的entitlements和provisioning pro?le中包含的開發者身份來重簽名App(合適的entitlements從provisioning pro?le文件里提取)

你能從
~/Library/MobileDevice/Provisioning Profiles/

https://developer.apple.com/
上得到provisioning pro?le文件

(Optional)生成有效的provisioning profile文件

替換provisioning pro?le文件

復制mobileprovision文件為app內的embedded.mobileprovision

PP_PATH=~/Downloads/ProvisProfile_92618.mobileprovision
cp "$PP_PATH" "$APP_FILE/embedded.mobileprovision"

刪除Plugins、Watch等文件夾

app里如果有Plugins文件夾時,里面的每個擴展都有自己唯一的application identi?er、唯一的provisioning pro?le。你能用其他唯一的provisioning pro?le重簽名每個擴展,但作為demo,這樣做太復雜了,我們選擇刪除整個Plugins文件夾。

刪除這些文件夾后,重簽名后的app就沒有相應的功能了,但作為演示可以接受。

修改Info.plist文件

可以從provisioning pro?le提取到application identi?er:

security cms -D -i "$PP_PATH" | grep application-identifier -A1

上面的命令得到如下輸出:

<key>application-identifier</key> 
<string>H4U46V6494.com.selander.code-signing</string>

通過替換Info.plist中CFBundleIdenti?er鍵的值來修改app的application identi?er:

plutil -replace CFBundleIdentifier -string H4U46V6494.com.selander.codesigning "$APP_FILE/Info.plist"

修改WordPress app顯示的名字:

plutil -replace CFBundleDisplayName -string "Woot" "$APP_FILE/Info.plist"

提取entitlements

因為entitlements在provisioning pro?le不是XML,而是字典,為了簡單起見:從可執行文件中提取原來entitlements并保存到entitlements.xml文件,再從provisioning pro?le中提取新的entitlements并替換掉entitlements.xml文件中原來的entitlements

  1. 從可執行文件中提取entitlements并保存到文件:
codesign -d --entitlements :/tmp/entitlements.xml "$APP_FILE/WordPress"
cat /tmp/entitlements.xml
  1. 從provisioning pro?le生成新的entitlements.xml的模板:
security cms -D -i "$PP_PATH" > /tmp/scratch

使用xpath命令只提取entitlement信息到剪切板:

xpath /tmp/scratch '//*[text() = "Entitlements"]/following-sibling::dict' | pbcopy

現在剪切板包含了有效的entitlements,打開/tmp/entitlements.xml文件,刪除<dict>包含的內容,粘帖剪切板的內容

最終的/tmp/entitlements.xml文件內容包含像如下的entitlements信息:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>keychain-access-groups</key>
    <array>
        <string>P9DNHPPVMB.*</string>   
    </array>
    <key>get-task-allow</key>
    <true/>
    <key>application-identifier</key>
    <string>P9DNHPPVMB.com.jason.DeleteMe</string>
    <key>com.apple.developer.team-identifier</key>
    <string>P9DNHPPVMB</string>
</dict>
</plist>

重點:/tmp/entitlements.xml這個文件的格式一定要正確,我在實踐時因為xpath .... | pbcopy命令生成了錯誤的<true />多了一個空格,而生成了不正確的entitlements.xml文件,導致安裝成功后但啟動app就崩潰

最后簽名WordPress app

You now have performed all the setup.
You have a valid signing identity;
you have a valid provisioning pro?le embedded in the WordPress application at embedded.mobileprovision;
you have removed the Plugins directory;
and you have the entitlements of the new provisioning pro?le found at /tmp/entitlements.xml.

使用codesign命令用你的身份來重簽名App:

codesign -f -s "iPhone Developer: Derek Selander (8AW8QLCX5U)" "$APP_FILE"/Frameworks/*
codesign --entitlements /tmp/entitlements.xml -f -s "iPhone Developer: Derek Selander (8AW8QLCX5U)" "$APP_FILE"

主要腳本代碼

命令 文件 功能 命令行
plutil Info.plist 替換CFBundleIdentifier plutil -replace CFBundleIdentifier -string "xxx" Info.plist
security embedded.mobileprovision 二進制解碼為文本格式 security cms -D -i xxx.mobileprovision
codesign 可執行文件 提取entitlements codesign -d --entitlements :xxx.xml WeChat
codesign xxx.app 重簽名 codesign --deep -f -s "iPhone Developer: xxx@yyy.com (TCDLVFEQHJ)" --entitlements zzz.xml xxx.app
# 定義要重簽名的app文件路徑、和有效的mobileprovision文件路徑
APP_FILE=~/Desktop/WeChat/Payload/WeChat.app
PP_PATH=~/Desktop/ProvisProfile_92618.mobileprovision

# 從mobileprovision文件中提取得到application-identifier(app id或CFBundleIdentifier)
EXTRACTED_ENT="/tmp/extracted_ent"
security cms -D -i "$PP_PATH" > "$EXTRACTED_ENT"
APP_IDENTIFIER=$(/usr/bin/xpath "$EXTRACTED_ENT" '//*[text() = "application-identifier"]/following-sibling::string[1]/text()' 2>/dev/null |  cut -d. -f 2-80 ) 
echo "app id is : $APP_IDENTIFIER"

# 復制mobileprovision文件為app內的embedded.mobileprovision
cp "$PP_PATH" "$APP_FILE/embedded.mobileprovision"

# 刪除PlugIns、Watch等文件夾
rm -rf "$APP_FILE/PlugIns"
rm -rf "$APP_FILE/Watch"

# 替換Info.plist內的CFBundleIdentifier、CFBundleDisplayName
plutil -replace CFBundleDisplayName -string "Woot" "$APP_FILE/Info.plist"
plutil -replace CFBundleIdentifier -string ${APP_IDENTIFIER} "$APP_FILE/Info.plist"

# 生成簽名app用的entitlements.xml
codesign -d --entitlements :/tmp/entitlements.xml "$APP_FILE/WeChat"
security cms -D -i "$PP_PATH" > /tmp/scratch

# 這名命令有點缺陷:生成的<true />多了一個空格,正確的是<true/>
xpath /tmp/scratch '//*[text() = "Entitlements"]/following-sibling::dict' | pbcopy 
# [不要用剪切板,否則會把上面命令得到剪切板中的內容給覆蓋了。把剪切板上的內容粘貼到/tmp/entitlements.xml中]
open /tmp/entitlements.xml  

# 重簽名Frameworks、 和app
codesign --deep -f -s "iPhone Developer: zhoujie_903@163.com (TCDLVFEQHJ)" "$APP_FILE/Frameworks/"*
codesign --deep -f -s "iPhone Developer: zhoujie_903@163.com (TCDLVFEQHJ)" --entitlements /tmp/entitlements.xml "$APP_FILE"

# 安裝到真機
mobdevim -i "$APP_FILE"

完整詳細代碼可以參考dsresign

參考

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容