reverse engineering: writing a linux driver for an unknown device

28
Ľubomír Rintel <[email protected]> OSSConf 2013, Žilina BTC: 1A28Etzh7zsK2Bq36qvPKJi18s53M9B2FU Reverse Engineering: Writing a Linux driver for an unknown device

Upload: lubomir-rintel

Post on 26-Dec-2014

5.350 views

Category:

Technology


4 download

DESCRIPTION

Reverse engineering an USB Video Grabber device protocol and creating a Linux kernel driver.

TRANSCRIPT

Page 1: Reverse Engineering: Writing a Linux driver for an unknown device

Ľubomír Rintel <[email protected]>OSSConf 2013, Žilina

BTC: 1A28Etzh7zsK2Bq36qvPKJi18s53M9B2FU

Reverse Engineering:Writing a Linux driver for an

unknown device

Page 2: 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

Page 3: Reverse Engineering: Writing a Linux driver for an unknown device
Page 4: Reverse Engineering: Writing a Linux driver for an unknown device

The Plan

● Make it work in Windows● Capture what happens● Find image data● Mimic the behavior in userspace● Transform into a kernel module

Page 5: Reverse Engineering: Writing a Linux driver for an unknown device

USB

Page 6: Reverse Engineering: Writing a Linux driver for an unknown device

USB Architecture

● Network of Host, Hubs and Devices

Page 7: Reverse Engineering: Writing a Linux driver for an unknown device

USB Addresses

● Bus & Device number

Host

Device 1:1Hub

Device 2:1Hub

Device 3:1Mouse

Device 2:2Flash Drive

Page 8: Reverse Engineering: Writing a Linux driver for an unknown device

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...

Page 9: Reverse Engineering: Writing a Linux driver for an unknown device

USB Device

● Self-describing● Endpoints

● CONTROL● INTERRUPT● BULK● ISOCHRONOUS

● Endpoints grouped into Interfaces● Interfaces grouped into Configurations

Page 10: Reverse Engineering: Writing a Linux driver for an unknown device

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

Page 11: Reverse Engineering: Writing a Linux driver for an unknown device

The Plan

● Make it work in Windows● Capture what happens● Find image data● Mimic the behavior in userspace● Transform into a kernel module

Page 12: Reverse Engineering: Writing a Linux driver for an unknown device

Windows & VirtualBox

Page 13: Reverse Engineering: Writing a Linux driver for an unknown device

Wireshark & usbmon

Page 14: Reverse Engineering: Writing a Linux driver for an unknown device

What did we see

● Number of CONTROL requests● ISOCHRONOUS packets once capture starts

Page 15: Reverse Engineering: Writing a Linux driver for an unknown device

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

Page 16: Reverse Engineering: Writing a Linux driver for an unknown device

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

Page 17: Reverse Engineering: Writing a Linux driver for an unknown device

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

Page 18: Reverse Engineering: Writing a Linux driver for an unknown device

Test image

0xaaaaaaaa0xff00ff00

0x00ff00ff

0x80808080

0x00000000

Page 19: Reverse Engineering: Writing a Linux driver for an unknown device

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)

...

Page 20: Reverse Engineering: Writing a Linux driver for an unknown device
Page 21: Reverse Engineering: Writing a Linux driver for an unknown device

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/

Page 22: Reverse Engineering: Writing a Linux driver for an unknown device

Architecture

Video4Linux2

Videobuf2

Our

cod

eUSB

Use

rspa

ce

Har

dwar

e

Page 23: Reverse Engineering: Writing a Linux driver for an unknown device

Video4Linux2

● Provide a device with known API● open(), close()● read(), write()● ioctl()● mmap()

● Negotiate format with userspace

Page 24: Reverse Engineering: Writing a Linux driver for an unknown device

Videobuf2

● Manages buffers of frames● Connects to Video4Linux2

● read(), write(), mmap()● some ioctl()s

– Start/stop capture– Exchange buffers with userspace

Page 25: Reverse Engineering: Writing a Linux driver for an unknown device

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

Page 26: Reverse Engineering: Writing a Linux driver for an unknown device

Architecture

Video4Linux2

Videobuf2

Our

cod

eUSB

Use

rspa

ce

Har

dwar

e

Page 27: Reverse Engineering: Writing a Linux driver for an unknown device

All done!

Page 28: Reverse Engineering: Writing a Linux driver for an unknown device

Questions?

Found this useful? My Bitcoin address is:1A28Etzh7zsK2Bq36qvPKJi18s53M9B2FU