A little bit of everything

View Original

A journey in script-kiddie-land and kernel-land

Yes, I know what some of you may think: will we finally get the third and last part about the robot vaccum? You will. But trust me, I don’t have a lot of spare time and debugging the radio stuff is not the funniest part nor the easiest one!

But let’s come back to our subject. Reading some (all?) of my posts here, you may know what a GoodFET is. But have you heard about its little brother, the FaceDancer?

It is basically a GoodFET + an USB controller on the same PCB. It runs the same firmware as a GoodFET and it’s purpose is to be able to emulate any USB device that you can imagine. Under Linux, it is pretty easy to mess with USB peripherals by relying on libusb. But with an USB host controller, you cannot emulate peripherals at all. And that’s precisely where the FaceDancer comes in handy.

What can you do with that? Well, you can circumvent your company USB port policy by emulating a keyboard, just like shown with a teensy on Hackaday a while ago. Or you can capture USB firmware like demonstrated by the awesome Travis Goodspeed himself. You can even fingerprint the operating system by the way it is enumerating and reading an emulated USB mass storage device or do some bad ass anti-forensics stuff too, just like shown in 29C3 by Travis again.

Of course, you can just try to fuzz the USB protocol and try to find 0days on you preferred operating system. And guess what? That’s exactly what we are going to do here!

But the USB protocol is pretty tough. Without going into the details, a device must expose a device descriptor that exposes one or more configurations, on which you get several interfaces, each one using endpoints (usually two) to be addressed and endpoints can be of 4 types (control, isochronous, interrupt or bulk)… So writing a fuzzer, whether it is in Python or not, is just not straightforward.

Fortunately, NCC Group did a real great job and published less than two months ago a very neat tool called umap that is designed specially for the FaceDancer to be able to emulate devices, fuzz USB stacks and even fingerprint an operating system. The latter function is not very accurate though as my Ubuntu was shown as ChromeOS. But still, imagine what an attacker can do if he finds several exploits through the USB stack and if he can actually fingerprint the operating system in an accurate way by relying on the USB stack too (hint: think about reliability).

The tool is fairly easy to use (on my computer, the FaceDancer comes up as /dev/ttyUSB3):

# Finds devices supported by the OS
$ python3 umap.py -P /dev/ttyUSB3 -i
# Fuzz a HID device class
$ python3 umap.py -P /dev/ttyUSB3 -f 03:00:00:C
# Try to identify the operating system
$ python3 umap.py -P /dev/ttyUSB3 -O
# Run a single fuzz test case
$ python3 umap.py -P /dev/ttyUSB3 -s 03:00:00:C:16

So, as I already have a FaceDancer for almost a year and as I don’t have to write my own fuzzer from scratch, I decided that it could be fun to let that tool run against a fully patched and up-to-date Windows 8.1 64bits, just like a script-kiddie can do. And yes, sadly, you can get a BSOD by just running a public tool against it…

But, as we are going to see through this post, a blue screen does not necessarily mean that you have an 0day. At that moment, you only caught a bug.

The first thing when dealing with kernel bugs is to configure the victim to not just reboot after a BSOD but also generate a kernel memory dump that you can grab and analyse. Once done, trigger the bug, let the host reboot and grab your MEMORY.DMP file.

Once you’ve got your memory dump, the tool you need is WinDBG. It is not the sexiest debugger ever, nor it is the funniest or most intuitive to use (specially when it comes to scripting) but that’s still the one you need for that stuff :-)

First of all, configure your kernel symbol path otherwise you are working for nothing and then, simply load your file into the debugger (File > Open crash dump).

From this point, I will demonstrate the HID device test case number 16 called Report_Usage_Page_Logic_error2 (not the enumeration ones) provided by umap. Why this particular one? Well because it made the operating system crash from Windows XP to Windows 8.1 whether it was a 32bit version or a 64bit one :-)

WinDBG will tell you directly what caused the crash.

On the screen capture, you can see that WinDBG tells you that the crash, a bugcheck 0x7E, occurred in HIDPARSE.SYS which is obviously the drivers that deals with the USB keyboard we were emulating and fuzzing.

The debugger is also kind enough to guide you and make you launch its extension command “!analyze” (in WinBDG, every command that starts with an exclamation mark is implemented in an extension DLL). This command will give you details on what precisely happened.

Here we can see what type of error we encountered: a NULL pointer is deferenced.

And on this final screen, the debugger shows you the call-stack and the faulty function: HidP_ParseCollections in HIDPARSE.SYS file.

By digging a bit further, you can tell that a function is called to create a structure. As our emulated device sends invalid stuff, the function fails and returns a NULL pointer that the caller does not check and BANG! Classic input validation failure.

Unfortunately, this kind of bug is not going to lead into code execution and will stay a simple and annoying denial of service. It was somehow predictable as the NCC Group may already have run their own tool against Windows to check for 0day themselves and report them to the MSRC.

But like I said, I was merely using the tool out of the box. Even though it comes with a lot of emulated devices and test cases, there is still a huge amount of work around that tool that can be done. For example, within a device class (e.g. a printer), depending on the vendor ID and product ID you are emulating, you may hit different drivers and some of them may be more buggy than others (specially third party drivers). In addition to that, all the device classes are not implemented yet and the OS fingerprinting function may be improved.

I hope that this post made you interested in USB security assessment and kernel debugging. If you want to get more information about how to analyse a Windows kernel memory dump with WinBDG you can start by reading this page and I also warmly encourage you to keep an eye at my co-worker’s blog and/or following him on Twitter. He really is an awesome guy :-)

Should you find any vulnerability, don’t forget to report it the Microsoft Security Response Center for Windows related ones or the appropriate contact for other vendors. 

I also encourage you to contribute to umap tool to support the work that NCC Group did. That’s the best way to thank them for making it opensource software.

Finally, to conclude this post, I would like to thank another co-worker, F4b, that did the analysis of every single memory dump that umap generated. Even though we weren’t lucky this time, he is a scary dude when it comes to reverse engineering and/or vulnerability exploitation :-)