Windows Remote Memory Access Though FireWire

Thomas Ptacek | February 9th, 2007 | Filed Under: Defenses, Development, Uncategorized

Maximillian Dornseif made a splash at CanSec in 2005 by hijacking Linux and OS X machines using a malicious iPod and the FireWire port. As it turns out, the “link layer” for FireWire —- OHCI, which is roughly to FireWire what Ethernet would be to 1000bTX if it included a standard programming interface —- supports direct DMA to host physical memory. You can plug a FireWire device in to a machine and read or write arbitrary physical memory locations.

OHCI Diagram

Get a sense of what this looks like for an “attacker” from Maximillian’s own presentation. Then, note the table of systems “compatible” with the attack:

  • OS X (supports read/write)

  • FreeBSD (supports read/write)

  • Linux (supports write)

  • Windows 2000 (crashes)

  • Windows XP (no support)

The reason Maximillian’s attack doesn’t seem to work against Windows XP is that OHCI specifies “Asynchronous Filter” and “Physical Filter” CSRs (a CSR is a hardware ioctl, by the way); if these CSRs are set to zero, the FireWire chipset will reject requests to access host physical memory. According to the spec, they default to zero. Windows doesn’t set them. So, by default, Windows disallows FireWire DMA.

I think this is pretty well known, but the attack does work against Windows (at least, pre-Vista). For instance, Adam Boileau showed that you can fake up a config ROM for yourself that, when read by the Windows host, will open up the filter CSRs. His attack basically advertises his machine as requiring DMA access, and Windows complies.

An attractive thing about both Maximillian’s and Adam’s attacks are that they’re implemented in Python; both quickly wrap the Linux or OSX FireWire APIs with Python bindings and then speak FireWire to the target with Python scripts.

I’m not particularly interested in “owning” my Windows box with FireWire, because I own my Windows box already. But I am interested in surreptitiously debugging my kernel and user processes that are aggressively rigged for anti-debugging. So I bought a $20 FireWire PCI card, and got Nate Lawson to talk me through disabling the OHCI Physical Request filters.

CSRs for PCI devices are mapped into memory; the host will typically map a block of address space just for the CSRs, which Windows will tell you about if you click on “Driver Details”; you want the smaller, 2-4k address range.

Unix and Windows ioctls have indexes or codes. In mapped memory, CSRs have offsets. The offsets we care about are 0x100 and 0x108 (the high and low 32 bits of the 64 bit AsynchronousRequestFilter) and 0x110 and 0x108 (the 64 bit PhysicalRequestFilter). Windows says my OHCI CSRs live at 0xdfbf8800 (phy addresses, not kernel virts). So I want to write 0xdfbf8900, 0xdfbf8908, 0xdfbf8910, and 0xdfbf8918; I simply want them to be 0xFFFFFFFF.

You can do this from any ring 0 code, or you can just use kd:

!dc dfbf8900        # see if they're already set
!ed dfbf8910 ffffffff
!ed dfbf8918 ffffffff   # set the physical request filters
g

… and now Maximillian’s code will work against Vista (you can then disable kd with kdbgctrl.exe if you need to).

Note that a FireWire bus reset will clear these registers; the Windows OHCI driver will set the AsyncRequestFilter, but not the PhysicalRequestFilter, so you’ll need to repeat this process —- in particular, and annoyingly, every time you close your FireWire IOKit object on OSX. I got around this problem by writing a quick proxy from TCP to FireWire, which holds the object open and (so far) prevents the bus reset from getting me.

Obligatory “what does this let me do” graf? Adam and Maximillian explain it better, but the answer is, uh, anything? The FireWire chipset autonomously DMA’s host memory; if the kernel can’t keep the chipset’s CSRs configured to reject physical DMA requests, it can’t do anything to stop me from rewriting bits of the kernel or stealing crypto secrets out of memory.

Viewing 6 Comments

Trackbacks

close Reblog this comment
blog comments powered by Disqus