iOS SpringBoard tweak插件,雙擊圖標快速啓動debugserver

debugserver+lldb很好用,但啓動起來太麻煩?咱們開發了一款iOS SpringBoard tweak小插件,簡化debugserver啓動過程。老鐵,請雙擊!ios

0x00 懶是第一輩子產力

咱們常常要經過debugserver對App進行調試,有書籍論壇對相關的技術和實踐進行了說明,但實際應用起來仍是有些麻煩。先要重籤拷貝,再要啓動終端ssh到iPhone啓動debugserver,各類ls加grep找到想調試的應用,敲命令啓動debugserver,而後Mac本地終端啓動lldb。這樣折騰下來,至少要開兩個終端,有的時候甚至更多。GitHub上有個issh工具對上述操做有封裝和優化,可是仍是須要敲命令找App,再運行debugserver。git

因此作個tweak提高一下生產力。只需雙擊應用圖標,便可一鍵啓動debugservergithub

代碼見:Githubapp

https://github.com/TalkingDat...ssh

運行界面異步

咱們所用的開發環境是iOS 13.3,可是並無用到特殊版本的API,低版本手機應該也OK。函數

下面簡單分享開發過程:工具

0x01 經過圖標找到應用執行路徑

從界面找邏輯,逆向發現SpringBoard的圖標是SBIconView。而且有一個叫屬性 applicationBundleIdentifierForShortcuts 返回的是圖標對應的App的Bundle ID。經過Bundle ID構造LSApplicationProxy對象,而且得到canonicalExecutablePath屬性,也就是應用的可執行文件路徑。學習

Class LSApplicationProxy_class = objc_getClass("LSApplicationProxy");NSObject* proxyObj = [LSApplicationProxy_class performSelector:@selector(applicationProxyForIdentifier:) withObject:bundle];NSString * canonicalExecutablePath = [proxyObj performSelector:@selector(canonicalExecutablePath)];複製代碼

0x02 尋找注入點添加擴展

接續看SBIconView,圖標上有兩個手勢對象:測試

  • 單擊,用來啓動App。
  • 長按,進入編輯狀態,執行刪除和排列圖標等操做。

因此,咱們來給圖標交互加個雙擊擴展。

%hook SBIconView

- (void)didMoveToWindow{    %orig;    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleClick:)];    [doubleTap setNumberOfTapsRequired:2];    [self addGestureRecognizer:doubleTap];    NSArray * ges = self.gestureRecognizers;    for(UITapGestureRecognizer * each in ges){        if([each isKindOfClass:[UITapGestureRecognizer class]]){            [each requireGestureRecognizerToFail: doubleTap];        }    }}複製代碼

這裏額外說一句,[each requireGestureRecognizerToFail: doubleTap]添加了雙擊手勢指揮,因爲iOS內部維護了手勢的狀態機,咱們進行單擊操做的時候,其實產生了兩種Possible State。第一種是識別爲單擊,而後結束。第二種是識別爲雙擊的第一下並等待第二下的發生,而後根據兩次點擊之時間間隔閾值來判斷是否是合法的雙擊。

因此咱們手動增長了約束,至關於指定了識別的優先級,只有雙擊失敗了,才繼續執行單擊回調。這種操做會帶來一點幾乎無感的瑕疵:單擊後等待雙擊識別失敗的延遲,延遲的值就是雙擊識別執行的閾值(大約零點幾秒)。

0x03 debugserver啓動和關閉

debugserver是一個二進制文件,狗神的教程裏有如何重籤,issh把這些過程給簡化了。先看一下debugserver的權限:
-rwxr-xr-x 1 root admin 9876848 Jan 19 11:28 /iOSRE/tools/debugserver*

再來看一下SpringBoard的權限:
-rwxr-xr-x 1 root wheel 71264 Dec 5 13:15 SpringBoard*

屬主用戶都是root,沒毛病。找個函數調用一下:

  1. system函數
  2. posix_spawn函數
  3. NSTask ,面向對象方便管理,異步執行,不會block UI,就用它了。

代碼以下:

task = [[NSTask alloc]init];[task setLaunchPath:bin_serverpath];[task setArguments:args];[task launch];複製代碼

每次server在launch以前,要把以前的task結束掉。

- (void)interrupt; // Not always possible. Sends SIGINT.複製代碼
- (void)terminate; // Not always possible. Sends SIGTERM.複製代碼

NSTask頭文件里居然告訴我 Not always possible。事實上,在調用的時候,還真的不怎麼possible,實際測試第一次server正常啓動,後續因爲沒成功關閉,因此第二次就無法啓動了。

因此仍是換種方式關閉吧。簡單粗暴的 kill 函數:

NSTask * task = [TaskManager sharedManager].runningTask;if(task){    kill(task.processIdentifier,SIGKILL);    task = nil;}複製代碼

0x04 添加UI交互

直接用Alert,又有按鈕又有輸入框,不過UIAlertView已經被廢棄掉了,須要用UIAlertController。因爲彈出Controller須要父Controller,經過View找到當前的Controller,作正向的應該都寫過這段代碼吧:

@implementation UIView(find)-(UIViewController*)findViewController{    UIResponder* target= self;    while (target) {        target = target.nextResponder;        if ([target isKindOfClass:[UIViewController class]]) {            break;        }    }    return (UIViewController*)target;}@end複製代碼

0x05 優化一下用戶體驗

輸入框裏的IP和debugserver的path,每一個人都不同,因此在第一次輸入完成以後,把這些值用NSUserDefault持久化存儲起來,下次直接讀取填充。

0x06後記

以前在相關技術論壇讀到討論用Root身份運行App的帖子,學習完帖子裏的技巧,加強對操做系統的理解以及實踐以後,發現若是真的想RootApp運行,其實SpringBoard自己就是一個RootApp,咱們把SpringBoard當作RootViewController,很容易把一些系統工具作出界面,從而提高生產力。好比砸殼、重籤、拷貝App等。

**
做者:TalkingData小張同窗

本文版權歸TalkingData全部,如需轉載請註明來源**

相關文章
相關標籤/搜索