Code Painters The Art of Coding

11Dec/0923

Android: IMEI number and the emulator

Update: Please see my latest post about this topic.

It is a common practice for mobile applications to identify the user by IMSI number (associated with the SIM card) or IMEI number (unique ID of the device). Of course, it is also possible on Android:

TelephonyManager manager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
String imei = manager.getDeviceId();
String imsi = manager.getSubscriberId();

This code works perfectly fine on a real device, however under emulator IMEI is always all-zero and it's not configurable. It quickly becomes awkward when debugging a network-enabled application which uses IMEI as a user ID.

Trying to resolve the problem I first looked at the TelephonyManager service, just to find the following snippet:

    private IPhoneSubInfo getSubscriberInfo() {
        // get it each time because that process crashes a lot
        return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
    }

Fair comment, isn't it? It really made my day 🙂

Anyway, code analysis shows that IMEI/IMSI request goes down through all the telephony layers (see the diagram), eventually getting to  the baseband device. In case of emulated system, rild daemon is used together with libreference-ril.so - reference Vendor RIL library which talks to the baseband modem device using plain, old AT commands.

The modem device itself is emulated outside the Android system, as part of qemu (which is the heart of the emulator). Details of the communication between the emulator and the Android system running inside the emulator are interesting on its own (all the communication goes through a virtual serial port, Android system's qemud daemon is used to (de)multiplex the data). I'll try to post a brief introduction to the topic soon.

Virtual modem implementation can be found in external/qemu/telephony/android_modem.c. The most important part of the file is this function:

const char*  amodem_send( AModem  modem, const char*  cmd );

This function is called for each received AT command. For each command sDefaultResponses array is searched for a given command and either predefined response is sent, or a command handler is executed. The array itself looks like:

static const struct {
    const char*      cmd;     /* command coming from libreference-ril.so, if first
                                 character is '!', then the rest is a prefix only */

    const char*      answer;  /* default answer, NULL if needs specific handling or
                                 if OK is good enough */

    ResponseHandler  handler; /* specific handler, ignored if 'answer' is not NULL,
                                 NULL if OK is good enough */
} sDefaultResponses[] =
{
    /* ... */
    { "+CIMI", OPERATOR_HOME_MCCMNC "000000000", NULL },   /* request internation subscriber identification number */
    { "+CGSN", "000000000000000", NULL },   /* request model version */
    /* ... */
};

Two array rows cited above are responsible for IMSI and IMEI retrieval. As you can see, both values are hardcoded and there is no chance to modify them without recompiling the emulator.

However, an old-school hack comes in handy. The emulator binary is not encrypted nor compressed, so the string literals should be visible inside the emulator binary. In fact they are, and IMEI number can be modified in a few simple steps:

  • backup the emulator binary
  • open the binary with your favourite hex editor
  • search for +CGSN string followed by a null byte, it should be followed by 15 digits of the IMEI number
  • edit the number, be careful not to change the number of digits
  • save the file, that's all!

Sure, it's not a perfectly comfortable solution, yet better than nothing. In the next part I'll explain how to make IMEI number a configurable option. Enjoy!

Share:
  • Facebook
  • Digg
  • del.icio.us
  • Twitter
  • LinkedIn
  • Google Bookmarks
  • Reddit
  • StumbleUpon
Comments (23) Trackbacks (0)
  1. Sorry if this is a silly question, but which binary file are you referring to? It’s not the SDK Setup executable I assume?

    • No, I refer to the Android emulator binary. Look for a file named emulator.exe on Windows (I’m not sure, I have no Windows machine here), and emulator on Linux/Mac.

  2. Thank you! I can now modify both IMEI and IMSI. But do you have any idea where we can modify the 20-digit sim serial number?

  3. You should look at sim_card.c, it seems to contain hardcoded responses to AT commands requesting various SIM card records. I believe it can be hacked in the same way as IMEI or IMSI.

    However, unfortunately, I’m not familiar with AT commands for GSM modems enough to guess which response needs to be modified. I suggest consulting some modem reference manual.

    Look here, search for answers[] :

    http://android.git.kernel.org/?p=platform/external/qemu.git;a=blob;f=telephony/sim_card.c;h=a5a32498d5eab3bcfa5693757230cd85ebf89940;hb=HEAD

  4. I would like to change the IMEI of my ADP2 developer phone, as the emulator cannot provide the functionality that I need for testing purposes.

    Do you know if the IMEI behaves the same way on actual hardware?

    Cheers

    • Nope, it is so easy to change in the emulator because the whole GSM modem is emulated by code running in QEMU, sending hardcoded responses. On real hardware the telephony subsystem will communicate with a real GSM modem. For sure it is possible to hack it around, but it is far from being that trivial.

  5. I seem to be too stupid to find this string with a hex editor. Or at least im finding serveral .. and don’t know which one the right one is.

  6. Thanks for the fast reply.
    I think if found it now …
    So it seems like it didnt change in the new version.

    How can i see what my IMEI on my virtual device is?

  7. And sometimes changing IMEI results in connection issues on my SDK. Is that normal?

  8. To explain what i am trying to do: im trying to run an app on the SDK and try to connect to it.
    This all works ..but i of course connect on a test-account. Everyone connects into this account using the SDK.
    So i thought changing the IMEI or the IMSI would identify my SDK as “another” phone and would allow me to create a new account.
    Changing the IMEI does nothing. Changing the IMSI results in connection-problems.

    Is there any other ID that could probably be the one this app is checking? Device_ID or something like this?

  9. So, I am guessing, that I can’t spoof different IMEI for different AVD’s with this trick, right? I test on various AVD’s and would have ideally liked each emulator reporting different IMEI’s.

    • Indeed, if you edit the emulator binary the way I’ve described, all your AVD’s would share the same IMEI. As a workaround, you can use multiple copies of the binary (but that would only work if you spawn the emulator manually).

      I have done a little patch adding the IMEI number property to the AVD configuration file. It works, but is not really a clean solution, so I’ve never published it. Perhaps it’s worth posting it upstream to Google 🙂

      • I would love to have a copy of that package if you could provide it to me before I wait for the update from Google. I could keep it to myself if you would like to. I am testing my program, and not being able to use different IMEI for different AVD is a blocking issue for me. Thank you in advance!

        • What is your development platform? I’ve only tried that change on Linux, building the SDK for Windows is a painful process according to Google, I haven’t tried it myself (as I rarely use Windows, anyway).

  10. Unfortunately my development platform is Windows. I could probably search for how to compile it online though. Did you get the Android source using git? Thanks!

  11. Okay. I really need to do this on my Android phone. But I am a rookie at using proper codes and what programs to use them in when it comes to this. So can someone please give me a summary or guide to do this? Like, tell me how and where to put these codes in until I get to the HEX editing, which I can do. And how do I backup the emulator binary?
    Thanks.

  12. hey,there is no +CGSN string in emulator.exe binary. I m using emulator on windows platform.

    • This is because in recent SDKs (not sure when it changed) emulator is only a thin wrapper spawning actual emulator binary. You should try with emulator-x86 and/or emulator-arm binaries instead!

  13. I know this is an old article, but here is an update.

    As you noted in your last comment, you now have to edit either emulator-arm.exe or emulator-x86.exe depending on which type of hardware you are trying to emulate. (A significant number of applications will not run or even install in the x86 environment, but if it does and you are running on Win7 and not in a VM, then you can use the Intel HAXM to greatly improve the emulator’s speed.)

    You can run the hardware specific EXEs directly which allows you to have multiple edited versions. However, not all command line options are available.

    In the latest version, the IMSI value is now 310260000000000. If you change it, it breaks Internet communications completely. I’ve even tried setting it to all zeros.

    It’s crazy that Google would go through so much effort to emulate at the hardware level resulting in a very slow environement but then they hardcode values that many client-server type apps will need to be changeable for testing.

    • Hi! There’s another article on my blog with an emulator patch allowing for IMEI/IMSI setting via AVD configuration. In the comments someone already reported the issue with changed IMSI breaking the communications. However, it seems that as long as the IMSI starts with 31026, everything is fine – I was never curious enough to look for the piece of code that needs this prefix to work.

      I perfectly agree with your opinion about the emulator environment. iOS emulator is so fast and light compared to Android’s… And thanks for the HAXM trick, I’ll definitely try it!


Leave a comment

No trackbacks yet.