RevNIC Reverse Engineering of Binary Device Drivers Vitaly Chipounov and George Candea School of Computer & Communica3on Sciences
Drivers: Hard to Write and Hard to Port Drivers are o@en closed source Por3ng from exis3ng drivers is difficult Devices rarely come with an interface specificadon Hard to write a driver from scratch SpecificaDons are o@en incomplete and buggy Buggy driver implementa3on
ExisDng SoluDons EmulaDng source OS (VMs, NDISwrapper...) Run 3me overhead, hard to maintain Making drivers from specificadons (Termite) Requires formal specifica3ons Manual trace analysis, decompiladon Tedious, imprecise
Windows Windows Linux KitOS μc/os II x86 PC Virtual Machines FPGA http://bplteensofwa.files.wordpress.com/2009/07/computer.jpg
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac3on traces RevNIC Code Synthesizer NIC Driver Template SyntheDc Driver
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac3on traces RevNIC Code Synthesizer NIC Driver Template SyntheDc Driver
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac3on traces RevNIC Code Synthesizer NIC Driver Template SyntheDc Driver
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac3on traces RevNIC Code Synthesizer NIC Driver Template SyntheDc Driver
High Coverage Driver Exerciser Hand cra@ed workload is not enough
int irq_handler(device_t *dev) { status = hw_read(status_reg); if (status == RX){ pkt_size = hw_read(rx_size_reg); if (pkt_size < 1514) { recv_packet(dev); else { drop_packet(dev); else if (status == TX) {...
int irq_handler(device_t *dev) { status = hw_read(status_reg); if (status == RX){ pkt_size = hw_read(rx_size_reg); if (pkt_size < 1514) { recv_packet(dev); else { drop_packet(dev); else if (status == TX) {... Boundary condidons Error recovery code
int irq_handler(device_t *dev) { status = hw_read(status_reg); if (status == RX){ pkt_size = hw_read(rx_size_reg); if (pkt_size < 1514) { recv_packet(dev); else { drop_packet(dev); else if (status == TX) {...
int irq_handler(device_t *dev) { status = hw_read(status_reg); if (status == RX){ pkt_size = hw_read(rx_size_reg); if (pkt_size < 1514) { recv_packet(dev); else { drop_packet(dev); else if (status == TX) {...
int irq_handler(device_t *dev) { status = hw_read(status_reg); if (status == RX){ pkt_size = hw_read(rx_size_reg); if (pkt_size < 1514) { recv_packet(dev); else { drop_packet(dev); else if (status == TX) {... status == TX status == RX F T...... drop packet pkt_size < 1514 receive packet
int irq_handler(device_t *dev) { status = hw_read(status_reg); if (status == RX){ pkt_size = hw_read(rx_size_reg); if (pkt_size < 1514) { recv_packet(dev); else { drop_packet(dev); else if (status == TX) {... status == TX status == RX F T...... drop packet pkt_size < 1514 receive packet High coverage automated driver exerciser
explorer.exe... advapi32.dll Applications and... libraries msvcrt.dll ntdll.dll user32.dll... Device Drivers Windows Kernel ndis.sys rtl8139.sys...
Exercising Windows NIC Drivers NICDRIVER.SYS IniDalize(...) QueryInformaDon(...)... SendPacket(...) HandleInterrupt(...) Unload(...)
Exercising Windows NIC Drivers NICDRIVER.SYS IniDalize(...) QueryInformaDon(...)... SendPacket(...) HandleInterrupt(...) Unload(...)
Exercising Windows NIC Drivers IniDalize(...)
Exercising Windows NIC Drivers IniDalize(...)
Exercising Windows NIC Drivers IniDalize(...)
IniDalize(...)
IniDalize(...) Send(..., Packet,...)
IniDalize(...) 001a706650e3... Send(..., Packet,...)
IniDalize(...) α β γ δ ε ϛ... Send(..., Packet,...)
α β γ δ ε ϛ... Send(..., Packet,...)
α β γ δ ε ϛ... Send(..., Packet,...) Interrupt
α β γ δ ε ϛ... Send(..., Packet,...) Interrupt HandleInterrupt(...)
(..., Packet,...) Interrupt dleinterrupt(...)
(..., Packet,...) Interrupt dleinterrupt(...) Unload(...)
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac3on traces RevNIC Code Synthesizer NIC Driver Template SyntheDc Driver
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac,on traces RevNIC Code Synthesizer NIC Driver Template SyntheDc Driver
Hardware InteracDon Traces Virtual Machine Guest OS Original Binary Driver Driver Exerciser ExecuDon tree Machine instrucdons Memory accesses Register values (Memory Mapped) I/O Trace Files
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac,on traces RevNIC Code Synthesizer NIC Driver Template SyntheDc Driver
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac3on traces RevNIC Code Synthesizer NIC Driver Template Traces C code SyntheDc Driver
ExecuDon Tree
ExecuDon Tree Sequences of basic blocks BB 1 BB 2 BB 3 BB 4 BB 5 BB 6 BB 7 Trace #1
ExecuDon Tree Sequences of basic blocks BB 1 BB 2 BB 3 BB 4 BB 5 BB 6 BB 7 BB 1 BB 2 BB 3 BB 4 BB 8 BB 9 BB 7 Trace #1 Trace #2
BB 1 BB 2 BB 3 BB 4 BB 5 BB 6 BB 7 BB 1 BB 2 BB 3 BB 4 BB 8 BB 9 BB 7 Trace #1 Trace #2
BB 1 BB 2 BB 3 BB 4 BB 5 BB 6 BB 7 BB 1 BB 2 BB 3 BB 4 BB 8 BB 9 BB 7 Trace #1 Trace #2
BB 1 BB 2 BB 3 BB 4 BB 1 BB 2 BB 3 BB 4 BB 1 BB 2 BB 3 BB 4 BB 5 BB 8 BB 6 BB 5 BB 8 BB 9 BB 7 BB 6 BB 9 BB 7 Trace #1 BB 7 Trace #2
CFG BB 1 BB 2 BB 3 BB 4 BB 1 BB 2 BB 3 BB 4 BB 1 BB 2 BB 3 BB 4 BB 5 BB 8 BB 6 BB 5 BB 8 BB 9 BB 7 BB 6 BB 9 BB 7 Trace #1 BB 7 Trace #2
CFG BB 1 BB 2 BB 3 BB 4 BB 5 BB 8 BB 6 BB 9 BB 7
CFG BB 1 BB 2 BB 3 BB 4 uint32_t function_0001(...) { BB1: BB2: BB3: BB4: BB 5 BB 6 BB 8 BB 9 BB5: BB6: BB8: BB9: BB 7 BB7:
BB 5 BB 6 CFG BB 1 BB 2 BB 3 BB 4 BB 7 BB 8 BB 9 uint32_t function_0001(uint32_t param1, uint32_t param2) { /*... */ BB1: goto BB2; BB2: v1 = read_port(param1); BB3: v2 = read_port(param2); BB4: if (v1 & 0x21) goto BB8; BB5: write_port(param2, 0x1234); BB6: goto BB7; BB8: write_port(param1, 0x4567); BB9: goto BB7; BB7:
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac3on traces RevNIC Code Synthesizer NIC Driver Template Traces C code SyntheDc Driver
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac3on traces RevNIC Code Synthesizer Traces C code NIC Driver Template C code driver SyntheDc Driver
Device Driver Structure Hardware facing funcdons Automa3cally synthesized by RevNIC OS facing funcdons Provided by the driver template
Hardware InteracDon Code Template Driver
Linux Network Driver Template Templates contain OSspecific boilerplate int pci_nic_init(...) { /* Allocate device resources */ i = pci_enable_device (pdev); if (i) {... ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; if (request_region (ioaddr, ADDR_RANGE, DRV_NAME) == NULL) {... /* --------------------------------- * Insert device detection code here * --------------------------------- */ /* Allocate private memory */ dev = alloc_netdev(...); if (!dev) {... /* Register entry points */...
Linux Network Driver Template Templates contain OSspecific boilerplate int pci_nic_init(...) { /* Allocate device resources */ i = pci_enable_device (pdev); if (i) {... ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; if (request_region (ioaddr, ADDR_RANGE, DRV_NAME) == NULL) {... /* --------------------------------- * Insert device detection code here * --------------------------------- */ /* Allocate private memory */ dev = alloc_netdev(...); if (!dev) {... /* Register entry points */...
int pci_nic_init(...) { /* Allocate device resources */ i = pci_enable_device (pdev); if (i) {... ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; if (request_region (ioaddr, ADDR_RANGE, DRV_NAME) == NULL) {... /* --------------------------------- * Insert device detection code here * --------------------------------- */ /* Allocate private memory */ dev = alloc_netdev(...); if (!dev) {... /* Register entry points */...
int pci_nic_init(...) { /* Allocate device resources */ i = pci_enable_device (pdev); if (i) {... ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; if (request_region (ioaddr, ADDR_RANGE, DRV_NAME) == NULL) {... /* --------------------------------- * Insert device detection code here * --------------------------------- */ Placeholders for hardware interacdon /* Allocate private memory */ dev = alloc_netdev(...); if (!dev) {... /* Register entry points */...
int pci_nic_init(...) { /* Allocate device resources */ i = pci_enable_device (pdev); if (i) {... ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; if (request_region (ioaddr, ADDR_RANGE, DRV_NAME) == NULL) {... /* --------------------------------- * Insert device detection code here * --------------------------------- */ if (hw_checkdevice(ioaddr) < 0) { v1 = read_port(ioaddr); if (!(v1 & 1)) { goto lbl0; write_port(ioaddr, 0); lbl0: write_port(ioaddr, 1); /* Allocate private memory */ dev = alloc_netdev(...); if (!dev) {... /* Register entry points */...
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac3on traces RevNIC Code Synthesizer NIC Driver Template SyntheDc Driver
RevNIC Virtual Machine Guest OS Original Binary Driver Driver Exerciser Hardware interac3on traces RevNIC Code Synthesizer NIC Driver Template SyntheDc Driver insmod revnic_driver.ko
ImplementaDon QEMU virtual machine 1 x86 to LLVM translator KLEE symbolic execudon engine 2 1 F. Bellard. QEMU, a Fast and Portable Dynamic Translator. In USENIX 2005. 2 C. Cadar et al. KLEE: Unassisted and automa3c genera3on of high coverage tests for complex systems programs. In OSDI 2008.
EvaluaDon RevNIC can port network drivers between different OS plaiorms different hardware architectures SyntheDc drivers have good performance
Reverse Engineered Drivers Driver Size 1 AMD PCNet Realtek RTL8139 SMSC 91C111 Realtek RTL8029 (NE2000) 35 KB 20 KB 19 KB 18 KB 1 80% of Linux 2.6.26 NIC drivers are smaller than 35KB
Target Plaiorms Windows Windows Linux KitOS μc/os II http://bplteensofwa.files.wordpress.com/2009/07/computer.jpg
Target Plaiorms Windows Windows Linux KitOS μc/os II x86 PC RTL8139 http://bplteensofwa.files.wordpress.com/2009/07/computer.jpg
Target Plaiorms Windows Windows Linux KitOS μc/os II x86 PC VMware QEMU RTL8139 PCnet, NE2000 http://bplteensofwa.files.wordpress.com/2009/07/computer.jpg
Target Plaiorms Windows Windows Linux KitOS μc/os II x86 PC RTL8139 VMware QEMU PCnet, NE2000 FPGA4U SMSC 91C111 http://bplteensofwa.files.wordpress.com/2009/07/computer.jpg
EffecDveness RevNIC reverse engineers all relevant funcdonality IniDalizaDon, sending, recepdon, shutdown, DMA, etc.
Performance Throughput (Mbps) 100 80 60 40 20 0 Windows KitOS Windows Windows Linux Original Windows Linux Windows Original 0 200 400 600 800 1000 1200 1400 UDP Packet Size (Bytes)
Performance Throughput (Mbps) 100 80 60 40 20 0 Windows KitOS Windows Windows Linux Original Windows Linux Windows Original 0 200 400 600 800 1000 1200 1400 UDP Packet Size (Bytes)
Performance Throughput (Mbps) 100 80 60 40 20 0 Windows KitOS Windows Windows Linux Original Windows Linux Windows Original 0 200 400 600 800 1000 1200 1400 UDP Packet Size (Bytes)
Performance Throughput (Mbps) 100 80 60 40 20 0 Windows KitOS Windows Windows Linux Original Windows Linux Windows Original 0 200 400 600 800 1000 1200 1400 UDP Packet Size (Bytes)
PorDng Effort
PorDng Effort Virtual Machine Guest OS Original Binary Driver 80% basic block coverage ~20 min Zero manual effort Driver Exerciser
PorDng Effort Virtual Machine Guest OS Original Binary Driver 80% basic block coverage ~20 min Zero manual effort Driver Exerciser ~1 min RevNIC Code Synthesizer Zero manual effort
PorDng Effort Virtual Machine Guest OS Original Binary Driver Driver Exerciser 80% basic block coverage ~20 min Zero manual effort Few hours 5 days ~1 min RevNIC Code Synthesizer One Dme effort NIC Driver Template Zero manual effort
PorDng Effort Virtual Machine Guest OS Original Binary Driver Driver Exerciser 80% basic block coverage ~20 min Zero manual effort Few hours 5 days ~1 min RevNIC Code Synthesizer One Dme effort NIC Driver Template Zero manual effort SyntheDc Driver (e.g., Linux)
PorDng Effort RevNIC speeds up driver development Device Manual (Linux) RevNIC Persons Span Persons Span RTL8139 18 4 years 1 1 week 91C111 8 4 years 1 4 days NE2000 5 2 years 1 5 days PCNet 3 4 years 1 1 week
PorDng Effort RevNIC speeds up driver development Device Manual (Linux) RevNIC Persons Span Persons Span RTL8139 18 4 years 1 1 week 91C111 8 4 years 1 4 days NE2000 5 2 years 1 5 days PCNet 3 4 years 1 1 week
PorDng Effort RevNIC speeds up driver development Device Manual (Linux) RevNIC Persons Span Persons Span RTL8139 18 4 years 1 1 week Mostly fixing undocumented quirks 91C111 8 4 years 1 4 days NE2000 5 2 years 1 5 days PCNet 3 4 years 1 1 week
PorDng Effort RevNIC speeds up driver development Device Manual (Linux) RevNIC Persons Span Persons Span RTL8139 18 4 years 1 1 week 91C111 8 4 years 1 4 days NE2000 5 2 years 1 5 days PCNet 3 4 years 1 1 week
RevNIC Reverse engineering of driver s state machine from interacdon traces High coverage reverse engineering through symbolic execudon Using symbolic hardware for reverse engineering without access to original devices
RevNIC Reverse engineering of driver s state machine from interacdon traces High coverage reverse engineering through symbolic execudon Using symbolic hardware for reverse engineering without access to original devices http://reveng.epfl.ch