破解的iphone上, 如何編寫具有root許可權的程式
正常途徑下, 我們編寫的程式發布在App store上, 使用官方規定的SDK. 但有些時候, 正常途徑實現不了的功能, 可以在破解的iphone上面實現. 以cydia上檔案管理軟體iFile為例, iFile可以修改系統的任何檔案, 這需要iFile具有root許可權, 在iphone沒有破解的情況之下, 是無論如何都實現不了的.
對於iphone系統, 有兩個目錄會安裝應用程式
1. /Application
2. /var/mobile/Applications
/var/mobile/Applications下的應用程式會有很多限制, 似乎系統會認為此目錄下的程式一定會運行在沙箱中, 不管怎麼設定許可權也無用. /Application目錄下的程式限制會小一些, 要取得root許可權, 第一步就是要將程式安裝在/Application目錄下.
幸好有cydia. 系統破解之後, 絕大多數都會安裝上cydia. 自己搭建cydia源, 第三方軟體也可以通過cydia來發布. 搭建cydia源中有一步是將編譯出的程式打包成deb. 打包的時候, 可以指定最終安裝後的目錄結構. 至於如何搭建cydia源, google一下會有詳細的教程, 這裡不多說, 下面已假設可以將程式安裝在/Application目錄下.
先簡單複習一下unix的許可權管理, iOS系統其實是個小的unix.
unix下面每個檔案都有自己所屬, 和存取權限.
比如使用者complex_ok是組mobile的成員, 他登入的時候建立了一個檔案A, 預設下, A就屬於使用者complex_ok, 組為mobile.
另外檔案A還可以指定自己的存取權限, 分成使用者, 組, 其它人三個層級, 三個層級都可以指定自身的 是否可讀, 是否可寫, 是否可執行.
比如 檔案A屬於使用者complex_ok, 組為mobile
它的存取權限指定為 使用者可讀可寫可執行, 組可讀可寫, 其他人為唯讀.
這個時候使用者complex_ok登入的時候, 可以執行檔案A, 如果使用者HelloKitty, 也屬於組mobile, HelloKitty對檔案A可以進行讀寫, 但不可以執行, 而其它非同組的人, 就唯讀.
當我們使用iphone的時候, 我們實際上是以使用者mobile, 組mobile的身份登入的. 當某檔案屬於root使用者, 許可權設為組和其它人都唯讀, 正常時候就不能修改這檔案.
幸好unix還可以為檔案的存取權限指定setuid位, 這個位很重要
比如可執行程式A, 程式也是檔案, 程式A是屬於root使用者的. 假設使用者mobile運行程式A, 如果沒有為程式A設定setuid位, 程式A是以使用者mobile的許可權運行. 如果指定了setuid位, 就算使用者是mobile, 並非root, 但因為程式A是屬於root使用者的, 程式A也可以以root的許可權運行.
明白setuid位的作用, 似乎取得運行root許可權的程式就很簡單了. 比如我們也想編寫自己的檔案管理程式aFile, 使aFile也運行在root許可權, 我們就將aFile程式的修改成屬於root使用者, 再將許可權位設定成可執行, 並有setuid位. 使用cydia將程式安裝到/Application, 使用者點擊iFile的表徵圖, 這樣iFile就以root許可權運行了.
想法是好的, 但是這樣還不行. 當使用者點擊程式的表徵圖時, 是通過iphone系統調用程式的, iphone系統會有一個安全檢查, 它會檢查到程式將以root許可權運行應用程式, 就不會執行, 你會看到程式閃一下, 就被結束了.
所以我們還需要一個間接層, 編寫一個引導程式A, 再通過A調用B.
首先將A的使用權限設定為其它人可讀可執行, B的所屬設定為root, 使用權限設定為其它人可讀可執行, 並有setuid為.
當使用者點擊表徵圖, iphone系統調用程式A, 它判斷出程式A並沒有root許可權, 正常執行, 程式A這時候去調用B, 因為B是A調用的, 程式A是我們自己寫的, 並不做安全檢查, 這樣B有setuid位之後, 所屬為root, 就可以以root執行了.
那如何使iphone系統調用引導程式A而不是調用正常程式B呢? 很簡單, 改改名字就可以了.
比如你建立的工程為aFile, 正常編譯出一個aFile.app檔案, 右鍵, 顯示包內容, 將裡面的可執行檔aFile, 修改名字為aFile_, 再將你的引導程式改成aFile, 這樣安裝之後, 點擊表徵圖系統就會自動調用你的引導程式. 引導程式的編寫很簡單, 大體為
int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString* string = [[NSBundle mainBundle] pathForResource:@"aFile_" ofType:nil];
argv[0] = (char*)[string UTF8String];
execve([string UTF8String], argv, NULL);
[pool release];
return 0;
}
取得root許可權後, 就可以做很多事情了, 你的程式編寫時候也要小心一點.
在打包成deb時候, 可以用指令碼自動修改檔案許可權和所屬.
許可權修改的命令為chmod, 所屬修改的命令為chown. 用法自己查一下.