Recently, I've had the pleasure to examine the libraries, and implementation code associated with the new generation of "driverless dongles" under Linux. I've examined two different products from different companies, both with the same "feature" on their keys. This feature is the ability to plug it into the box, and not have it require a driver be loaded for your application to work. To facilitate this feat, they simple assign their dongle to the HID (Human Interface Device) class in their USB descriptors, and when it's plugged in, Linux enumerates it, adds it to the tree, and that's that. Then, when the time comes to talk to it from a protected application, you use a library provided by the publisher. It has mostly been this library that has allowed me to gain a full understanding of a key that I've never touched, and another that I have. It seems that both companies, NOT related, and THOUSANDS of miles apart, had the same idea. "Let's use libusb inside our library, so that the code will be simple!". Well, that it is. A little TOO simple. After finding the library online, and tossing it into IDA Pro, I was able to determine that it was libusb, determine the version, and then see how they used it. Now, for your protection to be simple enough that a guy like me can spend about 30 minutes with it, and have a complete grasp of it, is kinda sad.
The pitfalls that I saw included the following:
* Forgetting(?) to strip the symbols from the library before shipping. This allows IDA to label all the functions and makes the whole process MUCH simpler to understand.
* Publishing the entire API spec, and library to the net, so that ANYONE can get a copy of it. I understand that it's a delicate issue of "We want developers to be able to look at how easy it all it". But, you're also giving away the keys to the store at the same time. As this also allowed someone to see where this library is integrated into a customer's program, and have a COMPLETE understanding of the names of the functions, as well as what they do.
* Using libusb. I understand that you want the library to be as simple, yet robust as possible, and that using an available, and THOROUGHLY tested lib makes that process much easier, but it also makes the reverse engineering process much easier as well.
I heard you saying "Those are all interesting things, but what do these holes allow me to do?". Well, here's what I was able to do. I developed a driver that registered itself with the USB stack as a dongle. Then, when the applications enumerated the devices, they found ME, assumed I was a key, and began talking to me. A VERY little debugging of the target application, and I was able to return the "right" answers to the applications challenges.
Once I acquired my own key of the 2nd type, I was able to write a VERY SMALL driver (400 lines of C code!), that was able to intercept all communications with the dongle, and "change" the data that my dongle was returning that wouldn't match what the application was expecting. (Login passwords that the dongle requires, GUIDs, etc.) So, now, the target application runs with a key that isn't the right one. It even reads the memory from the key, and everything else that it's supposed to do, and has no idea that I'm there.
I could write a BOOK on how bad the code was in the target application, but even had that NOT been the case, this still would have been an easy crack job.
If you are just starting Linux reverse engineering, and are faced with a dongle, I *HIGHLY* recommend that you look into an option called "usbfs_snoop". You can find it under the /proc tree. This will show you what types of IOCTLs are being sent to the key. Pair that up with strace, and you have a potent 1-2 punch.
Sunday, September 11, 2011
Subscribe to:
Posts (Atom)