assistd / go-ios

MIT License
2 stars 0 forks source link

dtx协议原理梳理及代码重构 #52

Open prife opened 1 year ago

prife commented 1 year ago

目标

  1. 参考最原始资料,梳理出iOS instrument dtx协议原理
  2. 根据原理,review go-ios/tidevice 拉起xctest app功能实现
  3. 修复go-ios拉起函数实现
    • app crash时,API应该返回,不应该阻塞
    • tcp中断时,API应该返回,不应该阻塞

参考资料

这里如何开启通道,以及数据解析,就要看向Troy Bowman 大佬在逆向工程大会上发布的演讲。 RECON-MTL-2018-Discovering_the_iOS_Instruments_Server.pdf

大佬的两个项目连接共大家参考 https://github.com/troybowman/dtxmsg https://github.com/troybowman/ios_instruments_client

DTXMessage Header 头解析 https://github.com/troybowman/ios_instruments_client/blob/master/ios_instruments_client.h https://github.com/facebook/idb/tree/master/PrivateHeaders IDB 仓库也有大量不同协议头,有兴趣的可自行查看,使用 python 构造 DTXMessage 头解析协议头示例

如何拿到 dtx 流数据可以参考项目: https://github.com/danielpaulus/dtx_codec 该项目可以直接获取和模拟器进行交互时的 dtx ,可以用来测试数据解析是否正常。

prife commented 1 year ago
prife commented 1 year ago

pymobileservice3 与go-ios中API对等异同

    def perform_handshake(self):
        args = MessageAux()
        args.append_obj({'com.apple.private.DTXBlockCompression': 0, 'com.apple.private.DTXConnection': 1})
        self.send_message(0, '_notifyOfPublishedCapabilities:', args, expects_reply=False)
        ret, aux = self.recv_plist()
        if ret != '_notifyOfPublishedCapabilities:':
            raise ValueError('Invalid answer')
        if not len(aux[0]):
            raise ValueError('Invalid answer')
        self.supported_identifiers = aux[0].value

类似的go-ios代码

func (d *Channel) MethodCallAsync(selector string, args ...interface{}) error {
    payload, _ := nskeyedarchiver.ArchiveBin(selector)
    auxiliary := NewPrimitiveDictionary()
    for _, arg := range args {
        auxiliary.AddNsKeyedArchivedObject(arg)
    }
    err := d.Send(false, Methodinvocation, payload, auxiliary)
    if err != nil {
        log.WithFields(log.Fields{"channel_id": d.channelName, "error": err, "methodselector": selector}).Info("failed starting invoking method")
        return err
    }
    return nil
}
prife commented 1 year ago

2.1比如这里必须生成两次,一个config用两次必崩溃,绝对是它序列化程序写的有问题

企业微信截图_bfadaaa4-6e76-425a-b1b9-6f6c26eba83e

2.2 这个1秒不能少,否则能拉起进程,但是test不执行

企业微信截图_af95ecf4-ca13-4120-9b24-fa971e0dadf2

2.3 这里go-ios写错了

image
err = ideDaemonProxy2.daemonConnection.startExecutingTestPlanWithProtocolVersion(ideInterfaceChannel, 25)

但是startExecutingTestPlanWithProtocolVersion这个函数的实现根本不需要传什么对象
func (xdc XCTestManager_DaemonConnectionInterface) startExecutingTestPlanWithProtocolVersion(channel *dtx.Channel, version uint64) error {
    return channel.MethodCallAsync("_IDE_startExecutingTestPlanWithProtocolVersion:", version)
}
prife commented 1 year ago

代码已经推送到wdb分支