写点什么

【iOS 逆向与安全】iOS 远程大师:通过 H5 后台远程查看和协助 iPhone 设备

作者:小陈
  • 2024-05-16
    四川
  • 本文字数:3115 字

    阅读完需:约 10 分钟

前言

在移动设备测试和远程协助的过程中,能够远程查看和协助 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 进行实时通信,以确保低延迟的指令传输。



  • 建立连接:前端与后端建立 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




发布于: 刚刚阅读数: 3
用户头像

小陈

关注

和昨天不一样 2019-03-12 加入

公众号:移动端Android和iOS开发技术分享

评论

发布
暂无评论
【iOS逆向与安全】iOS远程大师:通过H5后台远程查看和协助iPhone设备_移动端_小陈_InfoQ写作社区