- Al activar el controlador xDCI oculto de una ThinkPad X1 Carbon 6th Gen, la propia laptop pudo emular dispositivos USB arbitrarios, como un teclado o una unidad de almacenamiento
- La pista fue
/sys/class/usb_role/intel_xhci_usb_sw-role-switch, pero cambiar solo el rol de xHCI no alcanzaba: también tenía que exponerse como dispositivo PCIe un UDC xDCI basado en DWC3 independiente - En la imagen del BIOS había una opción
xDCI Support, pero estaba oculta en la interfaz de configuración predeterminada; tras activarla, aparecieron enlspciel xDCI8086:9d30y el driverdwc3-pci - El método que funcionó fue desbloquear la página Advanced del BIOS y parchar la NVRAM; reconfigurar los registros del PCH solo logró algunos cambios en el PMC y falló por el bloqueo del PSF
- Después de activar xDCI,
g_mass_storage, Raw Gadget, reproductores de syzkaller y un backend de Facedancer funcionaron sin hardware externo, aunque hacen falta un cable USB conVBUSdesconectado y cambiar el rol adevice
La pista del modo de dispositivo USB encontrada en una ThinkPad
- Raw Gadget es un módulo del kernel que ofrece una API de espacio de usuario para el subsistema USB Gadget del kernel Linux, y puede usarse para fuzzing y exploits contra hosts USB al proporcionar descriptores USB malformados
- Las PC comunes normalmente no tienen USB Device Controller, es decir, UDC, que suele venir integrado sobre todo en computadoras de placa única como la Raspberry Pi
- En trabajos anteriores hacía falta hardware externo, como una Raspberry Pi o una EC3380-AB basada en USB 3380
- En una ThinkPad X1 Carbon 6th Gen se encontró
intel_xhci_usb_sw-role-switchbajo/sys/class/usb_role/sys/class/usb_rolees una interfaz para cambiar componentes USB de hardware entre modo host y modo device- Al principio, aunque se escribiera
deviceen el archivo role, no aparecían mensajes endmesgni entradas en/sys/class/udc/
- xHCI es el HCD que permite que un sistema x86 funcione como host USB, y xDCI es el nombre que usa Intel para la interfaz del lado de dispositivo USB
Estructura confirmada con el código del kernel y las listas de correo
- En el kernel Linux,
intel_xhci_usb_swaparece en dos ubicacionesdrivers/usb/roles/intel-xhci-usb-role-switch.cimplementa el driver USB Role Switch que manipula registros xHCI cuando se escribedeviceohostdrivers/usb/host/xhci-ext-caps.ccrea el dispositivo de plataforma virtualintel_xhci_usb_swsi el driver xHCI configuró el quirkXHCI_INTEL_USB_ROLE_SW
- El device ID PCIe del xHCI de la ThinkPad era
0x9d2f, coincidente conPCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCIdel kernel - En discusiones de la lista de correo del kernel Linux se confirmó que xHCI y el UDC DWC3 son dispositivos separados, y que hay un mux entre ambos
- El role switch se encarga de cambiar ese mux
- Si el propio UDC DWC3 no aparece como dispositivo PCI, no hay ningún UDC disponible para usar en modo device
- DWC3 es la IP DesignWare Core SuperSpeed USB 3.0 Controller de Synopsys, usada en sistemas de varios proveedores, incluido Intel
- Al revisar
lspcien la ThinkPad, al principio solo se veía el xHCI8086:9d2f, y no aparecía0x9d30, el device ID de xDCI en Sunrise Point-LP segúndwc3-pci.c
Rastros de xDCI que quedaban en ACPI y en el BIOS
- En el DSDT de ACPI existían
Device (XDCI)y el método_STA/sys/bus/acpi/devices/device:33/pathera\_SB_.PCI0.XDCI/sys/bus/acpi/devices/device:33/statusera15, lo que significa que el dispositivo estaba en estado enabled and functioning- Pero como xDCI no aparecía en
lspci, solo parecía estar correcto desde el punto de vista de ACPI
- En la pantalla predeterminada de configuración del BIOS no se veía ninguna opción relacionada con xDCI u OTG
- Se descargó la imagen de actualización Lenovo BIOS Bootable CD, se extrajo el binario del BIOS
/mnt/bios/FLASH/N23ET86W/$0AN2300.FL1y se inspeccionó con UEFITool - Al buscar cadenas en el
PE32 image sectiondel móduloSetup, aparecieron estos elementosxDCI SupportEnable/Disable xDCI (USB OTG Device).
- Dentro del BIOS existe una opción xDCI Support, pero está oculta en la UI predeterminada
Activar xDCI desde la página Advanced del BIOS
- Siguiendo la documentación del proyecto x1c6-hackintosh, se probó un método para abrir la página Advanced del BIOS oculta
- Este método requería volver a flashear el chip SPI donde está almacenado el BIOS
- En vez de usar un clip SPI, se reemplazó el chip SPI por un zócalo para poder retirar e insertar varias veces el chip durante las pruebas
- Se usaron un FTDI FT2232H Mini Module y
flashrompara volcar y reescribir el contenido del chip SPI
- El parche del BIOS consta de dos pasos
- Con
UEFIPatch, se cambia la referencia GUID de la páginaDate/Timedel BIOS hacia la páginaAdvanced - Con un parche de bytes adicional, se fuerza el TPM a
MFG Modepara evitar que Boot Guard detecte la modificación del BIOS
- Con
- En BIOS 1.37, aplicar solo el primer parche hacía que la laptop emitiera pitidos y no arrancara; después de aplicar también el segundo parche, apareció la página Advanced
- Al cambiar
xDCI SupportaEnabledenIntel Advanced Menu→PCI-IO Configuration→USB Configuration, xDCI quedó expuesto tras el arranque- En
lspciapareció00:14.1 USB controller [8086:9d30] - El kernel cargó automáticamente el driver
dwc3-pci - En
/sys/class/udc/apareciódwc3.1.auto
- En
Puerto xDCI y condiciones del cable
- Para encontrar el puerto USB externo conectado a xDCI, se dejó el rol en
devicey se conectó una unidad flash USB en cada puerto- En un puerto específico, el SO no detectaba la unidad flash; al volver el rol a
host, funcionaba de nuevo - Ese puerto fue identificado como el puerto conectado a xDCI
- En un puerto específico, el SO no detectaba la unidad flash; al volver el rol a
- Como el puerto xDCI de la ThinkPad era USB Type-A, para conectarla a una computadora host hacía falta un cable Type-A a Type-A macho-macho
- Como el role switching no apagaba la alimentación
VBUSdel puerto, se usó un cable con VBUS desconectado para evitar que elVBUSde ambos dispositivos quedara conectado directamente- Al principio se fabricó manualmente un cable macho-macho cortando dos cables USB 2.0 y desconectando
VBUS - Más tarde se usaron un PortaPow USB Power Blocker y un cable USB 2.0 macho-macho
- Al principio se fabricó manualmente un cable macho-macho cortando dos cables USB 2.0 y desconectando
- Al cargar el gadget driver
g_zero, el dispositivo USB de prueba se emuló correctamente en otra laptop - Según una actualización del 11 de junio de 2024, el DataPro USB 3.0 Super-Speed A/A Debugging Cable también tiene desconectados
D-yD+de USB 2.0, por lo que falla la conexión High-Speed necesaria para establecer una conexión SuperSpeed- Un cable LogiLink CU0038 con
VBUSdesconectado manualmente funciona para emular dispositivos SuperSpeed
- Un cable LogiLink CU0038 con
Intento de activación por software con registros del PCH
- Para entender cómo el BIOS activa xDCI, se revisó
Pch/Library/Private/PeiPchInitLib/PchXdci.cdel código fuente de BIOS para Kaby Lake - La ruta de desactivación de xDCI en el BIOS lo deshabilitaba desde PMC y PSF
-
Cambios en PMC
- Se consideró que borrar el bit #24
XDCI Function Disabledel registroNST_PG_FDIS_1del PMC, offset0x628, podría quitar el corte de energía de xDCI - Se escribió un módulo del kernel que reutilizaba el mapeo de
pmc_core_deviceypmc->regbasedel kernel Linux - Justo después del arranque, el bit #31
ST_FDIS_LKdeST_PG_FDIS1estaba configurado, por lo que no era posible cambiar el valor deNST_PG_FDIS_1 - Después de suspender y reactivar la laptop, el bit de bloqueo no estaba configurado, y se logró borrar el bit
XDCI Function Disable
- Se consideró que borrar el bit #24
-
Cambios en PSF
- El BIOS deshabilita xDCI configurando el bit
USB Dual Role (OTG) Function Disableen el PCR PSF2 del Port ID0xBBdePID_PSF2 - La dirección PCR se calcula combinando
PCH_PCR_BASE_ADDRESS 0xFD000000, el Port ID y el offset - En el módulo del kernel, se mapeó el PCR PSF2 con
ioremap, pero el valor leído fue0xffffffffy no cambió - Aunque se hiciera unhide de P2SB, el resultado era el mismo
RemoveSidebandAccessdel BIOS separaPID_PSF2de IOSF-SB usandoEPMASK5y lo bloquea conMASKLOCK, por lo que el SO no puede volver a configurar PSF- El acceso al PCH logró modificar algunos ajustes del PMC, pero como falló la reconfiguración del PSF, no sirvió como método para activar xDCI
- El BIOS deshabilita xDCI configurando el bit
Activación con parche de NVRAM sin evadir Boot Guard
- Como los valores de configuración del BIOS se almacenan en el área NVRAM del chip SPI, se probó cambiar solo el valor de
xDCI Supportsin abrir la página Advanced oculta - Se extrajo la información UEFI IFR del módulo
Setupcon IFRExtractor-RS - La opción
xDCI Supportestaba almacenada dentro de la variable UEFIPchSetup- VarStore GUID:
4570B7F1-ADE8-4943-8DC3-406472842384 - VarStoreId:
0x5 - VarOffset:
0x40 - Rango de valores:
0x0o0x1
- VarStore GUID:
- En
efivarfsde Linux se revisó/sys/firmware/efi/efivars/PchSetup-4570b7f1-ade8-4943-8dc3-406472842384- Como los primeros 4 bytes de un archivo
efivarfsson el encabezado, el valor real dexDCI Supportestá en el offset0x44del archivo - Con xDCI desactivado, el valor era
00; después de activarlo desde la página Advanced del BIOS, cambiaba a01
- Como los primeros 4 bytes de un archivo
- Al intentar escribir directamente esa variable desde espacio de usuario o desde EFI Shell, se produjo un error
EFI_WRITE_PROTECTED- Aunque se eliminara el atributo immutable de
efivarfs, aparecía el errorRead-only file system - Al cambiarlo desde EFI Shell con chipsec, se producía el mismo error
- Aunque se eliminara el atributo immutable de
- En la imagen original del BIOS leída con un programador SPI, se buscó la secuencia de bytes alrededor de
PchSetup, se parchó solo el bitxDCI Supporta01y se volvió a flashear; con eso xDCI quedó activado - Este método todavía requiere reflashear el chip SPI, pero no necesita el parche de la página Advanced ni evadir Boot Guard, y tampoco rompe el TPM
- Tras parchar la NVRAM en BIOS 1.37 y actualizar a 1.61, el valor de configuración del BIOS se mantuvo, por lo que no hizo falta volver a aplicar el parche
Emular dispositivos USB con xDCI
- Todos los ejemplos asumen que xDCI está activado en el BIOS, que
intel_xhci_usb_sw-role-switchfue cambiado adevice, y que el puerto xDCI está conectado al USB host con un cable que tieneVBUSdesconectado -
Legacy gadget drivers
- Los legacy gadget drivers del subsistema Linux USB Gadget emulan un dispositivo de una clase USB específica al cargar el módulo
g_mass_storageexpone una imagen de sistema de archivos como dispositivo USB mass storage- Después de crear la imagen FAT
disk.imgy ponerHi from xDCIenfile.txt, se carga consudo modprobe g_mass_storage file=./disk.img stall=0 - En el USB host, la unidad se monta automáticamente y se verifica el contenido del archivo
-
Raw Gadget
- Se ejecutó Raw Gadget con xDCI para probar un ejemplo de teclado USB
- Al principio se quedaba detenido durante el manejo de
SET_CONFIGURATION - La causa era que
dwc3y algunos drivers UDC asumían que podían hacer acknowledge de inmediato a un control request de 0 bytes sin consultar al gadget driver - Tras aplicar a Raw Gadget el parche workaround y también corregir GadgetFS, la emulación de teclado funcionó correctamente
- El comportamiento relacionado se documentó en este commit
Uso con syzkaller y Facedancer
- syzkaller puede usar Raw Gadget para hacer fuzzing externo del stack USB del kernel Linux
- El fuzzing USB predeterminado de syzkaller usa Dummy HCD/UDC, que conecta internamente en el kernel un dispositivo USB virtual y un controlador host
- Para usar xDCI, se cambió el código de syzkaller que especifica el UDC de
dummy_udcadwc3-gadget,dwc3.1.auto - Se ejecutó con
syz-execprog -enable=usbel reproducer del bugWARNING in smsusb_start_streaming/usb_submit_urbencontrado por syzkaller- En una laptop con el kernel Ubuntu
5.15.0-91-genericcomo host, se reprodujo la advertencia enusb_submit_urb - Ese bug era un
WARNINGcausado porque el driversmsusbomitía validar el tipo de endpoint USB, y no era un comportamiento dañino
- En una laptop con el kernel Ubuntu
- Facedancer es un framework de emulación de dispositivos USB basado en Python
- El backend de Facedancer basado en Raw Gadget todavía es un prototipo y depende de parches de Raw Gadget out-of-tree
- Al configurar
BACKEND=rawgadget,RG_UDC_DRIVER=dwc3-gadget,RG_UDC_DEVICE=dwc3.1.autoy ejecutar el ejemplorubber-ducky.py, funcionó correctamente
- El USB Proxy basado en Raw Gadget también se ejecutó con xDCI, y usar xDCI permite usar la laptop como sniffer USB o herramienta de USB Man-in-the-Middle
Posibilidades en otros equipos y por software
- Puede ser posible activar xDCI también en otras PC además de la ThinkPad X1 Carbon 6th Gen
- En el caso más simple, podría funcionar con solo activar xDCI en la configuración del BIOS
- Debe haber soporte de ACPI y role switching, y el puerto xDCI tiene que estar cableado a un puerto externo
- Es posible que otras ThinkPad también tengan la opción xDCI del BIOS oculta y protegida, por lo que podría hacer falta reflashear el chip SPI
- El método por NVRAM puede aplicarse sin evadir Boot Guard
- En algunos sistemas más nuevos, el reflashing del chip SPI puede estar protegido con RPMC, y estos chips pueden incluir una
Ren el nombre, comoW25R128FW
- Según una actualización, Shiny Quagsire ya había activado xDCI en una XPS 13 y una Surface Go 1 modificando la variable
PchSetupcongrub-mod-setup_var- En esos dispositivos, la variable
PchSetupno estaba protegida, por lo que era posible un método puramente por software
- En esos dispositivos, la variable
- Otro enfoque por software podría ser usar una vulnerabilidad del BIOS para cambiar las variables NVRAM relacionadas con xDCI, o atacar el BIOS durante el arranque mediante DMA para ejecutar código arbitrario
- La palabra “secret” del título se refiere más a una función no documentada que a un ocultamiento intencional
1 comentarios
Comentarios de Hacker News
Siempre me he preguntado por qué no es más común usar una laptop como teclado y monitor genéricos para otra computadora
Tener que comprar un teclado y un monitor nuevos para dar mantenimiento a una máquina headless se siente raro, porque una laptop ya podría cumplir ese papel
La próxima tablet Minisforum V3 también tendrá entrada de video, así que podrá usarse como monitor externo, aunque no parece que vaya a compartir también el teclado y el mouse
Ojalá este tipo de función se vuelva más común
Puede redirigir el mouse y el teclado a puertos externos para conectarlos por cable a otra máquina, y en un costado tiene dos puertos HDMI, uno de salida y otro de entrada
Con un switch interno puede elegir si el monitor usa como fuente la propia máquina del deck o una entrada externa
Básicamente es un chip que captura la señal HDMI de la máquina headless y la expone a la laptop por USB como si fuera una webcam emulada, y es lo bastante pequeño como para que los componentes electrónicos quepan dentro del cable
Para el teclado, fuera de usar un teclado inalámbrico estándar y comprar uno con trackpad integrado para cuando rara vez hace falta mouse, no he encontrado una buena solución
Según entiendo, USB 4 tiene un modo que permite algo así
https://web.archive.org/web/20180610141436/http://anselm.hoffmeister.be/computer/hidclient/index.html.en
https://github.com/benizi/hidclient
Esto me recordó algo que hizo Travis Goodspeed hace algunos años
Una smart TV aceptaba actualizaciones de firmware desde archivos en una memoria USB común, y la TV leía el archivo completo una vez para verificar la firma digital y luego lo volvía a leer para hacer la actualización
Un dispositivo que fingiera ser almacenamiento USB podría entregar el firmware del fabricante en la primera lectura y firmware no oficial en la segunda
https://en.m.wikipedia.org/wiki/Time-of-check_to_time-of-use
Muy interesante. He estado investigando opciones parecidas que podrían hacerse realidad
Tengo un servidor NAS potente para el que sigo buscando una excusa de uso, y además tengo conexiones de 40G y 10G por toda la casa
La PS5 y la XBox usan discos duros USB como almacenamiento adicional
Revisando si era posible exponer almacenamiento del NAS a la PS5 y a la XBox, vi que sí. Basta con montar el recurso compartido del NAS por iSCSI o NFS y luego usar el módulo g_mass_storage para emular un dispositivo de almacenamiento USB y exponer ese almacenamiento al host USB
El principal obstáculo actual, además del tiempo y el costo, es el ancho de banda que ofrecería un sistema así. La mejora no sería tan grande
La Raspberry Pi es conocida por soportar USB-OTG, pero se queda en velocidades de USB 2.0, y la mayoría de las otras SBC de la misma clase que revisé también. La excepción fue la RockPi4, y la RockPi tiene un puerto Ethernet gigabit, así que si saturas Ethernet podría dar velocidades estables de HDD tanto a la PS5 como a la Xbox
Si existiera una solución con una tarjeta de red PCIe personalizada o una express card que permitiera superar 1GbE, sería bastante interesante, porque sí podría saturar de verdad una interfaz USB 3.0
Sí hace falta un cliente que se comunique con el servidor, pero parece funcionar bastante bien
Estoy pensando en poner un “cliente USB delgado” sobre el escritorio, conectar ahí los dispositivos USB y luego adjuntarlos o cambiarlos al host físico o al host de VM que quiera dentro del laboratorio
Supongo que sería NAS → SBC → PS5, pero ¿o estarías conectando el NAS directamente a la PS5 con un cable USB?
También me pregunto cómo funcionaría la reproducción de contenido en la PS5. Según entiendo, el NVMe interno tiene que cumplir cierta velocidad; ¿eso no aplica a las unidades externas?
De hecho, la NanoPi R6S tiene dos puertos Ethernet de 2.5G, además de un puerto de 1 gigabit
Gracias por el artículo tan detallado. Tiene muy buena calidad
El simple hecho de saber que esto fue posible me da esperanzas de que quizá se pueda lograr una configuración tipo Synergy / Mouse Without Borders sin red, usando solo un cable USB modificado
Para quien necesita controlar varias computadoras al mismo tiempo, es una dirección muy prometedora
Aun así, la idea que propones suena interesante
Hace poco estuve investigando algo parecido: quería conectar dos máquinas con USB-C usando un solo cable USB-C para tener comunicación de 10 Gbps
Por desgracia, la mayoría de las placas Ryzen todavía no tienen Thunderbolt, y con Thunderbolt esto se soporta de forma nativa con bastante facilidad
Los controladores USB de “doble rol” también eran bastante raros antes de USB 3.2/4.0 y, como se comenta en este artículo, incluso cuando es posible muchas veces no está soportado
Se siente completamente extraño que sea tan difícil conectar en red dos máquinas con un cable USB-C sin Thunderbolt
También me gustó la parte donde, después de una suspensión temporal, se libera el bit de bloqueo. Este tipo de problema es realmente común. Por ejemplo, también es una forma muy común de sacar a un dispositivo SATA de un estado que bloquea el borrado seguro
El nivel de profundidad es impresionante
Poder usar una PC como dispositivo USB abre muchas posibilidades interesantes
Es un poco una lástima que la opción xDCI necesaria exista en el hardware de este equipo pero no esté expuesta, y que para acceder a ella haga falta hackear el firmware
El hardware puede hacerlo, pero el fabricante simplemente lo desactivó y bloqueó los controles
Me pregunto si Lenovo usa esto como una vía para depurar un ThinkPad con otro ThinkPad
https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/secure-coding/intel-debug-technology.html
Actualización: parece que sí
https://www.youtube.com/watch?v=ExUvQa_jB7c
Es un video sobre depuración de Intel Firmware con DCI y USB 3.0
La parte de “pero trabajar con una Raspberry Pi es engorroso: conectar cables, arrancar la placa, entrar al shell, etc.” probablemente se habría podido resolver configurando USB OTG
Parece que se podría haber hecho para que tomara energía del dispositivo conectado, abrir el shell y manejarlo con un script
Entonces se podrían configurar montajes o ejecutar comandos por SSH, y probablemente hasta montar el dispositivo
Aun así, siempre vale la pena intentar entender tu propio dispositivo y leer el kernel. Es algo en lo que uno quiere seguir mejorando, y da esa sensación de que nuestro equipo lo arreglamos nosotros
Lo probé personalmente
Me recuerda muchísimo a la cultura hacker de los primeros días de internet, al punto de provocar nostalgia. De verdad es un texto excelente
Cuando ESR hablaba de convertirse en hacker, del hacker en el sentido de Hacker News, se refería precisamente a este tipo de persona
Esa combinación de curiosidad, perseverancia y capacidad técnica es extremadamente rara y muy impresionante
Tengo un sistema basado en Celeron N3350/Pentium N4200/Atom E3900, y en el BIOS aparece expuesto el interruptor xDCI
Al activarlo aparecen también varias opciones más, y al arrancar con Linux se ve el dispositivo PCI
USB controller: Intel Corporation Device 5aaa (rev 0b)Pero no aparece el nodo de dispositivo UDC. Creo que voy a tener que investigar un poco más tomando pistas del artículo original