# HG changeset patch # User Michael Spacefalcon # Date 1385689171 0 # Node ID 1e797f846563026e8319e5312741c55464992f79 # Parent 3f38da3933c27e9fa7f60aa105dbfa64b88c6ac6 imeibrute written diff -r 3f38da3933c2 -r 1e797f846563 .hgignore --- a/.hgignore Fri Nov 29 00:39:02 2013 +0000 +++ b/.hgignore Fri Nov 29 01:39:31 2013 +0000 @@ -3,6 +3,7 @@ \.[oa]$ ^factdiff$ +^imeibrute$ ^mokosrec2bin$ ^pirimei$ diff -r 3f38da3933c2 -r 1e797f846563 Makefile --- a/Makefile Fri Nov 29 00:39:02 2013 +0000 +++ b/Makefile Fri Nov 29 01:39:31 2013 +0000 @@ -1,19 +1,21 @@ CC= gcc CFLAGS= -O2 STD= factdiff mokosrec2bin -NSTD= pirimei -PROGS= ${STD} ${NSTD} +CRYPTO= imeibrute pirimei +PROGS= ${STD} ${CRYPTO} all: ${PROGS} ${STD}: ${CC} ${CFLAGS} -o $@ $@.c -factdiff: factdiff.c -mokosrec2bin: mokosrec2bin.c +${CRYPTO}: + ${CC} ${CFLAGS} -o $@ $@.c -lcrypto +factdiff: factdiff.c +imeibrute: imeibrute.c +mokosrec2bin: mokosrec2bin.c pirimei: pirimei.c - ${CC} ${CFLAGS} -o $@ $@.c -lcrypto clean: rm -f ${PROGS} *.o *errs *.out diff -r 3f38da3933c2 -r 1e797f846563 imeibrute.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imeibrute.c Fri Nov 29 01:39:31 2013 +0000 @@ -0,0 +1,99 @@ +/* + * The IMEI "protection" implemented by TI for Calypso (as opposed to Calypso+ + * or LoCosto) platforms for those device manufs who desired to obfuscate their + * IMEIs (not everyone did - Openmoko opted out, for example), as seen in + * g23m/condat/com/src/comlib/cl_imei.c in the Leonardo semi-src by Sotovik, + * encrypts the IMEI using plain DES, using a key derived from the Calypso die + * ID. However, only 28 effective key bits are used, and the key is then also + * encrypted with itself and stored right after the encrypted IMEI, and is used + * by the decryption & verification routine. Per TI's source, the 16-byte + * encrypted IMEI record is to be stored in FFS in /gsm/imei.enc; the DP-L10 + * phone by Pirelli/Foxconn has been found to use the same scheme, but store + * the 16-byte record in question in their "factory block" instead, at absolute + * address 0x027F0504 as seen by the ARM7 CPU. + * + * The encryption scheme seems so weak to me (28 effective key bits and an easy + * hit detection criterion for a brute force cracker) that I decided to see, + * just for fun, how long it would take to crack that encryption by brute force + * alone, and using a totally non-optimized program to do that. + */ + +#include +#include +#include +#include + +DES_cblock ciphertext[2], dieid_key, decrypted[2]; +DES_key_schedule keysched; + +read_ciphertext(filename, offset_arg) + char *filename, *offset_arg; +{ + FILE *f; + u_long offset_val; + + f = fopen(filename, "r"); + if (!f) { + perror(filename); + exit(1); + } + if (offset_arg) { + offset_val = strtoul(offset_arg, 0, 16); + fseek(f, offset_val, 0); + } + fread(ciphertext, 8, 2, f); + fclose(f); +} + +print_des_cblock(msg, blk) + char *msg; + DES_cblock blk; +{ + printf("%s: %02X %02X %02X %02X %02X %02X %02X %02X\n", msg, + blk[0], blk[1], blk[2], blk[3], blk[4], blk[5], blk[6], blk[7]); +} + +try() +{ + DES_set_key_unchecked(&dieid_key, &keysched); + DES_ecb_encrypt(&ciphertext[1], &decrypted[1], &keysched, DES_DECRYPT); + if (decrypted[1][0] & 0xFE != dieid_key[0]) + return; + if (decrypted[1][1]) + return; + if (decrypted[1][2] & 0xFE != dieid_key[2]) + return; + if (decrypted[1][3]) + return; + if (decrypted[1][4] & 0xFE != dieid_key[4]) + return; + if (decrypted[1][5]) + return; + if (decrypted[1][6] & 0xFE != dieid_key[6]) + return; + if (decrypted[1][7]) + return; + print_des_cblock("Hit", &decrypted[1]); + DES_ecb_encrypt(&ciphertext[0], &decrypted[0], &keysched, DES_DECRYPT); + print_des_cblock("IMEI", &decrypted[0]); +} + +main(argc, argv) + char **argv; +{ + if (argc < 2 || argc > 3) { + fprintf(stderr, "usage: %s binfile [offset]\n", argv[0]); + exit(1); + } + read_ciphertext(argv[1], argv[2]); + dieid_key[1] = 0; + dieid_key[3] = 0; + dieid_key[5] = 0; + dieid_key[7] = 0; + for (dieid_key[0] = 0; dieid_key[0] <= 0xFE; dieid_key[0] += 2) + for (dieid_key[2] = 0; dieid_key[2] <= 0xFE; dieid_key[2] += 2) + for (dieid_key[4] = 0; dieid_key[4] <= 0xFE; dieid_key[4] += 2) + for (dieid_key[6] = 0; dieid_key[6] <= 0xFE; dieid_key[6] += 2) + try(); + exit(0); +}