Mobile Substrate和Theos
Mobile Substrate是Cydia的作者Jay Freeman (@saurik)的另外一個牛X的作品,也叫Cydia Substrate,它的主要功能是hook某個App,修改代碼比如替換其中方法的實現,Cydia上的tweak都是基於Mobile Substrate實現的。目前支持iOS和Android平臺。
根據github上的介紹,theos是一個跨平臺iPhone Makefile系統。它的主要功能是生成iPhone 越獄App、tweak等程序的框架結構,並提供makefile來編譯、打包和安裝。
需要的準備工作:
####Mac * 安裝Theos,從Theos的GitHub上clone下來一份,放到某個目錄下,這裏我放到了/opt/下。 * 安裝Xcode Command Line Tools,可以在命令行下執行xcode-select --install來安裝或者參考SO來安裝,安裝完之後再進行下一步。 * 安裝dpkg ,首先安裝MacPorts,可以通過它的官網,根據自己的系統版本來選擇。安裝好之後,重啓Terminal,執行port version,顯示出版本號說明安裝成功。如果提示command not found,嘗試在/etc/paths文件中加入下面兩個路徑:/opt/local/bin/opt/local/sbin,需要使用root權限來編輯,比如用Vim的話:sudo vi /etc/paths. 重啓Terminal,再次輸入port version就應該會顯示版本號了,然後執行sudo port selfupdate來更新一下,之後執行sudo port install dpkg來安裝dpkg. 安裝dpkg的目的是把我們寫的tweak打成deb包。
JailBreaked iPhone iOS 5/6
- 安裝OpenSSH,打開Cydia的主界面就能看到OpenSSH Access How-To 以及Root Password How-To的選項,可以按照它的提示一步一步安裝,這裏不贅述了,需要提醒的是一定要改掉root的密碼,防止別人通過SSH連接到你的手機。這一步是爲了後面我們通過SSH連接到手機,把deb包安裝到手機上準備的。
- iOS7上的Mobile Substrate還有bug,32位的系統下每次重啓後需要重新安裝Mobile Substrate才能正常使用, 64位今天貌似才能用。推薦暫時在iOS5/6的機器上測試[2014-01-01]。
- apt. 在cydia中搜索Apt檢查是否已經安裝,沒有安裝就安裝一下。
- ldid. 全名是Link Identify Editor,也直接可以在Cydia中搜索全名安裝。
創建Tweak並安裝到手機上
首先我在桌面上創建一mytweaks的文件夾,保存我們要創建的tweak程序。
➜ ~ cd ~/Desktop
➜ Desktop mkdir mytweaks
➜ Desktop cd mytweaks
然後執行我們剛纔的獲得的theos來生成一個tweak的模板:
➜ mytweaks /opt/theos/bin/nic.pl
NIC 2.0 - New Instance Creator
------------------------------
[1.] iphone/application
[2.] iphone/library
[3.] iphone/preference_bundle
[4.] iphone/tool
[5.] iphone/tweak
Choose a Template (required): 5
Project Name (required): FirstTweak
Package Name [com.yourcompany.firsttweak]: com.joeyio.firsttweak
Author/Maintainer Name [Joey]:
[iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]:
[iphone/tweak] List of applications to terminate upon installation (space-separated,'-' for none) [SpringBoard]:
Instantiating iphone/tweak in firsttweak/...
Done.
在創建模板的時候,我們選擇5,創建一個iPhone的tweak.其他4個選項可以自己去搜索下。名字輸入FirstTweak,包名我輸入com.joeyio.firsttweak,下面的三個選項都直接回車使用缺省值。
MobileSubstrate Bundle filter這一項表示要hook的程序,默認是com.apple.springboard,就是hook Spring Board,如果你想hook別的App,這裏改成那個App的BundleID.
OK,那麼我們的第一個tweak就創建好了,好像一點也不難啊。進入到firsttweak目錄下,使用make編譯一下,可能結果是這樣的:
➜ firsttweak make
/Users/qiaoxueshi/Desktop/mytweaks/firsttweak/theos/makefiles/targets/Darwin/iphone.mk:41: Deploying to iOS 3.0 while building for 6.0 will generate armv7-only binaries.
Making all for tweak FirstTweak...
Preprocessing Tweak.xm...
Name "Data::Dumper::Purity" used only once: possible typo at /Users/qiaoxueshi/Desktop/mytweaks/firsttweak/theos/bin/logos.pl line 615.
Compiling Tweak.xm...
Linking tweak FirstTweak...
Stripping FirstTweak...
Signing FirstTweak...
/bin/sh: ldid: command not found
我們看到裏面有2個警告,第一個我沒有搜索到什麼結果,第二個是隻要手機上安裝ldid就行了,這裏不用管它。我自己試了一下,是可以安裝到手機上的,可以暫時忽略,如果哪位小夥伴知道什麼原因,歡迎告知。
在部署到手機之前確認手機和電腦在一個wifi環境下,並且可以通過SSH連接到手機,方法是在Terminal下,通過SSH連接到手機,之後會提示你輸入root密碼(上面安裝SSH步驟中有提到),確保連接成功再往下進行。手機的IP地址可以在wifi設置中看到。
ssh root@手機IP地址
然後把手機IP地址放在THEOS_DEVICE_IP環境變量中,這樣theos才知道安裝到哪裏,如下:
export THEOS_DEVICE_IP=手機IP地址
然後執行make package install打包並安裝到手機上 (如果Cydia在前臺,把它退到後臺,否則安裝會失敗):
➜ firsttweak make package install
/Users/qiaoxueshi/Desktop/mytweaks/firsttweak/theos/makefiles/targets/Darwin/iphone.mk:41: Deploying to iOS 3.0 while building for 6.0 will generate armv7-only binaries.
Making all for tweak FirstTweak...
make[2]: Nothing to be done for `internal-library-compile'.
Making stage for tweak FirstTweak...
dpkg-deb:正在新建軟件包“com.joeyio.firsttweak”,包文件爲“./com.joeyio.firsttweak_0.0.1-2_iphoneos-arm.deb”。
install.exec "cat > /tmp/_theos_install.deb; dpkg -i /tmp/_theos_install.deb && rm /tmp/_theos_install.deb" < "./com.joeyio.firsttweak_0.0.1-2_iphoneos-arm.deb"
[email protected]'s password:
Selecting previously deselected package com.joeyio.firsttweak.
(Reading database ... 6250 files and directories currently installed.)
Unpacking com.joeyio.firsttweak (from /tmp/_theos_install.deb) ...
Setting up com.joeyio.firsttweak (0.0.1-2) ...
install.exec "killall -9 SpringBoard"
[email protected]'s password:
安裝過程中需要輸入兩次手機Root密碼,一次是爲了把打包後的deb程序文件傳到手機上,另外一次是kill掉SpringBoard,使SpringBoard重啓。
完成後在Cydia裏的“變更”裏,往下翻一翻,就能看到一個名字爲“FirstTweak”的插件了了,想想接下來出任CEO,迎娶白富美,走向人生巔峯,有木有一點小激動?
完成一個小功能
到目前爲止,我們還沒寫過一行代碼呢。下面我們要完成一個小功能:在鎖屏界面增加一個UILabel顯示一行文字,可以是你的座右銘或者其他的,這裏我們顯示Hello, MobileSubstate!!。
打開我們剛纔創建的firsttweak目錄下的Makefile文件,在FirstTweak_FILES = Tweak.xm下面增加一行FirstTweak_FRAMEWORKS = UIKit並保存文件,前綴都是TWEAK_NAME的值,也就是FirstTweak,注意根據你自己的情況來修改。增加這行的原因很明顯,增加UILabel需要用到UIKit Framework。整個文件看起來像這樣:
include theos/makefiles/common.mk
TWEAK_NAME = FirstTweak
FirstTweak_FILES = Tweak.xm
FirstTweak_FRAMEWORKS = UIKit
include $(THEOS_MAKE_PATH)/tweak.mk
after-install::
install.exec "killall -9 SpringBoard"
這個步驟完成之後,我們就要找到鎖屏界面對應的ViewController,然後替換它的某個方法,把UILabel添加到它的view上。這個ViewController的名字叫SBAwayController, SB是SpringBoard的縮寫,不要想偏了 :).我們要替換它的- (void)activate方法。SBAwayController類的頭文件可以在iOS6的私有類的頭文件中找到。在SBAwayController裏有個叫_awayView的ivar,獲得這個ivar需要一個theos中不存在的方法,好吧,它叫MSHookIvar,這個方法在默認的theos的substrate.h頭文件裏沒有,可以在GitHub得到包含這個方法的頭文件。下載到本地,覆蓋theos/include下的同名文件(推薦將原有的substrate.h頭文件重命名)。
OK,到這裏萬事具備,只欠Coding了。
打開firsttweak目錄下的Tweak.xm文件並清空,添加下面這段代碼:
%hook SBAwayController
- (void)activate {
%orig(); //invoke the orignal method to do what should to do.
NSLog(@"=========================================================");
NSLog(@"Hello MobileSubstrate!!");
NSLog(@"=========================================================");
//get _awayView via MSHookIvar method
UIView *_awayView = MSHookIvar<*>(self,"_awayView");
//create a lable whose width = 200 and height = 100 and add to _awayView
float w =200;
float h =100;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake((_awayView.frame.size.width - w)/2,100,w,h)];
label.text = @"Hello, MobileSubstate!!";
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
[_awayView addSubview:label];
}
%end
大概解釋一下,%hook SBAwayController以及裏面的- (void)activate方法,其實就類似swizzling了SBAwayController的activate方法。當系統執行SBAwayController的activate方法的時候會執行tweak裏的activate的方法。 在這裏方法裏我們先執行了%orig(),就是執行原來的activate方法,保證原有的方法先執行,再執行我們自己的代碼。
這個activate方法在第一次進入鎖屏界面的時候會執行,在以後每次非鎖屏狀態下,按關機鍵也會執行。
接下來就是通過MSHookIvar獲得_awayView。然後就是我們非常熟悉的了,創建一個UILabel,添加到_awayView裏。到這裏就結束了。make package install一下(還需要先執行一下export THEOS_DEVICE_IP=手機IP地址),安裝到手機上,等SpringBoard重啓完,你會看到類似下圖的界面:
把手機連接到電腦上,打開Xcode,在Organizer裏的Console裏能看到程序中使用NSLog打印的信息,用來調試很方便呢。
總結
本文主要是講Mobile Substrate的作用以及如何使用Theos開發一個簡單的tweak。有了這些入門的基礎之後,你就可以根據自己的想法來寫自己喜歡的tweak。如果你是在iOS7下越獄的話,可以嘗試一下把控制中心的AirDrop和音樂播放器給隱藏掉,讓控制中心看起來更簡潔。接着可以再進行改進,比如在藍牙關閉的時候不顯示AirDrop,開啓的時候依然顯示,音樂正在播放的時候顯示音樂播放器,否則不顯示。
這個小Demo是前兩週寫的,一直沒有時間整理出來,今天抽時間整理了一下文字發了出來,算是送給自己新年的一件禮物吧!
Thanks,Have Fun!
More About Substrate And Theos
- iphonedevwiki
- Theos/Getting Started
- Cydia Substrate(Mobile Substrate也叫做Cydia Substrate)