windows中的苹果USB过滤驱动与iPhone-WPD工作原理

admin 2023年8月13日19:43:08评论138 views字数 19229阅读64分5秒阅读模式

Windows 设备上的 Apple USB 下置过滤器如何帮助控制设备配置

如果您曾经将 iPhone、iPad 或 iPod 连接到 Windows PC,您可能已经注意到该设备显示为不同类型的设备,具体取决于您使用它做什么。例如,如果您正在为 iPhone 充电,它可能会显示为“USB 复合设备”,但如果您正在与 iTunes 同步音乐,它可能会显示为“Apple Mobile Device USB 驱动程序”。你有没有想过这是如何工作的?事实证明,苹果在Windows机器上有一个USB下过滤器,可以帮助他们控制操作系统使用哪些USB配置。

这篇博文将分为两部分:首先,我们将探讨 Apple 的 USB 下层过滤器的工作原理、它的作用以及无论是否安装了 Apple 软件,它如何提供不同的体验,其次,我们将调查为什么当设备的 WPD 属性指示设备正在使用协议媒体传输协议 (MTP) 时,iPhone 的开箱即用文件操作如此有限。我们将深入研究 Windows 便携式设备 (WPD)、USB 描述符和用户模式驱动程序框架 (UMDF) 等主题。WPD_DEVICE_PROTOCOL

备注:这篇文章的研究是使用Windows 11 22H2,AppleLowerFilter版本486.0.0.0和iPhone SE第二代进行的。

赋予动机

这篇博文背后的动机是一种好奇心,这种好奇心源于将iPhone连接到Windows机器时提供的有限选项。令人惊讶的是,查看iPhone的WPD属性,WPD设备协议被定义为,这很奇怪,因为接口描述符定义的类是Image。这种不匹配以及在不使用Apple软件的情况下与设备交互的有限选项困扰着我,因此我决定进行调查以尝试阐明这些观察结果。MTP: 15.20

初始化苹果的 USB 下部过滤器

Apple 设备将自己呈现为具有多个接口的复合设备,以确保正确识别其设备并加载所有必要的驱动程序。这是因为 Apple 设备通常具有多个接口,这些接口提供不同的功能,例如音频、视频和控制。当我们将Apple设备插入Windows机器时,总线适配器会识别该设备并将其硬件ID和兼容ID提供给操作系统。这些 ID 用于根据 ID 的匹配质量在驱动程序存储区中搜索最佳驱动程序。若要使总线驱动程序将此设备视为复合设备,必须满足某些要求。如果无法满足这些要求,操作系统将不会自动加载 USB 复合设备类驱动程序 (usbccgp)。在这种情况下,我们需要提供一个 INF 来加载通用父驱动程序,对于苹果来说,它是文

件 AppleUSB.inf


对于iPhone,未满足的要求是设备具有多种配置()。bNumConfigurations == 4


这个单一的INF文件包含不同设备(例如AppleUSB,AppleUsbHomePod和AppleUsbWatch)的各种设置配置。对于iOS设备,硬件ID将完全匹配,因此操作系统将应用AppleUSB设置配置,这将复制并在设备特定的注册表项下添加以下值:AppleLowerFilter.sys


[AppleUSB_CCGPDriverInstall_AddReg.HW]HKR,,"OriginalConfigurationValue",0x00010001,2HKR,,"UsbccgpCapabilities",0x00010001,0x10      ; Selective suspend for USB devices attached to the USB Composite Parent DriverHKR,,FriendlyName,,%iPhone.AppleUSB.DeviceDesc% ;"Apple Mobile Device USB Composite Device"HKR,,LowerFilters,0x00010000,AppleLowerFilter

该值可在设备的硬件注册表项中为 Usbccgp.sys 驱动程序设置。它确定应将复合设备的哪个配置用作默认配置。首次插入复合设备时,系统会读取原始配置值并加载指定的配置。这对于具有多个配置的复合设备非常有用,其中一种配置可能首选为默认配置。更多信息。OriginalConfigurationValue


安装驱动程序包后,Microsoft将详细介绍以下步骤 - Windows 如何安装设备:步骤 3 - 设备将重新启动。- 重新启动后,PnP 管理器识别设备的功能驱动程序和任何可选的筛选器驱动程序,构建设备堆栈 - 在我们的例子中,FDO 是 Usbccgp,LowerFiDO 是 AppleLowerFilter - 并通过为尚未加载的任何所需驱动程序调用 DriverEntry 例程来启动设备。然后为每个驱动程序调用 AddDevice 例程,从较低筛选器的驱动程序开始,然后是函数驱动程序。如果需要,将分配资源,PnP 管理器会向设备的驱动程序发送IRP_MN_START_DEVICE

深入了解苹果的USB下部过滤器

在上一节中介绍了 AppleLowerFilter 枚举和安装背后的理论之后,我们现在将仔细研究驱动程序的工作原理以及它在启用 Windows 机器上的 Apple 设备功能方面所扮演的角色。

作为 WDF 驱动程序,PnP 调用驱动程序条目的第一步是初始化框架并绑定 WDF 版本(在本例中为 WDF 1.15)。完成此操作后,框架将调用我们的 DriverEntry 函数,在 AppleLowerFilter 的情况下,驱动程序条目将简单地创建一个驱动程序对象,并在 .AppleLowerFilter 的 AddDevice 例程将执行以下操作:WDF_DRIVER_CONFIG


通过调用 WdfFdoInitSetFilter 将自身标识为 FiDO。

为事件注册 PnP 和电源管理回调:


EvtDevicePrepareHardware

EvtDeviceReleaseHardware

EvtDeviceD0Entry

EvtDeviceD0Exit

为 IRP 设置两个 IRP 预处理回调:


IRP_MJ_PNP

IRP_MJ_INTERNAL_DEVICE_CONTROL

最后,使用名为“上下文类型信息”创建 DO。FILTER_EXTENSION (sizeof == 0x50)


在上电序列期间,我们感兴趣的下一步是准备上电硬件,这意味着调用过滤器注册的 EvtDevicePrepareHardware 回调。这可能是AppleLowerFilter中最有趣的一步,所以让我们仔细看看它。

回调的第一步是检索 USB 描述符,这是通过我调用的函数完成的。此函数用于检索 USB 设备的 USB 设备描述符。这是通过为 URB(USB 请求块)分配内存并使用类型来完成的,该类型是从 USB 设备检索描述符的请求。请求的描述符是 ,它提供有关 USB 设备的信息,例如其供应商和产品 ID、设备类和协议。该函数同步提交 URB 以检索描述符。GetUsbDeviceDescriptorURB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICEUSB_DEVICE_DESCRIPTOR_TYPE


对于苹果正在使用usbdlib的大多数USB相关操作,这有点令人惊讶,因为这是一个WDF驱动程序,他们本可以使用wdfusb标头,我个人认为这会简化事情🙂。

然后,驱动程序将 存储到上下文中,并继续调用我认为此驱动程序的主要函数:。在描述内部结构之前,让我们看一下此函数的简单伪代码:bNumConfigurationsFILTER_EXTENSIONGetPreferredConfig





int PreferredConfig;if (FilterCtx->bNumConfigurations == 1) { PreferredConfig = 1;} else { if( !NT_SUCCESS( GetDeviceConfigUrb(WdfDevice, &PreferredConfig) ) { PreferredConfig = 3; }}

FilterCtx->DeviceConfig = PreferredConfig;if( !QueryAppleSoftwarePresent() ){ PreferredConfig = 1;}

if ( PreferredConfig >= FilterCtx->bNumConfigurations) { PreferredConfig = FilterCtx->bNumConfigurations;}

if ( PreferredConfig >= 5 ) { return 5;}

return PreferredConfig;

此功能将首先检查设备的配置数量是否为 1。如果是,则首选配置设置为 1。否则,代码将发送 URB 以检索首选配置。如果 URB 请求失败,则首选配置设置为 3。然后,代码在 FilterCtx 结构中设置字段。然后,它会检查函数是否返回 false(表示未安装 Apple 软件),如果是,则将首选配置设置为 1。然后,代码检查首选配置是否大于或等于设备描述符中指定的配置数。如果是,则首选配置设置为最大配置数。最后,如果首选配置大于或等于 5,则代码返回 5。DeviceConfigQueryAppleSoftwarePresent


此函数中有几个关键点,我们将更深入地研究。首先突出的是函数,此函数将为 URB 分配内存,设置 URB 以发出特定于供应商的控制请求,然后将 URB 同步提交到 USB 驱动程序堆栈。发出的特定供应商请求是请求类型为 69 的控制传输和包含 <> 字节数据的传输缓冲区。GetDeviceConfigUrb



Urb->UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE;Urb->UrbHeader.Length = sizeof(_URB_CONTROL_VENDOR_OR_CLASS_REQUEST);Urb->UrbControlVendorClassRequest.TransferBufferLength = 1;Urb->UrbControlVendorClassRequest.TransferBuffer = preferredConfig;Urb->UrbControlVendorClassRequest.Request = 69; // Curious number choice by the Apple guys :DUrb->UrbControlVendorClassRequest.Value = 0;Urb->UrbControlVendorClassRequest.Index = 0;Urb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_OUT | USBD_SHORT_TRANSFER_OK;Status = SubmitUrbSync(wdfDevice, UsbdHandle, Urb);

选择首选配置的下一个关键点是函数,这个函数起着重要作用,因为它的返回值将决定我们是否总是被限制在一个首选配置上。此函数将执行以下操作:QueryAppleSoftwarePresent


// Check if we have already found the Apple Mobile Device Serviceif (gAppleMobileServiceFound) {    return 1;}

// pseudocode just for simplicity auto EventString{"\BaseNamedObjects\com.apple.MobileDeviceProcess.QueryMuxReady"};// Try to open the MuxReady eventif ( NT_SUCCESS( ZwOpenEvent(&eventHandle, STANDARD_RIGHTS_REQUIRED, &EventString) ) ) { ZwClose(eventHandle) return 1;}

// I believe this is old behavior. At least with the latest version of iTunes from the// Microsoft Store, these keys are not created.auto serviceFound = QueryRegistry( L"\Registry\Machine\System\CurrentControlSet\Services\Apple Mobile Device Service", L"ImagePath");auto appFound = QueryRegistry( L"\Registry\Machine\System\CurrentControlSet\Services\Apple Mobile Device App", 0);

if (serviceFound || appFound) { // Apple Mobile Device Service and app were found, so set the global flag gAppleMobileServiceFound = true; return 1;}

// Apple NT event, Apple Mobile Device Service and app not found, so return 0return 0;

回到函数,这个值起着很大的作用,因为这个函数返回的数字将用于覆盖设备的注册表项。GetPreferredConfigOriginalConfigurationValue

注意:返回的值将减去 1,因为 描述的注册表值对应于 USB 定义的配置索引,由配置描述符 () 的成员指示,而不是由设备配置描述符中报告的 bConfigurationNum 值指示。GetPreferredConfigOriginalConfigurationValuebConfigurationValueUSB_CONFIGURATION_DESCRIPTOR


我们刚刚看到的是,为什么即使您的INF将值写入 如果您将iPhone插入未安装iTunes的PC,您将在注册表中看到以下内容:2OriginalConfigurationValue

windows中的苹果USB过滤驱动与iPhone-WPD工作原理

在注册表中设置 后,EvtDevicePrepareHardware 函数将调用 WdfUsbTargetDeviceCreate 来创建 USB 目标设备对象。USB 目标设备对象表示基础 USB 设备,并为驱动程序提供与设备通信的方法。OriginalConfigurationValue


要定期检查首选配置,该函数会设置 .将定期调用计时器的回调函数,以检查首选配置是否已更改。如果首选配置已更改,则该函数将同步调用 WdfUsbTargetDeviceCyclePortSync,以便意外删除并重新枚举设备,以便使用新配置加载。WDFTIMER


计时器设置了一个句点,因此框架不会调用计时器。另一方面,筛选器将从计时器的回调函数和 D5Entry 回调中以 0 秒(相对于当前系统时间)的 DueTime 进行调用。0WdfTimerStart


现在,让我们查看这两个 IRP 预处理回调,以全面了解驱动程序工作流。IRP 的预处理允许驱动程序在将 IRP 发送到默认处理程序或堆栈中的另一个驱动程序之前修改或重定向 IRP。让我们首先看一下内部设备控制请求的处理程序。此函数将检查 IRP 是否IOCTL_INTERNAL_USB_SUBMIT_URB请求以选择 USB 配置。如果是,该函数将获取设备的句柄,转发 IRP,然后检索具有类 Image 的 USB 接口的管道句柄。中断、批量输入和批量输出的管道句柄将存储在设备上下文中。

现在,让我们看一下 PnP IRP 预处理的处理程序。在这种情况下,句柄将处理两种情况:-IRP_MN_QUERY_DEVICE_RELATIONS - IRP_MN_QUERY_ID。QueryID IRP 的情况非常简单,该函数将检查 - 请记住,此值是通过供应商特定的 URB 获得的 - 是否设置为 1,如果是,该函数会将字符串附加到返回的信息和请求。FilterCtx->DeviceConfig&RESTORE_MODEBusQueryHardwareIDsBusQueryDeviceID。

另一方面,QueryDeviceRelation 更有趣一些。首先,此处理程序仅在某些计时器未运行(稍后会详细介绍)并且计算机上安装了Apple软件时才执行。它只会处理总线关系 IRP,它将同步转发请求并检查状态是否成功。如果返回任何信息,它将在返回的设备对象列表中查找其 CompatibleId 包含 的设备。如果找到,它会取消引用此 DO,然后将其从列表中删除并更新设备计数 – 这将使即使 usbccgp 为 WPD 设备创建了 PDO,PnP 也不会看到 DO,因为返回的列表不会有它。很快我们将看到较低的过滤器如何处理这个问题。USBClass_06


如果找到类 6 的设备,则该函数将根据 DbgPrints 设置另一个 WDF 计时器,我们将其称为 PtpTimer,它在 5 秒后触发。触发时,回调将在 deviceContext 中设置一个标志,以便 QueryDeviceRelations 处理程序不再处理请求,将检查 iTunes 是否存在,如果存在,它将向 USB 设备发送以下一组 PTP/MTP 操作请求数据包。

打开会话 - 操作代码:0x1002

供应商扩展 - 操作代码:0x9008

关闭会话 - 操作代码:0x1003

下面的 USB 数据包捕获说明了这些操作的执行,请注意它们在该端口上捕获大约 5 秒后是如何发生的。

windows中的苹果USB过滤驱动与iPhone-WPD工作原理

我已经尽一切努力获取有关操作0x9008的更多信息,但似乎没有任何关于Apple设备的信息。我能得到的最好的是ChatGPT说“PTP / MTP数据包中的操作命令0x9008通常对应于”Apple设备信息“命令”。不幸的是,我要求提供证明这一点的文档/报价,聊天给我的每个链接要么无效,要么不可用/已弃用的Apple文档。给定名称“Apple Device Info”,我认为它类似于 PTP/MTP 命令“GetDeviceInfo”,但我在机器命令上尝试的每个测试似乎0x9008都没有数据阶段,所以我最好的猜测是要么不是“设备信息”命令,要么 Apple 设备不再响应该命令。但是,如果有人对此命令有更多信息,请联系,我很想听到更多关于它🙂的信息!


 作为参考,来自ChatGPT的引用/链接:


windows中的苹果USB过滤驱动与iPhone-WPD工作原理

最后,在发送 PTP/MTP 请求后,PtpTimer 将使用关系类型进行调用,这将触发新的 IRP 查询设备关系,但由于此时计时器已执行,因此处理程序不会从“设备”列表中删除 WPD 设备。因此,这次PnP管理器我们将实际看到WPD设备的PDO,并开始为其构建堆栈。下图显示了通过将我们自己的 LowerFilter 添加到堆栈并仅跟踪 IRP 由 AppleLowerFilter 处理的前置和后捕获的此行为。IoInvalidateDeviceRelationsBusRelation

windows中的苹果USB过滤驱动与iPhone-WPD工作原理

我不知道苹果为什么要这样做,我的猜测是带有操作代码0x9008的 PTP 数据包以某种方式通知设备主机上存在 iTunes 或这些行周围的内容。我没有注意到在安装或不安装iTunes的WPD设备上有任何不同的行为,除了WPD设备需要5秒钟才能实际显示。从设备的 LowerFilter 列表中删除 AppleLowerFilter 似乎不会对 WPD 设备的行为产生任何重大影响。再说一次,如果有人知道更多关于苹果为什么要这样做,我很想听听!

这几乎就是AppleLowerFilter的行为方式,可以看出它主要在设备初始化期间工作,除此之外,检查活动配置的计时器将每5秒在后台运行一次,以查看端口是否必须重新枚举。

PTP还是MTP,这是个问题

在本节中,我们将重点介绍为什么iPhone没有像我们对使用MTP协议的设备所期望的那样在其存储上提供一整套操作。我们还将调查 USB 接口类/子类与属性不匹配的原因。为了回答这些问题,我们将了解如何创建 WPD 设备、如何“装载”存储以及如何设置 WPD 属性。WPD_DEVICE_PROTOCOL


首先让我们看看使用 PTP 和 iPhone 连接的 Android 设备之间的 WPD 设备协议属性的差异:

windows中的苹果USB过滤驱动与iPhone-WPD工作原理


鉴于iPhone中的WPD协议属性,我们希望有一组更丰富的选项来与设备进行交互。我们可以通过查看设备的接口描述符来快速回答为什么iPhone表现为PTP设备。请参阅以下 iPhone 和小米在 PTP 和 MTP 模式下的描述符 – iPhone 有多种配置,但无论我们选择哪一种,创建 WPD PDO 的接口都将始终包含具有 Class 6 和子类 1 的接口。

         ---------------- iPhone Interface Descriptor -----------------bLength                  : 0x09 (9 bytes)bDescriptorType          : 0x04 (Interface Descriptor)bInterfaceNumber         : 0x00 (Interface 0)bAlternateSetting        : 0x00bNumEndpoints            : 0x03 (3 Endpoints)bInterfaceClass          : 0x06 (Image)bInterfaceSubClass       : 0x01 (Still Imaging device)bInterfaceProtocol       : 0x01iInterface               : 0x0E (String Descriptor 14) Language 0x0409         : "PTP"
---------------- Xiaomi MTP Interface Descriptor -----------------bLength : 0x09 (9 bytes)bDescriptorType : 0x04 (Interface Descriptor)bInterfaceNumber : 0x00 (Interface 0)bAlternateSetting : 0x00bNumEndpoints : 0x03 (3 Endpoints)bInterfaceClass : 0xFF (Vendor Specific)bInterfaceSubClass : 0xFFbInterfaceProtocol : 0x00iInterface : 0x05 (String Descriptor 5) Language 0x0409 : "MTP"
---------------- Xiaomi PTP Interface Descriptor -----------------bLength : 0x09 (9 bytes)bDescriptorType : 0x04 (Interface Descriptor)bInterfaceNumber : 0x00 (Interface 0)bAlternateSetting : 0x00bNumEndpoints : 0x03 (3 Endpoints)bInterfaceClass : 0x06 (Image)bInterfaceSubClass : 0x01 (Still Imaging device)bInterfaceProtocol : 0x01iInterface : 0x00 (No String Descriptor)

尽管这回答了这个大问题,但仍有一些细节,例如为什么iPhone不允许在其中创建或复制任何内容,而另一方面,即使使用PTP的Xioami也允许创建对象,因此作为一个喜欢深入了解事物的人,仅仅瞥一眼界面描述符不足以满足我的好奇心。

由于此描述符将生成 兼容ID ,寻找与此 ID 匹配的 INF,我们找到 .在此 INF 中,我们可以获取 WPD 设备的 UMDF 部分的以下组件:USBClass_06&SubClass_01&Prot_01wpdmtp.inf


WpdMtp.dll:MTP 核心协议组件


WpdMtpUS.dll:MTP 驱动程序的 USB 扫描传输层


WpdMtpDr.dll:Windows 便携式设备媒体传输协议驱动程序


只是为了完成,作为内核方面的一部分,INF 将添加为下过滤器,反射器作为函数驱动程序。WinUSB.sysWUDFRd.sys


从上面提到的三个二进制文件中,主要的WPD MTP驱动程序将在 中运行,因此我们将从那里开始。这是一个 UMDFv1 驱动程序,它将强烈基于 COM 并以 C++ 编写,从好的方面来说,我们有 WpdWudfSampleDriver,这将使我们几乎没有逆转要做 - 令我惊讶的是,该驱动程序尚未更新为使用 UMDFv2,因为 UMDFv1 几乎已被弃用并且几乎没有对新功能的支持, 我想如果没有坏,不要修复它😅.WpdMtpDrWUDFHost

windows中的苹果USB过滤驱动与iPhone-WPD工作原理


如上所示,我们的入口点将是 OnDeviceAdd 例程。在此函数中,将创建对象,这将我们带到 CDevice::OnPrepareHardware 例程,其中 WpdBaseDriver 通过调用 WpdBaseDriver::Initialize 进行初始化。不幸的是,这是示例代码的部分,并且将开始有所不同。示例代码没有要与之通信的真实设备,但在我们的例子中,我们有。这就是进来的地方,充当设备和真实设备之间的粘合剂。MTP 核心库包含表示真实设备的类。在 WpdBaseDriver 初始化期间,将加载 MTP 核心库,并打开与设备的会话,如以下简化代码片段所示。CDeviceWpdMtpDrWpdMtp.dllWpdMtpDrCMtpDevice

// No error handlingHANDLE hEvent{};CMtpDevice * MtpCore{};MTP_RESPONSECODE mtpRes = OK; // 0x2001
CoCreateInstance(&CLSID_WindowsMtp, NULL, CLSCTX_INPROC_SERVER, &IID_IMtp2, (LPVOID *)&MtpCore);//// wpdEvent represents a class that implements IMtpEventCallback, to get notifications from MTP events// MtpCore->Open(pszPortName, wpdEvents, NULL); MtpCore->InitAsyncCancelEventHandle(hEvent);
CWpdDriverBase->m_mtpCore = MtpCore // Let's assume this will be wrapped in a ComPtr
MtpCore->OpenSession( 1, &mtpRes );if( mtpRes == SessionAlreadyOpened || mtpRes == InvalidTransactionId ) { // 0x201E & 0x2004 respectively MtpCore->ResetDevice( &mtpRes ); MtpCore->OpenSession( 1, &mtpRes );}
MtpCore->Close();

加载 MTP 核心模块后,将触发初始化例程以检索 MTP 设备信息数据集。这是发送到设备的初始 MTP 请求之一,并且在其返回时填充 DeviceInfo 结构。值得注意的是,该结构包含关键信息,例如型号、制造商和各种 MTP 版本标识符,如 MTPforUSB-IFv5.1 规范的第 1.1.1 节所述。此类信息在以后设置 WPD 属性时起着至关重要的作用。


MTP 核心发送请求并将响应解析为结构,而 则利用缓存系统存储指向 返回的类的 COM 指针。此方法可防止频繁地向设备重新发出 PTP/MTP 请求,从而优化 I/O 操作。请注意,此缓存机制超出了本文的范围。CDeviceInfoWpdMtpDrWpdMtp

以下堆栈显示了首次调用此函数的时间:

0:008> k # Child-SP          RetAddr               Call Site00 000000b5`6027f3d8 00007ffb`db67dc66     wpdmtp!CMtpDevice::GetDeviceInfo01 000000b5`6027f3e0 00007ffb`db6850fd     wpdmtpdr!CMtpWrapper::GetDeviceInfo+0x10a02 000000b5`6027f450 00007ffb`db65f058     wpdmtpdr!CMtpWrapper::IsDevicePropertySupported+0xf503 000000b5`6027f4f0 00007ffb`db65f3c6     wpdmtpdr!WpdBaseDriver::Initialize+0x5804 000000b5`6027f570 00007ffb`db6494a9     wpdmtpdr!WpdBaseDriver::Initialize+0xbe05 000000b5`6027f5a0 00007ffb`db64b9f6     wpdmtpdr!CDevice::InitializeBaseDriver+0x71d06 000000b5`6027f660 00007ffb`db64acf9     wpdmtpdr!CDevice::_PrepareHardwareThread+0x4e07 000000b5`6027f7b0 00007ffc`1f3626bd     wpdmtpdr!CDevice::PrepareHardwareThread+0x908 000000b5`6027f7e0 00007ffc`2034a9f8     KERNEL32!BaseThreadInitThunk+0x1d09 000000b5`6027f810 00000000`00000000     ntdll!RtlUserThreadStart+0x28


注意:我不会详细介绍WPD协议的工作原理,因为这本身就是一篇文章。但是,主要是有两个 IOCTL(用于只读和读写命令),它们将 WPD 有效负载打包在里面。在 UM 中,WPD 应用程序将生成通常使用 WPD API 的 WPD 命令,该命令将序列化此 WPD 命令并将其打包到 IOCTL 请求中,这将到达驱动程序,驱动程序将反序列化命令并采取相应的操作。有关 WPD 驱动程序如何处理此问题的示例,请参阅:CQueue::P rocessWpdMessage。


设备准备好接收 I/O 操作后,操作系统将尝试检索 WPD 设备属性,此信息位于对象 ID 中(此对象 ID 是预定义的,始终表示设备对象)。此请求将到达 WPD 驱动程序,该驱动程序将使用 .对于这种情况,这是设置值的方式:DEVICECDeviceInfoWPD_DEVICE_PROTOCOL





// No error handlingULONG extId;CString protocol;USHORT extVersion;IMtpDeviceInfo deviceInfo;IPortableDeviceValues portableDeviceValues;

if( property == WPD_DEVICE_PROTOCOL) { deviceInfo->GetVendorExtId( &extId ); deviceInfo->GetVendorExtVersion( &extVersion ); if( extId == MICROSOFT_VENDOR_EXT_ID ) { // MICROSOFT_VENDOR_EXT_ID == 6 protocol.Format(_T("MTP: %.2f"), extVersion / 100.0 ); } else { protocol.Format(_T("PTP: %.2f"), extVersion / 100.0 ); } portableDeviceValues->SetStringValue( &WPD_DEVICE_PROTOCOL, protocol);}

所以现在如果我们看一下iPhone返回的DeviceInfo数据集,我们可以查看并最终回答为什么设置为。如果有人好奇,MS 将其定义为其 WMDRM 协议的一部分。这是MTP响应程序需要在DeviceInfo数据集中设置的值之一,以告诉MTP发起方它支持AAVT,令人惊讶的是,iPhone只添加此必需值,而不是其他值。有关详细信息,请参阅:MTP 供应商扩展标识消息和媒体传输协议 MS 增强规范VendorExtIdVendorExtVersionWPD_DEVICE_PROTOCOLMTP 15.20MICROSOFT_VENDOR_EXT_IDwindows中的苹果USB过滤驱动与iPhone-WPD工作原理

WPD 设备属性中的一个快速详细信息是,有一个名为的属性仅用于表示目的。但既然我们在这里,我认为快速讨论它很有趣。此属性将在函数上检索,该函数将使用 SetupAPI 获取 CompatibleId,并使用大致如下的算法确定设备类型:WPD_DEVICE_TYPECDevicePropContext::GetDeviceType


如果为 ,则使用 从 ID 的“XXX”部分提取设备类型。MS_SUBCOMP_XXXwcstol


如果为 ,请尝试获取 PTP/MPT 属性“感知设备类型 (0xD407)”(如果未找到),请将“设备类型”设置为 WPD_DEVICE_TYPE_GENERIC。MS_COMP_MTP


如果两者都不是,请将“设备类型”设置为WPD_DEVICE_TYPE_MEDIA_TYPE。CLASS_06&SUBCLASS_01&PROT_01URN:MICROSOFT-COM:DEVICE:MTP:1


获取 .如果 VendorExtId 不是 6,请将 DeviceType 设置为 WPD_DEVICE_TYPE_CAMERA。否则,如果未找到,请尝试获取“感知设备类型”,将“设备类型”设置为WPD_DEVICE_TYPE_GENERIC,如果找到,请将“设备类型”设置为设备返回的值。DeviceInfo


对于iPhone,我们将到达步骤4,并且由于VendorExtId等于6并且不存在属性“感知设备类型”,因此DeviceType将设置为WPD_DEVICE_TYPE_GENERIC。

现在我们了解了属性的设置方式,让我们探讨一下为什么 Apple 设备的文件操作如此有限。对于任何熟悉 PTP/MTP 协议的人来说,他们可能已经知道这一点,但无论协议 PTP 或 MTP,设备中的每个存储对象(以 开头表示)都有自己的属性。同样,当设备上的 I/O 操作启动时,OS 使用两个关键操作从存储对象中检索信息:(检索 ) 的列表和(定义存储对象的行为方式)。我们将重点介绍后者,因为它返回一个包含以下三个关键字段的 StorageInfo 数据集(有关详细信息,请参阅 MTPforUSB-IFv5.2 规范的第 2.1.1 节)。WPD_DEVICE_PROTOCOLStorageIDssGetStorageIDs (0x1004)StorageIDsGetStorageInfo (0x1005)


存储类型

文件系统类型

访问能力

当 WPD 驱动程序首次尝试获取设备的存储信息时,请求将通过 MTP 核心模块。此模块将 PTP/MTP 操作请求发送到设备,并将生成的 StorageInfo 数据集返回到驱动程序。

0:008> k # Child-SP          RetAddr               Call Site00 000000b5`6027de48 00007ffb`db68387f     wpdmtp!CMtpDevice::GetStorageInfo01 000000b5`6027de50 00007ffb`db695d05     wpdmtpdr!CMtpWrapper::GetStorageInfo+0x11702 000000b5`6027def0 00007ffb`db6cc52f     wpdmtpdr!CStoragePropContext::CacheStorageUniqueId+0xed03 000000b5`6027df40 00007ffb`db6cb7e9     wpdmtpdr!CHierarchyHandler::QueryStorages+0x1bb04 000000b5`6027dfe0 00007ffb`db6c9c7e     wpdmtpdr!CHierarchyHandler::QueryDeviceChildren+0x6505 000000b5`6027e0c0 00007ffb`db68f589     wpdmtpdr!CHierarchyHandler::GetChildren+0x2ae06 000000b5`6027e140 00007ffb`db672608     wpdmtpdr!CEnumContext::BeginFunctionalObjectsEnumeration+0xa907 000000b5`6027e230 00007ffb`db66f5a7     wpdmtpdr!WpdCapabilities::OnGetFunctionalObjects+0x11808 000000b5`6027e2f0 00007ffb`db65e497     wpdmtpdr!WpdCapabilities::DispatchWpdMessage+0x18f09 000000b5`6027e3e0 00007ffb`db65036d     wpdmtpdr!WpdBaseDriver::DispatchWpdMessage+0x5e70a 000000b5`6027e6a0 00007ffb`db64f82d     wpdmtpdr!CSessionQueue::ProcessWpdMessage+0x4110b 000000b5`6027e720 00007ffc`14858eba     wpdmtpdr!CSessionQueue::OnDeviceIoControl+0x22d

因此,如果我们查看iPhone如何响应此请求,我们将能够根据我们上面提到的三个字段确定存储对象的行为方式。

windows中的苹果USB过滤驱动与iPhone-WPD工作原理

从上图中,我们得到以下信息:- 存储类型 == 固定 RAM,这是移动设备的标准配置。- 文件系统类型 == DCF,DCF 代表相机 FS 的设计规则,你们中的许多人会从著名的根目录中认出这一点。DCF 标准定义了在目录和文件上设置只读属性的选项。- 访问能力==只读,不删除对象,这是棺材上的钉子。这将定义对存储对象的访问限制,操作系统将遵守这些限制。例如,这将影响iPhone内上下文菜单中显示的选项。DCIM


所以在这里我们有它,这就是为什么iPhone上的文件选项如此有限的原因。仅供比较,下图显示了使用 PTP 插入小米设备时的 StorageInfo 数据集

windows中的苹果USB过滤驱动与iPhone-WPD工作原理

事实证明,这就是为什么即使使用 PTP 协议连接,我也能够在小米设备上创建对象的原因。但是,值得注意的是,小米似乎对其MTP响应器有问题。无论在设备上选择了 PTP 还是 MTP,都会返回相同的数据集以响应请求,至少在 Redmi Note 8 型号上是这样。GetStorageInfo

这样,我们已经解决了本节前面提出的问题,从而更清楚地了解了 Apple 设备的行为方式的原因,以及如何为设备配置 WPD 属性。

苹果软件对苹果设备堆栈的影响

在结束这篇文章之前,让我们简要讨论一下在主机上安装 iTunes 时会发生什么,以及它如何启用诸如将文件复制到设备/从设备复制文件等操作。如前所述,由于存储对象中的限制,WPD API 将仅在 iPhone 上提供有限的操作子集。但是,安装 iTunes 时,它会添加一个不同的层,以便更全面地访问设备。

正如我们在AppleLowerFilter中看到的那样,一旦安装了iTunes,这将允许设备选择不同的USB配置描述符。如果没有iTunes,我们仅限于配置1,另一方面,默认情况下安装iTunes后,所选配置将为3。让我们快速浏览一下这两种配置及其接口:


------------------ Configuration Descriptor -------------------bLength : 0x09 (9 bytes)bDescriptorType : 0x02 (Configuration Descriptor)wTotalLength : 0x0027 (39 bytes)bNumInterfaces : 0x01 (1 Interface)bConfigurationValue : 0x01 (Configuration 1)iConfiguration : 0x05 (String Descriptor 5) Language 0x0409 : "PTP"bmAttributes : 0xC0 D7: Reserved, set 1 : 0x01 D6: Self Powered : 0x01 (yes) D5: Remote Wakeup : 0x00 (no) D4..0: Reserved, set 0 : 0x00MaxPower : 0xFA (500 mA)
---------------- Interface Descriptor -----------------bLength : 0x09 (9 bytes)bDescriptorType : 0x04 (Interface Descriptor)bInterfaceNumber : 0x00 (Interface 0)bAlternateSetting : 0x00bNumEndpoints : 0x03 (3 Endpoints)bInterfaceClass : 0x06 (Image)bInterfaceSubClass : 0x01 (Still Imaging device)bInterfaceProtocol : 0x01iInterface : 0x0E (String Descriptor 14) Language 0x0409 : "PTP"
// Endpoint descriptors -> Bulk IN, Bulk OUT & Interrupt IN
------------------ Configuration Descriptor -------------------bLength : 0x09 (9 bytes)bDescriptorType : 0x02 (Configuration Descriptor)wTotalLength : 0x003E (62 bytes)bNumInterfaces : 0x02 (2 Interfaces)bConfigurationValue : 0x03 (Configuration 3)iConfiguration : 0x07 (String Descriptor 7) Language 0x0409 : "PTP + Apple Mobile Device"bmAttributes : 0xC0 D7: Reserved, set 1 : 0x01 D6: Self Powered : 0x01 (yes) D5: Remote Wakeup : 0x00 (no) D4..0: Reserved, set 0 : 0x00MaxPower : 0xFA (500 mA)
---------------- Interface Descriptor -----------------bLength : 0x09 (9 bytes)bDescriptorType : 0x04 (Interface Descriptor)bInterfaceNumber : 0x00 (Interface 0)bAlternateSetting : 0x00bNumEndpoints : 0x03 (3 Endpoints)bInterfaceClass : 0x06 (Image)bInterfaceSubClass : 0x01 (Still Imaging device)bInterfaceProtocol : 0x01iInterface : 0x0E (String Descriptor 14) Language 0x0409 : "PTP"
// Endpoint descriptors -> Bulk IN, Bulk OUT & Interrupt IN
---------------- Interface Descriptor -----------------bLength : 0x09 (9 bytes)bDescriptorType : 0x04 (Interface Descriptor)bInterfaceNumber : 0x01 (Interface 1)bAlternateSetting : 0x00bNumEndpoints : 0x02 (2 Endpoints)bInterfaceClass : 0xFF (Vendor Specific)bInterfaceSubClass : 0xFEbInterfaceProtocol : 0x02iInterface : 0x17 (String Descriptor 23) Language 0x0409 : "Apple USB Multiplexor"
// Endpoint descriptors -> Bulk IN & Bulk OUT


选择配置 3,将使 usbccgp 生成设备 ID(01 提取自 bInterfaceNumber)。这些设备 ID 实际上是在 中定义的,它定义了以下文件的副本:USBVID_xxxx&PID_yyyy&MI_01appleusb.inf

[AppleUsbMux_Install]Include=winusb.infNeeds=WINUSB.NTCopyFiles=AppleUsbFilter_CopyFilesCopyFiles=AppleKmdfFilter_CopyFilesFeatureScore=0x7F
[AppleUsbFilter_CopyFiles]AppleUsbFilter.dll
[AppleKmdfFilter_CopyFiles]AppleKmdfFilter.sys

这两个驱动程序将成为苹果称为“苹果移动设备USB设备”的设备的一部分,该设备使用专有协议而不是MTP或PTP与iPhone通信。Yoy 可以通过查看令人敬畏的 libimobiledevice 的源代码来了解有关此协议的更多信息。一旦驱动程序安装并运行,iTunes本身就会使用标准WPD API调用和自定义Apple特定命令的组合与iPhone进行通信。这允许iTunes提供将文件复制到/从设备复制文件,管理应用程序和备份以及更新设备固件等功能。


下图提供了 iPhone 的整个设备堆栈的简化概述,包括安装 iTunes 和创建 AppleUsbMux 设备的方案。

windows中的苹果USB过滤驱动与iPhone-WPD工作原理

结论

在这篇文章中,我们探讨了Apple的USB下过滤器如何在Windows机器上工作,以及它的作用是提供不同的体验,具体取决于是否安装了Apple软件。我们还深入研究了 Windows 便携设备 (WPD) 和用户模式驱动程序框架 (UMDF) 等主题,以更好地了解 Apple 设备堆栈的内部工作原理。我们介绍了如何初始化和设置 WPD 设备,这有助于我们了解为什么 WPD 设备协议属性与 Apple 设备中的接口描述符定义的类不匹配。我们还研究了如何设置 WPD 设备的存储对象,以及这如何在我们必须在不使用第三方软件的情况下使用 iPhone 进行操作的限制中发挥作用。最后,我们简要讨论了安装iTunes如何在Apple移动设备堆栈中发挥作用,以及这如何使iTunes能够正确管理设备内容。


苹果希望保护某些信息并限制与iPhone存储交互的开箱即用选项是可以理解的,但是如果有一个更加混合的解决方案,用户可以在某些限制内拥有更大的灵活性,那就太好了。虽然iTunes为管理iPhone内容提供了强大的解决方案,但有时安装第三方软件可能不是一种选择。但是,我认识到,随着iTunes作为Microsoft商店应用程序的最近发布,此限制可能会减少。总的来说,虽然我理解苹果限制访问某些信息的方法,但更多的灵活性是受欢迎的。也许Mac是更好地与Apple设备😄集成的解决方案。

windows中的苹果USB过滤驱动与iPhone-WPD工作原理

windows中的苹果USB过滤驱动与iPhone-WPD工作原理



windows中的苹果USB过滤驱动与iPhone-WPD工作原理




原文始发于微信公众号(安全狗的自我修养):windows中的苹果USB过滤驱动与iPhone-WPD工作原理

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年8月13日19:43:08
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   windows中的苹果USB过滤驱动与iPhone-WPD工作原理https://cn-sec.com/archives/1939371.html

发表评论

匿名网友 填写信息