Detect The Recovery Device Using LibUSB

UPDATE: I should have read Geohot’s driver code earlier, the secrets to USB communication with iPhone in recovery mode is right inside the code. Thanks timschuerewegen’s comment which drives me to read Geohot’s code and it does help. This article seems dumb if you have read Geohot’s code, but at least it shows you how I reverse the code to analyze and learn before I read the actual source iBooter uses to access the device.

UPDATE: I’ve figured out how to handle recovery mode using Apple iBoot USB Driver, Geohot’s driver is a very good starting point to learn for beginners. I’ve written a dirty class to handle it, here’s a snapshot of my test program which uses LibUSB to access Apple iBoot USB Driver:

Source code for is available: HERE (there might be bugs in code)
NOTICE: The GUI uses Raize Component Suite so you will not be able to compile it if you don’t have this component, but it’s easy to write your own GUI using the included unitIUSB class.

— old post follows —

I’m curious about everything I don’t know and always try to learn from other people’s code, this time I turn to iBooter because I want to implement the bi-directional communication facility into iLiberty+. As of the time this article was written, there’s no iBooter source code yet, so I fired up my favorite IDA Pro and took a brief look at what’s inside iBooter.

The program is very small (about 9.5KB) so it’s sort of easy to disassemble, and the flow is straightforward, all operations are based on the LibUSB, this is good because LibUSB has various libraries, even including a BCC import library, so writing a similar function in C++ Builder will not be too difficult.

Later I decided to go further to see how it works, following main(), I soon got to a function which was used to find the recovery device (iPhone), I took a deep look into it, then I found 2 interesting values that I didn’t know: 0×5AC and 0×1280. The following is the flowchart of the function:

usb_device_handle *getRecoveryDeviceHandle()

usb_device_handle *getRecoveryDeviceHandle

The program tried to cycle through all devices on all buses to find out the recovery device, the above two values (0×5AC and 0×1280) were used to examine if the device is what we’re looking for, since the values are compared with some data in usb_device, here’s the definition for usb_device:

struct usb_device {
  struct usb_device *next, *prev;

  char filename[LIBUSB_PATH_MAX];

  struct usb_bus *bus;

  struct usb_device_descriptor descriptor;
  struct usb_config_descriptor *config;

  void *dev;		/* Darwin support */

  unsigned char devnum;

  unsigned char num_children;
  struct usb_device **children;
};

In the program, the value 0×5AC was compared with value at offset 0×214 which I thought was the low word of dev (because next and prev each occupied 4 bytes, filename occupied 0×200 bytes, bus occupied 4 bytes, decscriptor and config each took 4 bytes, that sums up to 8+0×200+4+8 = 0×214), and value 0×1280 was compared with value at offset 0×216 which I thought was the high word of dev. I quickly checked the LibUSB documentation, no description about this. Header file was not helpful at all, there’s only a comment /* Darwin support */ so I had no idea what it was for, just speculating it’s some kind of signature, but it’s weird to use a pointer for signature purpose.

I sent a quick and dirty question to cmw (the developer of iBooter) trying to get an answer, seemed like the guy’s busy on pwnage thing so I got the same quick and dirty answer: “Just wait for the source, will be available next week”.

UPDATE: cmw has mailed me and confirmed again the source will be released next week and he’s doing cleanup for the code, nice.

Later, I thought maybe I made some mistakes, so I checked it again, this time I figured out what was wrong. The descriptor was not a pointer, it’s a structure, so it occupied more bytes, the offset 0×214 and 0×216 actually falled into the structure usb_device_descriptor, my calculation was wrong. Here’s the definition for usb_device_descriptor:

struct usb_device_descriptor {
  unsigned char  bLength;
  unsigned char  bDescriptorType;
  unsigned short bcdUSB;
  unsigned char  bDeviceClass;
  unsigned char  bDeviceSubClass;
  unsigned char  bDeviceProtocol;
  unsigned char  bMaxPacketSize0;
  unsigned short idVendor;
  unsigned short idProduct;
  unsigned short bcdDevice;
  unsigned char  iManufacturer;
  unsigned char  iProduct;
  unsigned char  iSerialNumber;
  unsigned char  bNumConfigurations;
};

Combined the above 2 structures (struct usb_device and struct usb_device_descriptor), the calculation resulted in:

offset 0x214,0x215 = idVendor (short occupies 2 bytes)
offset 0x216,0x217 = idProduct (short occupies 2 bytes)

According to the above analysis, if idVendor is 0×5AC and idProduct is 0×1280 then it’s an iPhone, although I didn’t know if I was correct or not, it looked reasonable.

UPDATE: according to This Link offered by AViegas, 0×5AC does mean Apple, but the 0×1280 (I think its device id for iPhone) is not listed there, maybe iPhone is just too new to be included.

Anyway, before the source is released, I can still learn it from reversing, fortunately the code is not complex compared with other programs. Last, thanks cmw to write such an amazing tool, I’ll say it’s valuable both in functionalities and in education :) I had never written any USB related programs, and this reversing will be a very good starting point for me.

UPDATE: The function analyzed in this article is a typical function to detect and open a designated device (as illustrated in LibUSB’s documentation), it can be reversed to the following C++ code:

#define ID_APPLE 0x5AC
#define ID_IPHONE 0x1280
struct usb_dev_handle *GetRecoveryDeviceHandle(void)
{
    struct usb_bus *busses = usb_get_busses();
    if (busses)
    {
        struct usb_bus *bus;
        for (bus=busses; bus != NULL; bus=bus->next)
        {
            struct usb_device *dev;
            for (dev=bus->devices; dev != NULL; dev=dev->next)
            {
                if (dev->idVendor == ID_APPLE && dev->idProduct == ID_IPHONE)
                    return usb_open(dev);
            }
        }
    }
 
    return NULL;
}

BTW, idProduct returns different values for recovery mode and normal mode, as shown below:

Recovery mode: idVendor: 0×5AC, idProduct: 0×1280
Normal mode: idVendor: 0×5AC, idProduct: 0×1290

Related posts


17 Comments

  1. timschuerewegen
    Posted April 4, 2008 at 2:39 am | Permalink

    iBooter = libusb + http://iphonejtag.blogspot.com/2008/01/113-unlock-and-linux-driver.html

  2. idatheme
    Posted April 4, 2008 at 3:25 am | Permalink

    I like the IDA theme colors very much!
    Can you provide it or is it pre-made and somewhere available for download?

  3. Roger
    Posted April 4, 2008 at 9:23 am | Permalink

    Do you know what the reason why so many iphones have no wifi

  4. Posted April 4, 2008 at 10:03 am | Permalink

    @idatheme, it’s not a pre-made theme, it’s my customized theme. I don’t know how to export IDA theme, so here’re the snapshots of my color scheme, you may adjust your color accordingly:

    Color settings: Here
    Arrow settings: Here
    Graph settings: Here

  5. Posted April 4, 2008 at 10:20 am | Permalink

    @timschuerewegen, Windows also uses that driver ? I think Windows only uses Apple Recovery (iBoot) USB Driver. Geohot developed that driver for Linux. So:

    For Windows, iBooter = LibUSB + Apple iBoot USB Driver
    For Linux, iBooter = LibUSB + Geohot iPhone Linux Drvier (statically linked)

    And iBooter doesn’t access USB Driver directly, it accesses LibUSB, and which in turn accesses USB Driver.

  6. idatheme
    Posted April 5, 2008 at 7:09 am | Permalink

    Thanks!

  7. timschuerewegen
    Posted April 7, 2008 at 4:35 am | Permalink

    @george, sorry but you’re wrong :)

    iBooter (on any platform) = libusb + client code from George Hotz’s iphone linux driver

    You don’t need to disassemble iBooter if you know how to use LibUSB (not that difficult) and understand what George Hotz’s client code is doing.

  8. Posted April 7, 2008 at 10:12 am | Permalink

    @timschuerewegen, yeah I might be wrong because I didnt even read geohot’s code :) and I was just thinking in a normal sense that a user application should not deal with hardware directly, from you comment it seems like I really need to read the driver code. The reason I need to disassemble iBooter is simply because I have no idea how to use LibUSB at all (as I said I didn’t write any USB code) so I gotta see how it calls LibUSB, and in what sequence etc, that’s my way to learn LibUSB.

  9. mav
    Posted April 8, 2008 at 2:30 pm | Permalink

    George: You either misspelled productID or there is something fishy around here.

    mav@marle:~$ lsusb
    Bus 005 Device 004: ID 05ac:1290 Apple Computer, Inc.

    My iPhone identifies itself as 0×1290, not 0×1280. It’s the 8G one.

  10. Posted April 8, 2008 at 2:51 pm | Permalink

    @mav, if you read the article carefully, you should know it’s for the recovery mode device :)

    Okay, to clarify it: iPhone in recovery mode: 0×1280, iPhone in normal mode: 0×1290.

  11. mav
    Posted April 9, 2008 at 2:48 pm | Permalink

    Okay, now everything’s clear :).

  12. Ben
    Posted April 11, 2008 at 8:47 pm | Permalink

    Do you mind to share your C++ Builder Code?
    Thank you ;-)
    Ben

  13. Posted April 13, 2008 at 10:41 pm | Permalink

    @Ben, refresh to see the source, hope it helps.

  14. Ben
    Posted April 14, 2008 at 3:52 am | Permalink

    great, thanks!

  15. jessica
    Posted April 19, 2008 at 2:03 am | Permalink

    Also, my touch cant respond to anything!!1 I think it got something bad

  16. Paul
    Posted July 1, 2008 at 11:34 pm | Permalink

    why won’t iliberty ” go for it ” to jail break the iphone i have.. it has 0 functionality ..please respond thru my email please … if any one has an answer …. i hope i did not get screwed in purchasing this program …

  17. Stephen
    Posted July 3, 2008 at 6:32 pm | Permalink

    Hi George, first off thank you for a great programme, it does everything needed with ease and simplicity. I would be writing unless I had a problem, and my problem is the dreaded ‘repair needed’. What’s the problem here and can it be resolved. I am hoping it’s going to be easy. If you can help, I would sincerely appreciate it.

    Without wishing to be self congratulatory, it was with great empathy and sympathy that, through our church, we made our donation to Christian Aid, specifically for the flood and earthquake in China. Not everyone spends their time navel gazing and fixated on their own problems.

    Again thanks

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*