1,代碼簽名
驗(yàn)證代碼的“正確性”是計(jì)算機(jī)科學(xué)中最難的問題之一,目前沒有“完美”辦法能夠分析任意一段代碼,確定它是否是惡意的,而目前通常對(duì)代碼驗(yàn)證的方法是數(shù)字簽名。
目前數(shù)字簽名用于驗(yàn)證
驗(yàn)證代碼來源:由簽名者的私鑰進(jìn)行簽名,其他使用者可以用公鑰進(jìn)行驗(yàn)證。
驗(yàn)證代碼的真實(shí)性:對(duì)代碼的任何修改都有可能破壞數(shù)字簽名。
代碼簽名不是蘋果獨(dú)創(chuàng)的,其他開發(fā)語言都在使用它,比如java。但是蘋果對(duì)于整個(gè)代碼簽名的解決方案在許多方面是相當(dāng)具有創(chuàng)新性的,其中最重要的是與授權(quán)的整合、對(duì)額外的資源的簽名和確保在整個(gè)應(yīng)用的生命周期中保持代碼的完整性。
2,代碼塊中簽名
蘋果公司代碼塊格式是Mach-O,首先說明的是目前做數(shù)字簽名的算法是我們熟知的算法,主要是sha1,sha256等摘要算法。這些算法做摘要運(yùn)算,算出散列值。
如果是要計(jì)算的代碼塊比較小,則會(huì)很快計(jì)算出簽名值。但是如果代碼塊超級(jí)大,這時(shí)候?qū)φ麄€(gè)二進(jìn)制文件計(jì)算散列值來驗(yàn)證代碼簽名,可能很耗費(fèi)性能的操作。而且實(shí)際上整個(gè)代碼塊在運(yùn)行時(shí),并不是一起映射到內(nèi)存中的,而可能是只映射一部分。蘋果在代碼塊目前采取分頁處理(因?yàn)榉猪摚砸簿陀兄芾磉@些分頁的代碼目錄),所以此時(shí)計(jì)算散列值是以每一個(gè)二進(jìn)制頁來計(jì)算的。
如何計(jì)算--->使用sha1等摘要算法計(jì)算出散列值,然后再對(duì)散列值求散列值
如何存儲(chǔ)--->計(jì)算出的散列值一般位于文件的末尾,更進(jìn)一步散列值由代碼目錄pagesize字段指定,并放置在代碼插槽中
如何驗(yàn)證--->蘋果定義LC_CODE_SIGNATURE的加載命令,該加載命令遵循_LINKEDIT加載命令架構(gòu)體,該結(jié)構(gòu)體僅僅指向代碼簽名的位置和大小
codesign -d -vvvvv /xxx
可以用這個(gè)命令來查看代碼簽名,/xxx表示你要查看的代碼塊Mach-O文件
從macOS10.12/iOS11開始,蘋果是用sha256算法,取代了之前的sha1
3,其他資源的簽名
蘋果除了保護(hù)代碼塊外,其他plist、nib等資源也做了保護(hù)。
首先可以思考總結(jié)的是,姑且不管每個(gè)代碼頁計(jì)算出的散列值具體怎樣存儲(chǔ)在一個(gè)代碼插槽中的,但是基礎(chǔ)的原理咱們可以明曉。這個(gè)散列值大小加位置的結(jié)構(gòu)體,肯定存放在代碼頁中的,按照蘋果4096的代碼分頁最起碼插槽是存在這4096個(gè)字節(jié)中的。
但是其他資源不同于代碼塊,比如一個(gè)nib資源,它本質(zhì)不是代碼資源,也就是說上面那一套代碼插槽存儲(chǔ)散列值是不行的。是以蘋果為了做這些資源文件的保護(hù),設(shè)計(jì)出了特殊插槽。
特殊插槽:資源文件用了本身不具有的代碼插槽。
特殊插槽具體的特殊性:
1,特殊插槽的索引都是負(fù)數(shù)的,正常的代碼插槽索引都是正數(shù)的。這是蘋果為了資源文件設(shè)計(jì)一種主動(dòng)“溢出”的特殊索引,解決非代碼插槽的問題。
2,特殊插槽的數(shù)量是限定的,5個(gè)。正常的代碼插槽數(shù)量不固定,理論上沒有上限。但是特殊插槽不是,數(shù)量只有5個(gè)。而且這5個(gè)索引,每一個(gè)都有固定意義,比如-1索引綁定的是資源文件信息plist,-3是資源文件的散列值,-5嵌入在代碼簽名中的授權(quán)。
在特殊插槽中任何未使用的索引,都會(huì)用NULL進(jìn)行填充
4,偽簽名ad-hot
如上面所說,蘋果可以完全控制iOS中每一個(gè)二進(jìn)制文件,因此完全可以編譯一個(gè)封閉的各個(gè)二進(jìn)制文件的散列值列表,并將其硬編碼到內(nèi)核中,特別是AppleMobileFileIntegrity.kext的“信任緩存”中。而這種簽名被稱為“ad-hot”簽名.
ad-hot簽名對(duì)持有證書的CMS二進(jìn)制塊做了留空,通俗地說就是沒有證書了。因?yàn)樯鲜龅拇a簽名的散列值存儲(chǔ)在緩存的內(nèi)核擴(kuò)展中,消除了對(duì)證書的需求,因此這些二進(jìn)制驗(yàn)證只需要找散列值就行。
ldid工具在tweak開發(fā)中通過用戶偽簽名。