- Khi bật bộ điều khiển xDCI ẩn trên ThinkPad X1 Carbon Gen 6, bản thân laptop có thể mô phỏng bất kỳ thiết bị USB nào như bàn phím hoặc thiết bị lưu trữ
- Manh mối là
/sys/class/usb_role/intel_xhci_usb_sw-role-switch, nhưng chỉ chuyển vai trò xHCI là chưa đủ; một xDCI UDC dựa trên DWC3 riêng phải được lộ ra dưới dạng thiết bị PCIe - Trong ảnh BIOS có thiết lập
xDCI Support, nhưng nó bị ẩn khỏi giao diện Setup mặc định; sau khi bật,lspcixuất hiện xDCI8086:9d30và driverdwc3-pci - Cách thành công là mở khóa trang Advanced BIOS và vá NVRAM; việc cấu hình lại thanh ghi PCH chỉ thay đổi được một phần PMC và thất bại do khóa PSF
- Sau khi bật xDCI,
g_mass_storage, Raw Gadget, bộ tái hiện của syzkaller và backend Facedancer hoạt động mà không cần phần cứng ngoài, nhưng cần cáp USB đã ngắtVBUSvà chuyển vai trò sangdevice
Manh mối về chế độ thiết bị USB tìm thấy trên ThinkPad
- Raw Gadget là module kernel cung cấp API không gian người dùng cho subsystem Linux kernel USB Gadget, có thể cung cấp USB descriptor sai để dùng trong fuzzing và khai thác USB host
- PC thông thường thường không có USB Device Controller, tức UDC, và nó chủ yếu được tích hợp trong các máy tính bo mạch đơn như Raspberry Pi
- Công việc trước đây cần phần cứng ngoài như Raspberry Pi hoặc EC3380-AB dựa trên USB 3380
- Trên ThinkPad X1 Carbon Gen 6, phát hiện
intel_xhci_usb_sw-role-switchdưới/sys/class/usb_role/sys/class/usb_rolelà giao diện để chuyển thành phần USB phần cứng giữa chế độ host và chế độ device- Ban đầu, dù ghi
devicevào file role, cũng không xuất hiện thông báodmesghay mục nào trong/sys/class/udc/
- xHCI là HCD giúp hệ thống x86 hoạt động như USB host, còn xDCI là tên Intel dùng cho giao diện phía USB device
Cấu trúc được xác nhận qua mã kernel và mailing list
- Trong Linux kernel,
intel_xhci_usb_swxuất hiện ở hai vị trídrivers/usb/roles/intel-xhci-usb-role-switch.ctriển khai driver USB Role Switch, thao tác các thanh ghi xHCI khi ghidevicehoặchostdrivers/usb/host/xhci-ext-caps.ctạo thiết bị nền tảng ảointel_xhci_usb_swnếu driver xHCI đặt quirkXHCI_INTEL_USB_ROLE_SW
- PCIe device ID của xHCI trên ThinkPad là
0x9d2f, khớp vớiPCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCItrong kernel - Từ thảo luận trên Linux kernel mailing list, xác nhận rằng xHCI và DWC3 UDC là các thiết bị riêng biệt, và có một mux giữa chúng
- role switch có nhiệm vụ thay đổi mux này
- Nếu bản thân DWC3 UDC không hiện ra dưới dạng thiết bị PCI, thì không có UDC để dùng ở device mode
- DWC3 là IP DesignWare Core SuperSpeed USB 3.0 Controller của Synopsys, được nhiều nhà cung cấp, bao gồm Intel, sử dụng trong hệ thống
- Khi kiểm tra
lspcitrên ThinkPad, ban đầu chỉ thấy xHCI8086:9d2f; không thấy0x9d30, device ID xDCI của Sunrise Point-LP theodwc3-pci.c
Dấu vết xDCI còn lại trong ACPI và BIOS
- Trong ACPI DSDT có
Device (XDCI)và phương thức_STA/sys/bus/acpi/devices/device:33/pathlà\_SB_.PCI0.XDCI/sys/bus/acpi/devices/device:33/statuslà15, nghĩa là thiết bị ở trạng thái enabled and functioning- Nhưng vì
lspcikhông có xDCI, đây là trạng thái chỉ trông bình thường từ góc nhìn ACPI
- Màn hình BIOS Setup mặc định không hiển thị thiết lập nào liên quan đến xDCI hay OTG
- Tải ảnh cập nhật Lenovo BIOS Bootable CD, trích xuất binary BIOS
/mnt/bios/FLASH/N23ET86W/$0AN2300.FL1và kiểm tra bằng UEFITool - Khi tìm chuỗi trong
PE32 image sectioncủa moduleSetup, xuất hiện các mục sauxDCI SupportEnable/Disable xDCI (USB OTG Device).
- Trong BIOS có thiết lập xDCI Support, nhưng nó bị ẩn trong UI mặc định
Bật xDCI qua trang Advanced BIOS
- Thử cách mở trang Advanced BIOS ẩn theo tài liệu của dự án x1c6-hackintosh
- Cách này cần flash lại chip SPI chứa BIOS
- Thay vì dùng kẹp SPI, thay chip SPI bằng socket để thử nghiệm bằng cách tháo lắp chip nhiều lần
- Dùng FTDI FT2232H Mini Module và
flashromđể dump rồi ghi lại nội dung chip SPI
- Bản vá BIOS gồm hai bước
- Dùng
UEFIPatchđể đổi tham chiếu GUID của trang BIOSDate/Timesang trangAdvanced - Dùng bản vá byte riêng để buộc TPM vào
MFG Mode, nhằm tránh Boot Guard phát hiện BIOS đã bị sửa đổi
- Dùng
- Trên BIOS 1.37, nếu chỉ áp dụng bản vá đầu tiên, laptop phát tiếng bíp và không boot; sau khi áp dụng cả bản vá thứ hai thì trang Advanced xuất hiện
- Khi đổi
xDCI SupportthànhEnabledtrongIntel Advanced Menu→PCI-IO Configuration→USB Configuration, xDCI được lộ ra sau khi bootlspcixuất hiện00:14.1 USB controller [8086:9d30]- Kernel tự động load driver
dwc3-pci /sys/class/udc/xuất hiệndwc3.1.auto
Điều kiện về cổng xDCI và cáp
- Để tìm cổng USB ngoài được nối với xDCI, đặt role ở
devicerồi cắm USB flash drive vào từng cổng để kiểm tra- Ở một cổng nhất định, OS không phát hiện flash drive; khi đổi role về
hostthì hoạt động lại - Cổng đó được xác định là cổng nối với xDCI
- Ở một cổng nhất định, OS không phát hiện flash drive; khi đổi role về
- Vì cổng xDCI trên ThinkPad là USB Type-A, cần cáp Type-A to Type-A male-to-male để nối với máy host
- Vì role switching không tắt nguồn
VBUScủa cổng, dùng cáp đã ngắt VBUS đểVBUScủa hai thiết bị không nối trực tiếp với nhau- Ban đầu tự chế cáp male-to-male bằng cách cắt hai cáp USB 2.0 và ngắt
VBUS - Sau đó dùng PortaPow USB Power Blocker cùng cáp USB 2.0 male-to-male
- Ban đầu tự chế cáp male-to-male bằng cách cắt hai cáp USB 2.0 và ngắt
- Khi load gadget driver
g_zero, thiết bị USB thử nghiệm được mô phỏng bình thường trên laptop khác - Theo cập nhật ngày 11/6/2024, DataPro USB 3.0 Super-Speed A/A Debugging Cable cũng ngắt USB 2.0
D-vàD+, khiến kết nối High-Speed cần cho việc thiết lập kết nối SuperSpeed bị thất bại- Cáp LogiLink CU0038 được ngắt
VBUSthủ công hoạt động cho mô phỏng thiết bị SuperSpeed
- Cáp LogiLink CU0038 được ngắt
Thử kích hoạt bằng phần mềm qua thanh ghi PCH
- Để hiểu BIOS bật xDCI như thế nào, kiểm tra
Pch/Library/Private/PeiPchInitLib/PchXdci.ctrong mã nguồn BIOS Kaby Lake - Đường dẫn vô hiệu hóa xDCI của BIOS có cấu trúc vô hiệu hóa xDCI trong PMC và PSF
-
Thay đổi PMC
- Cho rằng có thể bỏ ngắt nguồn xDCI bằng cách xóa bit #24
XDCI Function Disabletại offset0x628của thanh ghiNST_PG_FDIS_1trong PMC - Viết một kernel module tái sử dụng ánh xạ
pmc_core_devicevàpmc->regbasecủa Linux kernel - Ngay sau khi boot, bit #31
ST_FDIS_LKcủaST_PG_FDIS1được đặt nên không thể đổi giá trịNST_PG_FDIS_1 - Sau khi suspend rồi đánh thức laptop, lock bit không được đặt, và xóa được bit
XDCI Function Disable
- Cho rằng có thể bỏ ngắt nguồn xDCI bằng cách xóa bit #24
-
Thay đổi PSF
- BIOS vô hiệu hóa xDCI bằng cách đặt bit
USB Dual Role (OTG) Function Disabletrong PSF2 PCR củaPID_PSF2Port ID0xBB - Địa chỉ PCR được tính từ tổ hợp
PCH_PCR_BASE_ADDRESS 0xFD000000, Port ID và offset - Trong kernel module, ánh xạ PSF2 PCR bằng
ioremap, nhưng giá trị đọc ra là0xffffffffvà không thay đổi được - Kết quả vẫn vậy dù unhide P2SB
RemoveSidebandAccesscủa BIOS táchPID_PSF2khỏi IOSF-SB bằngEPMASK5và khóa bằngMASKLOCK, khiến OS không thể thiết lập lại PSF- Truy cập PCH thành công với một số thiết lập PMC, nhưng vì không cấu hình lại được PSF nên không thể trở thành cách kích hoạt xDCI
- BIOS vô hiệu hóa xDCI bằng cách đặt bit
Kích hoạt bằng vá NVRAM mà không cần обход Boot Guard
- Vì giá trị thiết lập BIOS được lưu trong vùng NVRAM của chip SPI, thử phương pháp chỉ đổi giá trị
xDCI Supportmà không mở trang Advanced ẩn - Dùng IFRExtractor-RS để trích xuất thông tin UEFI IFR của module
Setup - Thiết lập
xDCI Supportđược lưu trong biến UEFIPchSetup- VarStore GUID:
4570B7F1-ADE8-4943-8DC3-406472842384 - VarStoreId:
0x5 - VarOffset:
0x40 - Miền giá trị:
0x0hoặc0x1
- VarStore GUID:
- Kiểm tra
/sys/firmware/efi/efivars/PchSetup-4570b7f1-ade8-4943-8dc3-406472842384trongefivarfscủa Linux- 4 byte đầu của file
efivarfslà header, nên giá trịxDCI Supportthực nằm tại offset0x44của file - Khi xDCI bị tắt, giá trị là
00; sau khi bật trong trang BIOS Advanced, nó đổi thành01
- 4 byte đầu của file
- Khi cố ghi trực tiếp biến này từ không gian người dùng hoặc EFI Shell, gặp lỗi
EFI_WRITE_PROTECTED- Dù gỡ thuộc tính immutable của
efivarfs, vẫn gặp lỗiRead-only file system - Sửa bằng chipsec trong EFI Shell cũng gặp lỗi tương tự
- Dù gỡ thuộc tính immutable của
- Tìm chuỗi byte quanh
PchSetuptrong ảnh BIOS gốc đọc bằng SPI programmer, chỉ vá bitxDCI Supportthành01rồi flash lại thì xDCI được kích hoạt - Cách này vẫn cần reflashing chip SPI, nhưng không cần vá trang Advanced hay обход Boot Guard, và TPM cũng không bị hỏng
- Sau khi vá NVRAM trên BIOS 1.37 rồi cập nhật lên 1.61, giá trị thiết lập BIOS được giữ lại nên không cần áp dụng lại bản vá
Mô phỏng thiết bị USB bằng xDCI
- Tất cả ví dụ đều giả định xDCI đã được bật trong BIOS,
intel_xhci_usb_sw-role-switchđã được chuyển sangdevice, và cổng xDCI được nối với USB host bằng cáp đã ngắtVBUS -
Legacy gadget drivers
- Các legacy gadget drivers của subsystem Linux USB Gadget mô phỏng thiết bị thuộc một USB class nhất định khi module được load
g_mass_storagelộ ảnh hệ thống file ra như thiết bị USB mass storage- Tạo ảnh FAT
disk.img, đưaHi from xDCIvàofile.txt, rồi load bằngsudo modprobe g_mass_storage file=./disk.img stall=0 - Trên USB host, ổ đĩa được tự động mount và nội dung file được xác nhận
-
Raw Gadget
- Chạy Raw Gadget cùng xDCI để thử ví dụ bàn phím USB
- Ban đầu bị treo khi xử lý
SET_CONFIGURATION - Nguyên nhân là
dwc3và một số driver UDC giả định rằng 0-length control request có thể được acknowledge ngay mà không cần hỏi gadget driver - Sau khi áp dụng workaround patch cho Raw Gadget và sửa GadgetFS, mô phỏng bàn phím thành công
- Hành vi liên quan được tổng kết trong bản vá tài liệu commit
Sử dụng syzkaller và Facedancer
- syzkaller có thể dùng Raw Gadget để fuzz bên ngoài USB stack của Linux kernel
- Fuzzing USB mặc định của syzkaller dùng Dummy HCD/UDC, kết nối virtual USB Device và Host controller bên trong kernel
- Để dùng xDCI, đổi mã chỉ định UDC của syzkaller từ
dummy_udcsangdwc3-gadget,dwc3.1.auto - Chạy reproducer của lỗi
WARNING in smsusb_start_streaming/usb_submit_urbmà syzkaller tìm thấy bằngsyz-execprog -enable=usb- Cảnh báo
usb_submit_urbđược tái hiện trên laptop dùng kernel Ubuntu5.15.0-91-genericlàm host - Lỗi này là
WARNINGphát sinh do driversmsusbbỏ sót việc kiểm tra USB endpoint type, và không phải hành vi gây hại
- Cảnh báo
- Facedancer là framework mô phỏng thiết bị USB dựa trên Python
- Facedancer backend dựa trên Raw Gadget vẫn là prototype và phụ thuộc vào bản vá Raw Gadget out-of-tree
- Đặt
BACKEND=rawgadget,RG_UDC_DRIVER=dwc3-gadget,RG_UDC_DEVICE=dwc3.1.autorồi chạy ví dụrubber-ducky.py, kết quả hoạt động bình thường
- USB Proxy dựa trên Raw Gadget cũng chạy được cùng xDCI; dùng xDCI có thể biến laptop thành USB sniffer hoặc công cụ USB Man-in-the-Middle
Khả năng trên thiết bị khác và bằng phần mềm
- Có thể kích hoạt xDCI cả trên các PC khác ngoài ThinkPad X1 Carbon Gen 6
- Trường hợp đơn giản nhất có thể chỉ cần bật xDCI trong thiết lập BIOS là hoạt động
- Cần có hỗ trợ ACPI và role switching, đồng thời cổng xDCI phải được nối ra cổng ngoài
- Các ThinkPad khác cũng có thể bị ẩn và bảo vệ thiết lập BIOS xDCI, nên có thể cần reflashing chip SPI
- Cách NVRAM có thể áp dụng mà không cần обход Boot Guard
- Chip SPI trên một số hệ thống mới có thể được RPMC bảo vệ khỏi reflashing; các chip như vậy có thể có chữ
Rtrong tên, chẳng hạnW25R128FW
- Theo cập nhật, Shiny Quagsire từng kích hoạt xDCI trên XPS 13 và Surface Go 1 bằng cách sửa biến
PchSetupbằnggrub-mod-setup_var- Trên các thiết bị đó, biến
PchSetupkhông được bảo vệ nên có thể dùng cách thuần phần mềm
- Trên các thiết bị đó, biến
- Một cách tiếp cận phần mềm khác có thể là lợi dụng lỗ hổng BIOS để đổi biến NVRAM liên quan đến xDCI, hoặc tấn công BIOS bằng DMA trong lúc boot để thực thi mã tùy ý
- Từ “secret” trong tiêu đề gần với nghĩa chỉ một tính năng không được tài liệu hóa hơn là bị cố ý che giấu
1 bình luận
Các ý kiến trên Hacker News
Tôi luôn thắc mắc vì sao tính năng dùng laptop làm bàn phím và màn hình đa dụng cho máy tính khác lại không phổ biến
Việc mua thêm bàn phím và màn hình để bảo trì máy headless nghe khá lạ, vì laptop vốn đã có thể đảm nhận vai trò đó
Máy tính bảng Minisforum V3 sắp ra mắt cũng có đầu vào video nên có thể dùng như màn hình ngoài, nhưng có vẻ sẽ không chia sẻ được cả bàn phím và chuột
Sẽ thật tuyệt nếu tính năng như vậy trở nên phổ biến hơn
Có thể chuyển chuột và bàn phím sang cổng ngoài để nối bằng cáp với máy khác, và bên hông có hai cổng HDMI, một cổng xuất và một cổng nhập
Công tắc bên trong cho phép chọn nguồn màn hình là chính máy của deck hoặc đầu vào bên ngoài
Về cơ bản, đó là một con chip capture tín hiệu HDMI của máy headless và đưa qua USB để laptop thấy như một webcam giả lập; phần điện tử nhỏ đến mức nằm gọn trong sợi cáp
Còn bàn phím thì tôi chưa tìm được giải pháp hay nào ngoài việc dùng bàn phím không dây tiêu chuẩn, và mua loại có trackpad tích hợp để phòng khi hiếm hoi cần chuột
Nghe nói USB 4 có một chế độ cho phép làm việc này
https://web.archive.org/web/20180610141436/http://anselm.hoffmeister.be/computer/hidclient/index.html.en
https://github.com/benizi/hidclient
Tôi nhớ đến một trường hợp Travis Goodspeed đã làm vài năm trước
Một chiếc smart TV nhận cập nhật firmware từ các tệp trên USB thông thường; TV đọc tệp từ đầu đến cuối để kiểm tra chữ ký số, rồi đọc lại để cập nhật
Nếu là một thiết bị giả làm bộ lưu trữ USB, nó có thể gửi tệp firmware của nhà sản xuất ở lần đọc đầu tiên, rồi gửi firmware không chính thức ở lần thứ hai
https://en.m.wikipedia.org/wiki/Time-of-check_to_time-of-use
Thực sự thú vị. Tôi đã tìm hiểu các lựa chọn khả thi tương tự
Tôi có một máy chủ NAS mạnh mà cứ tìm mãi lý do để dùng, và cũng đã kéo sẵn kết nối 40G và 10G khắp nhà
PS5 và XBox đang dùng ổ cứng USB làm dung lượng lưu trữ bổ sung
Khi tìm hiểu xem có thể đưa dung lượng NAS cho PS5 và XBox thấy không thì hóa ra là có. Chỉ cần mount một share trên NAS bằng iSCSI hoặc NFS, rồi dùng mô-đun g_mass_storage để giả lập thiết bị lưu trữ USB và phơi bày vùng lưu trữ đó cho USB host
Nút thắt lớn hiện tại, ngoài thời gian và chi phí, là băng thông mà hệ thống như vậy có thể cung cấp. Mức nâng cấp không lớn lắm
Raspberry Pi nổi tiếng là hỗ trợ USB-OTG nhưng vẫn dừng ở tốc độ USB 2.0, và hầu hết các SBC cùng phân khúc mà tôi tìm được cũng vậy. Ngoại lệ là RockPi4; RockPi có cổng Ethernet gigabit, nên nếu dùng hết băng thông Ethernet thì có thể cung cấp tốc độ HDD ổn định cho cả PS5 lẫn Xbox
Nếu tạo được giải pháp vượt quá 1GbE bằng cách cắm card mạng PCIe tùy chỉnh hoặc card Express, thì có thể bão hòa đúng nghĩa giao diện USB 3.0, nghe khá thú vị
Vẫn cần một client để giao tiếp với server, nhưng có vẻ hoạt động khá tốt
Tôi đang nghĩ đến cấu hình đặt một “USB client mỏng” trên bàn, cắm thiết bị USB vào đó, rồi gắn hoặc chuyển nó sang host vật lý hay host VM mong muốn trong phòng lab
Tôi đoán là NAS → SBC → PS5, hay là nối trực tiếp NAS vào PS5 bằng cáp USB?
Cũng tò mò việc phát nội dung trên PS5 sẽ ra sao. Tôi biết NVMe nội bộ phải đạt một tốc độ nhất định, vậy yêu cầu đó không áp dụng cho ổ ngoài à?
Thực tế NanoPi R6S có hai cổng Ethernet 2.5G bên cạnh một cổng 1 gigabit
Cảm ơn vì bài viết rất chi tiết. Chất lượng tốt
Việc điều này khả thi khiến tôi hy vọng rằng có thể tạo một cấu hình kiểu Synergy / Mouse Without Borders không cần mạng chỉ bằng một sợi cáp USB đã chỉnh sửa
Đây là hướng rất tốt cho những người phải điều khiển nhiều máy tính cùng lúc
Dù vậy, cách bạn đề xuất nghe vẫn thú vị
Gần đây tôi có tìm hiểu một thứ tương tự: tôi muốn nối hai máy USB-C với nhau bằng một sợi cáp USB-C để giao tiếp 10Gbps
Tiếc là phần lớn bo mạch Ryzen vẫn chưa có Thunderbolt, còn nếu là Thunderbolt thì việc này được hỗ trợ native khá dễ dàng
Các bộ điều khiển USB “dual-role” cũng khá hiếm trước USB 3.2/4.0, và như bài viết này đề cập, ngay cả khi có thể thì nhiều trường hợp vẫn không được hỗ trợ
Việc nối mạng hai máy bằng cáp USB-C mà không có Thunderbolt lại khó đến vậy nghe thật sự rất kỳ lạ
Phần bit khóa được gỡ sau khi suspend cũng hay. Những vấn đề kiểu này rất phổ biến. Ví dụ đây cũng là cách rất thường gặp khi đưa thiết bị SATA thoát khỏi trạng thái ngăn secure erase
Độ sâu của bài thật ấn tượng
Nếu có thể dùng PC như một thiết bị USB, rất nhiều khả năng thú vị sẽ mở ra
Hơi đáng tiếc là tùy chọn xDCI cần thiết có trong phần cứng của thiết bị này nhưng không được phơi ra, và muốn truy cập phải hack firmware
Phần cứng thì làm được, nhưng nhà sản xuất đơn giản là tắt nó đi và khóa chức năng điều khiển
Tôi tò mò liệu Lenovo có dùng đường này để debug một ThinkPad bằng một ThinkPad khác không
https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/secure-coding/intel-debug-technology.html
Cập nhật: có lẽ đúng vậy
https://www.youtube.com/watch?v=ExUvQa_jB7c
Đây là video debug Intel Firmware bằng DCI và USB 3.0
Phần “Nhưng xử lý Raspberry Pi thì phiền phức: nối dây, boot bo mạch, truy cập shell, v.v.” có lẽ chỉ cần thiết lập USB OTG là được
Có thể để nó nhận nguồn từ thiết bị được cắm vào, bật shell rồi xử lý bằng script
Khi đó có thể cấu hình mount hoặc chạy lệnh qua SSH, và có lẽ còn mount được thiết bị
Dù vậy, tôi vẫn khuyến khích nỗ lực hiểu thiết bị của mình và đọc kernel. Đó là việc tôi luôn muốn làm tốt hơn, kiểu như thiết bị của chúng ta thì chúng ta tự sửa
Tôi đã tự thử rồi
Nó gợi nhớ mạnh đến văn hóa hacker thời Internet sơ khai, đến mức khơi dậy cảm giác hoài niệm. Một bài viết thật sự xuất sắc
Khi ESR nói về việc trở thành hacker, hay hacker theo nghĩa của Hacker News, người mà ông nói đến chính là kiểu người như thế này
Sự kết hợp giữa tò mò, bền bỉ và năng lực kỹ thuật là cực kỳ hiếm và rất ấn tượng
Tôi có một hệ thống dựa trên Celeron N3350/Pentium N4200/Atom E3900, trong BIOS có phơi ra công tắc xDCI
Khi bật lên thì xuất hiện thêm vài tùy chọn khác, và khi boot vào Linux thì thấy thiết bị PCI
USB controller: Intel Corporation Device 5aaa (rev 0b)Nhưng node thiết bị UDC thì không xuất hiện. Có lẽ tôi nên dựa vào gợi ý trong bài gốc để đào sâu thêm