【iOS逆向與安全】iOS遠端大師:透過H5後臺遠端檢視和協助iPhone裝置

移动端小陈發表於2024-05-16

前言

在移動裝置測試和遠端協助的過程中,能夠遠端檢視和協助iPhone裝置是一項非常實用的功能。為了解決這一需求,我開發了一款名為iOS遠端大師的產品,允許使用者透過H5後臺介面檢視和協助越獄或非越獄的iPhone裝置。本文將詳細介紹iOS遠端大師的開發過程和技術實現。


一、技術實現

整個專案的核心技術包括H5前端介面、WebSocket通訊、伺服器轉發和iPhone裝置處理。下面將分步驟介紹每個部分的實現。

1. H5前端介面

在H5前端,我使用了vue框架來構建使用者介面。使用者透過這個介面可以實時檢視iPhone的螢幕,並透過滑鼠傳送互動指令。

  • 實時螢幕顯示:透過WebSocket連線,接收伺服器轉發的iPhone螢幕影像,並在H5頁面上進行渲染。
  • 使用者指令捕獲:在div中監聽使用者的滑鼠事件,並將這些事件轉換為特定的指令格式。

橫屏座標轉換

在前端實現中,處理橫屏模式下的座標轉換至關重要。在 H5 後臺將裝置切換為橫屏時,儘管你看到的介面已經是橫屏了,但 iPhone 端實際仍然是豎屏,因此必須進行座標轉換,以確保點選事件能夠在正確的位置被執行,並且保持顯示的一致性。

const convertCoordinates = (width, height, clickX, clickY) => {
  const angle = rotateAngle.value % 360
  if (angle === -90) {
    const rotatedX = height - clickX * Math.cos(angle * Math.PI / 180) + clickY * Math.sin(angle * Math.PI / 180)
    const rotatedY = -clickX * Math.sin(angle * Math.PI / 180) + clickY * Math.cos(angle * Math.PI / 180)
    clickX = rotatedX
    clickY = rotatedY
  } else if (angle === -180) {
    const rotatedX = width - clickX
    const rotatedY = height - clickY
    clickX = rotatedX
    clickY = rotatedY
  } else if (angle === -270) {
    const rotatedX = clickY
    const rotatedY = width - clickX
    clickX = rotatedX
    clickY = rotatedY
  }
  return { clickX, clickY }
}

2. WebSocket通訊

前端和裝置之間採用WebSocket進行實時通訊,以確保低延遲的指令傳輸。

image-20240515180325536

  • 建立連線:前端與後端建立WebSocket連線,確保雙向通訊的實現。
  • 指令傳送:使用者在前端頁面上進行互動操作,前端將這些指令傳送給後端,透過WebSocket進行傳輸。
  • 指令轉發:後端接收到前端傳送的指令後,根據指令內容識別目標裝置,並將指令下發到對應的裝置。
  • 執行指令:目標裝置接收到後端傳送的指令,並執行相應的操作。
  • 結果回傳:裝置執行完指令後,將執行結果傳送給後端,後端再透過WebSocket將結果回傳給前端,以供使用者檢視或處理。

3. iPhone裝置處理命令

在iPhone裝置端,我們區分越獄和不越獄裝置的支援情況。

  • 越獄裝置:支援iOS 12到14版本,透過私有API實現更深層次的操作。主要包括硬體觸發和螢幕點選。

    • 按鍵操作:透過私有API直接觸發iPhone的硬體功能,例如電源、Home鍵、音量+-等操作。
    • 螢幕點選:利用越獄許可權,直接在螢幕座標上模擬觸控事件。

    按鍵操作的部分程式碼如下:

    + (void)sendHIDEventWithUsagePage:(uint16_t)usagePage usage:(uint16_t)usage down:(Boolean)down {
        uint64_t abTime = mach_absolute_time();
        IOHIDEventRef event = IOHIDEventCreateKeyboardEvent(kCFAllocatorDefault, abTime, usagePage, usage, down, 0);
        IOHIDEventSetIntegerValue(event,4, 1);
        IOHIDEventSetSenderID(event, senderID);
        postIOHIDEvent(event);
    }
    
    static void postIOHIDEvent(IOHIDEventRef event)
    {
        static IOHIDEventSystemClientRef ioSystemClient = NULL;
        if (!ioSystemClient){
            ioSystemClient = IOHIDEventSystemClientCreate(kCFAllocatorDefault);
        }
        if (senderID != 0) {
            IOHIDEventSetSenderID(event, senderID);
        } else {
            return;
        }
        IOHIDEventSystemClientDispatchEvent(ioSystemClient, event);
    }
    

    具體的按鍵程式碼可參考:https://iphonedev.wiki/IOHIDFamily

    螢幕點選的部分程式碼如下:

    // 示例程式碼:使用私有API觸發螢幕點選
    void simulateTouch(CGFloat x, CGFloat y) {
        // 在實現模擬滑動過程中,滑動效果始終不理想,最終放棄。引用IOS13-SimulateTouch 專案來實現了螢幕的點選和滑動
        // 具體實現參考 IOS13-SimulateTouch 專案
        // https://github.com/xuan32546/IOS13-SimulateTouch
    }
    

    在這也要感謝微信群裡的 @福州-啊嘴 在模擬滑動中提供的幫助

  • 非越獄裝置:支援iOS 15及以上版本,利用XCUITest實現硬體的觸發和螢幕的點選。

    • 硬體觸發:透過XCUITest框架模擬按鍵操作。
    • 螢幕點選:使用XCUITest框架在指定座標模擬點選。

    按鍵操作的部分程式碼如下:

    + (void)sendHIDEventWithUsagePage:(uint16_t)usagePage usage:(uint16_t)usage down:(Boolean)down {
      if (usage == 0xe9) {
        [[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonVolumeUp];
      } else if (usage == 0xea) {
        [[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonVolumeDown];
      } else if (usage == 0x30 && down) {
        if ([XCUIDevice sharedDevice].fb_isScreenLocked) {
          [[XCUIDevice sharedDevice] fb_unlockScreen:nil];
        } else {
          [[XCUIDevice sharedDevice] fb_lockScreen:nil];
        }
      }
    }
    
    + (void)simulateHome {
      [[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonHome];
    }
    

    螢幕點選的部分程式碼如下:

    @interface XCUICoordinate ()
    
    // 滑動事件
    - (void)pressForDuration:(double)arg1 thenDragToCoordinate:(id)arg2;
    
    // 點選事件
    - (void)pressForDuration:(double)arg1;
    
    @end
    
    
    + (void)simulateClick:(CGPoint)tapPoint {
        // 在 https://github.com/appium/WebDriverAgent 專案已經有現成封裝好的程式碼,在這就直接拿來用了
        CGFloat x = tapPoint.x;
        CGFloat y = tapPoint.y;
        CGSize screenSize = [self getScreenSize];
        double multiple = screenSize.width / remote_device_screen_width;
        x = x * multiple;
        y = y * multiple;
           
        FBRouteRequest *request = [[FBRouteRequest alloc] init];
        request.arguments = @{@"x": @(x), @"y": @(y), @"duration": @0.001};
        NSLog(@"witwit simulateClick =%@=", request.arguments);
        [FBElementCommands handleTouchAndHold:request];
    }
    

二、具體功能

iOS遠端大師主要實現了以下幾個功能:

  1. 實時螢幕顯示:使用者可以在H5介面實時檢視iPhone的螢幕。
  2. 遠端協助:支援鍵盤輸入、觸屏操作等常見互動方式,以便對遠端iPhone進行協助。
  3. 多裝置管理:支援同時連線和管理多個iPhone裝置。

三、遇到的問題及解決方案

在開發過程中,我也遇到了幾個主要問題:

模擬滑動:在越獄機上的模組滑動效果始終不理想,豎滑正常,橫滑始終反應,折騰了好久,最終放棄,直接引用了IOS13-SimulateTouch專案程式碼。
越獄裝置socket連線偶爾斷開 :在socket失去連線時,有重新建立連線,但還是有偶現的裝置掉線線情況,後邊有時間再處理。
裝置相容性:在越獄機上的12,13,14系統能正常執行,非越獄機15和16部分機型能正常執行。

總結

透過開發iOS遠端大師,我們不僅實現了H5後臺遠端檢視和協助iPhone的功能,還積累了豐富的經驗和技術儲備。希望這篇文章能對有類似需求和興趣的開發者提供一些參考和啟發,如你需要體驗該專案,請聯絡我。

提示:閱讀此文件的過程中遇到任何問題,請關住工眾好【移動端Android和iOS開發技術分享】或+99 君羊【812546729

image-20230225231548837

相關文章