首页
论坛
课程
招聘
[翻译]发现iOS INstruments服务器
2018-8-8 16:10 2913

[翻译]发现iOS INstruments服务器

2018-8-8 16:10
2913

Recon Montreal 2018

 

(译者按:原文来自于一个安全会议上的演讲PPT,有疑问处请直接访问这里)

本次讨论的目的

  • 分享我们的发现
  • 我们所有步骤的文档
  • 搞起!
什么是Instruments?
  • Instruments是一个由苹果开发的调试工具集
    – 时间分析
    – 泄露检测
    – 追踪文件I/O操作
    所有的这些任务都能在iOS上运行

  • 为此,苹果实现了一个服务器,该服务器旨在为在OSX上运行的Instruments前端提供iOS调试统计数据
    这个服务器简直就是我们所有想要的有用信息的宝库
    图片描述

  • 这个服务器是怎么和OSX数据交换的?IDA能相应它吗?
  • 从这儿开始:找出Xcode怎么查询Instruments这个进程列表的服务器(目标设备上运行的每个进程,还有它的PID)

我们所知道的

  • 不管怎么说,我们会和iOS的一个内部进程通信(通常在iOS上被禁止)

  • MobileDevice.framework提供了OSX上应用和iOS上进程通信的能力,也就是 “Services”

  • 这是IDA和iOS debugserver通信的方式

  • 我们够幸运的话,那儿也会有一个Instruments服务器的service:

$ hdiutil mount DeveloperDiskImage.dmg
– com.apple.debugserver.plist
– com.apple.instruments.remoteserver.plist
– com.apple.instruments.deviceservice.plist

// launch the debugserver service
static bool start_dbgsrv(void *device_handle)
{
 void *srv_handle = NULL;
 mach_error_t err = AMDeviceSecureStartService(
 device_handle,
 CFSTR(“com.apple.debugserver”),
 &srv_handle);
 if ( err != 0 )
 return false;
 char buf[1024];
 size_t nrecv = AMDServiceConnectionReceive(
 srv_handle,
 buf,
 sizeof(buf));
 printf(“received %llx bytes\n”, nrecv);
 return true;
}

DVTInstrumentsFoundation

__text:00000001000F96F4
__text:00000001000F96F4 ; =============== S U B R O U T I N E =======================================
__text:00000001000F96F4
__text:00000001000F96F4 ; Attributes: bp-based frame
__text:00000001000F96F4
__text:00000001000F96F4 ; id __cdecl -[DTDeviceInfoService runningProcesses](DTDeviceInfoService *self, SEL)
__text:00000001000F96F4 __DTDeviceInfoService_runningProcesses_ ; DATA XREF: __objc_const:00000001001935C8
o
__text:00000001000F96F4
__text:00000001000F96F4 var_250 = -0x250
__text:00000001000F96F4 var_230 = -0x230
__text:00000001000F96F4 ...
__text:00000001000F96F4
__text:00000001000F96F4 STP X28, X27, [SP,#-0x10+var_50]!
__text:00000001000F96F8 STP X26, X25, [SP,#0x50+var_40]
  • DTServiceHub, DVTInstrumentsFoundation类库实现了Instruments的核心功能
  • 在DVTInstrumentsFoundation中,我们发现了一个有趣的方法 - [DTDeviceInfoService runningProcesses]
    *这个方法调用+[NSProcessInfo processInfo],然后生成一个带有每个进程描述的NSMutableArray,然后把它返回
  • 棒呆!看起来我们在对的路上了,但是...
    – There are no xrefs to this method
    这个方法没有交叉引用
  • 在iOS的开发者工具的其他地方似乎没出现runningProcesses这个Selector
  • 谁调用的它??栈追踪应该有用

DTXMessage

  • DTXMessage 类负责序列/反序列化Objective-C消息
  • 此类的实例可以编码需要的信息来调用给定Objective-C方法:
    图片描述
  • Instruments通过从缓冲区读取序列化消息来调用关键逻辑。此序列化数据的来源是什么?
  • 一个线程从缓冲区读取序列化的消息:
00000001816A1014 000000018157E3E4 00000001000C8C4C 00000001000C87A4 00000001000C8510 000000018156D4B8
libsystem_kernel.dylib libdispatch.dylib DTXConnectionServices DTXConnectionServices DTXConnectionServices libdispatch.dylib
_semaphore_wait_trap+8
__dispatch_semaphore_wait_slow+F0
-[DTXMessageParser waitForMoreData:incrementalBuffer:]+68
-[DTXMessageParser parseMessageWithExceptionHandler:]+40
-[DTXMessageParser initWithMessageHandler:andParseExceptionHandler:]_block_invoke+24 __dispatch_call_block_and_release+14
  • 分析每条消息后, 将调度另一个线程来执行调用:
00000001001096F4 0000000181B28ADC 0000000181A20544 00000001000CD3D0 00000001000C49980 000000018156D4B8
DVTInstrumentsFoundation CoreFoundation CoreFoundation DTXConnectionServices DTXConnectionServices libdispatch.dylib
id __cdecl -[DTDeviceInfoService runningProcesses](DTDeviceInfoService *self, SEL) ___invoking___+8C
-[NSInvocation invoke]+118
-[DTXMessage invokeWithTarget:replyChannel:validator:]+2C8
-[DTXChannel _scheduleMessage:tracker:withHandler:]_block_invoke697+7C __dispatch_call_block_and_release+14

浏览 Xcode IDE 二进制文件, 我们在 IDEiPhoneSupport 中发现了这一点:
图片描述
这个关键的代码块实际上是一个反编译的block函数。原始源代码可能类似于:

@implementation DVTiPhoneProcessInformation
+ (void) requestCurrentProcessInformationForDevice:(id)device {
  id server  = [device primaryInstrumentsServer];
  id channel = [server makeChannelWithIdentifier:@"com.apple.instruments.server.services.deviceinfo"];
  if ( channel )
  {
    [DVTFuture futureWithBlock:^{
      [channel sendControlAsync:[DTXMessage messageWithSelector:"runningProcesses" objectArguments:Nil]];
}]; }
}
@end

结论: DTXMessage 是一种通过网络传输Objective-C消息的机制。这允许进程在另一个进程中有效地 "调用" 给定的方法 (可以在完全独立的设备上运行)

 

现在怎么办?

 

可以从反汇编中逆向工程序列化Objective-C消息的, 但这是一个艰难的战斗

 

即使我们完全理解消息序列化, 它仍然没有把故事讲完整。如果服务器只响应特定的消息序列, 该怎么办?

 

另一种方法是获取通过导线传输的原始数据的样本。静态 + 方法动态获取的成功几率更高。

 

再次, iOS 调试器的救援!

 

特别设置的断点将允许我们记录服务器收到的每个序列化消息:
图片描述

dtxmsg

我开发了一个 IDA 插件自动记录消息

 

https://github.com/troybowman/dtxmsg

 

插件使用反汇编的微代码检测在内存中序列化消息的位置和时间, 并将字节转储到文件
更多关于微码, 详见Ilfak在Recon Brussels 2018的谈话

 

该插件还可以反序列化每个截获的消息, 并以纯文本的形式将有效负载打印到文件中 (稍后再详细介绍)

解剖DTXMessage

图片描述
它看起来像是使用 NSKeyedArchiver 序列化方法选择器, 但是方法参数呢?
runningProcesses 不接受任何参数, 所以让我们看一个不同的消息:

 

真相正在浮出水面, 但仍然有一个缺失的链接: 消息接收器。谁来决定接收邮件的对象?

 

记得, 我们注意到这样的东西在 Xcode:

id channel = [server makeChannelWithIdentifier:@"com.apple.instruments.server.services.deviceinfo"]; [channel sendControlAsync:[DTXMessage messageWithSelector:"runningProcesses" objectArguments:Nil]];

-[DTXConnection makeChannelWithIdentifier:] 似乎确定消息接收器。这个方法做了什么?请注意, 我们捕获了此消息:
图片描述
让我们总结一下:
在查询进程列表时, Xcode 向仪器发送了5条消息
服务器:

– _notifyOfPublishedCapabilities:
– _requestChannelWithCode:identifier:
● identifier = "com.apple.instruments.server.services.deviceinfo" – _requestChannelWithCode:identifier
● identifier = "com.apple.instruments.server.services.device.applictionListing” – runningProcesses
– installedApplicationsMatching:registerUpdateToken:

最后步骤: 反编译

请记住, 我们的目标是独立地与服务器通信, 而无需 Apple 代码的帮助。

 

我们对序列化消息的理解必须是完美的
幸好我们已经有了很多线索
IDA 在这里是无价之宝。我们可以积极改进反编译迄今为止我们已经找到了的所有关键方法。

 

反编译产生一些重要的结构体:

// a DTXMessage object in memory
struct DTXMessage
{
  NSObject super;
  int32 _messageType;
  int32 _compressionType;
  uint32 _status;
  id _destructor;
  const char *_internalBuffer;
  uint64 _internalBufferLength;
  uint64 _cost;
  id _payloadObject;
  void *_auxiliary;
  bool _deserialized;
  bool _immutable;
  bool _expectsReply;
  uint32 _identifier;
  uint32 _channelCode;
  uint32 _conversationIndex;
  NSDictionary *_auxiliaryPromoted;
};
// header for serialized message data
struct DTXMessageHeader
{
  uint32 magic;
  uint32 cb;
  uint16 fragmentId;
  uint16 fragmentCount;
  uint32 length;
  uint32 identifier;
  uint32 conversationIndex;
  uint32 channelCode;
  uint32 expectsReply;
};
// layout of serialized payload
struct DTXMessagePayloadHeader
{
  uint32 flags;
  uint32 auxiliaryLength;
  uint64 totalLength;
};

解剖 DTXMessage: 终章

图片描述

 

我们终于准备好开始自己发送消息了

 

独立应用程序 (dtxmsg_client) 也包含在 dtxmsg 插件源中。

 

此应用程序能够调用 runningProcesses 方法, 检索其返回值, 并以纯文本形式打印它

 

目标完成!

 

此应用程序的源代码可供参考

 

我们还有其他一些可能感兴趣的方法:

– -[DTApplicationListingService installedApplicationsMatching:registerUpdateToken:]
– -[DTProcessControlService launchSuspendedProcessWithDevicePath:bundleIdentifier:environment:arguments:]
 – -[DTProcessControlService killPid:]

dtxmsg_client 可以调用所有这些方法

 

它们提供了对如何处理复杂方法参数和返回值的更多了解

将来的工作

Instruments服务器负责的不仅仅是简单的进程控制

 

DTXMessage 也被其他 iOS 开发工具使用

 

希望这只是个开始!

 

谢谢大家赏脸!

 

原文:https://github.com/troybowman/dtxmsg/blob/master/slides.pdf

 

翻译:daemond【看雪翻译小组】


[公告]名企招聘!

收藏
点赞0
打赏
分享
打赏 + 1.00
打赏次数 1 金额 + 1.00
 
赞赏  junkboy   +1.00 2018/08/08
最新回复 (0)
游客
登录 | 注册 方可回帖
返回