reverse engineering: writing a linux driver for an unknown device
DESCRIPTION
Reverse engineering an USB Video Grabber device protocol and creating a Linux kernel driver.TRANSCRIPT
Ľubomír Rintel <[email protected]>OSSConf 2013, Žilina
BTC: 1A28Etzh7zsK2Bq36qvPKJi18s53M9B2FU
Reverse Engineering:Writing a Linux driver for an
unknown device
Our device
● Unknown to Linux● No documentation● No Google hits for chip● Desperate users in
Ubuntu forums
The Plan
● Make it work in Windows● Capture what happens● Find image data● Mimic the behavior in userspace● Transform into a kernel module
USB
USB Architecture
● Network of Host, Hubs and Devices
USB Addresses
● Bus & Device number
Host
Device 1:1Hub
Device 2:1Hub
Device 3:1Mouse
Device 2:2Flash Drive
USB Addresses
$ lsusbBus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hubBus 002 Device 001: ID 1337:abcd Trololol USB 1.1 HubBus 002 Device 002: ID 1337:0123 Trololol Flash DriveBus 003 Device 001: ID dead:b4b3 Random Mouse$ lsusb -v...
USB Device
● Self-describing● Endpoints
● CONTROL● INTERRUPT● BULK● ISOCHRONOUS
● Endpoints grouped into Interfaces● Interfaces grouped into Configurations
Our device
Device
Alternate setting 0Endpoints:
Alternate setting 1Endpoints:
0x81 Isochronous IN
0x82 Bulk IN
0x83 Bulk IN
0x84 Interrupt IN
0x81 Isochronous IN
0x82 Bulk IN
0x83 Bulk IN
0x84 Interrupt IN
The Plan
● Make it work in Windows● Capture what happens● Find image data● Mimic the behavior in userspace● Transform into a kernel module
Windows & VirtualBox
Wireshark & usbmon
What did we see
● Number of CONTROL requests● ISOCHRONOUS packets once capture starts
RGB
R R R R R R R R
G G G G G G G G
B B B B B B B B
YUV2Y Y Y Y U1 U1 U1 U1
Y Y Y Y V1 V1 V1 V1
Y Y Y Y U2 U2 U2 U2
Y Y Y Y V2 V2 V2 V2
LibUSB
● We could replay the traffic● In userspace – no kernel hacking needed● C, Python & Perl bindings● Now we need to find start & end of the picture
Test image
0xaaaaaaaa0xff00ff00
0x00ff00ff
0x80808080
0x00000000
Frame format
88 01 00 00
88 01 02 cf
88 02 80 00
88 02 82 cf
88 03 00 00
xx xx xx xx • 240 00 00 00 00 • 15
88 01 00 01...
...
● Frame number● Even/odd● Chunk number 0 – 0x2cf = 719
740 x 480 YUV2 Interlaced (NTSC)
...
To kernel!
● Booooring!● A module● USB framework
● Linux Device Drivers: http://lwn.net/Kernel/LDD3/
● Video4Linux2● LWN Series: http://lwn.net/Articles/203924/
● Videobuf2● LWN Article: http://lwn.net/Articles/447435/
Architecture
Video4Linux2
Videobuf2
Our
cod
eUSB
Use
rspa
ce
Har
dwar
e
Video4Linux2
● Provide a device with known API● open(), close()● read(), write()● ioctl()● mmap()
● Negotiate format with userspace
Videobuf2
● Manages buffers of frames● Connects to Video4Linux2
● read(), write(), mmap()● some ioctl()s
– Start/stop capture– Exchange buffers with userspace
USB framework
● Setup the device● Allocate buffers for exchange of data with
device● Handle start/stop● Isochronous callbacks
● Copy data from USB buffers to Videobuf2 buffers
Architecture
Video4Linux2
Videobuf2
Our
cod
eUSB
Use
rspa
ce
Har
dwar
e
All done!
Questions?
Found this useful? My Bitcoin address is:1A28Etzh7zsK2Bq36qvPKJi18s53M9B2FU