# HG changeset patch # User Michael Spacefalcon # Date 1385685542 0 # Node ID 3f38da3933c27e9fa7f60aa105dbfa64b88c6ac6 # Parent d05b2e790e6b03799f5f124f0134c6713fb80bf5 Pirelli's IMEI obfuscation cracked! diff -r d05b2e790e6b -r 3f38da3933c2 .hgignore --- a/.hgignore Wed Nov 13 21:00:30 2013 +0000 +++ b/.hgignore Fri Nov 29 00:39:02 2013 +0000 @@ -4,6 +4,7 @@ ^factdiff$ ^mokosrec2bin$ +^pirimei$ ^mpffs/mpffs-cat$ ^mpffs/mpffs-dbgls$ diff -r d05b2e790e6b -r 3f38da3933c2 Makefile --- a/Makefile Wed Nov 13 21:00:30 2013 +0000 +++ b/Makefile Fri Nov 29 00:39:02 2013 +0000 @@ -1,14 +1,19 @@ CC= gcc CFLAGS= -O2 -PROGS= factdiff mokosrec2bin +STD= factdiff mokosrec2bin +NSTD= pirimei +PROGS= ${STD} ${NSTD} all: ${PROGS} -${PROGS}: +${STD}: ${CC} ${CFLAGS} -o $@ $@.c factdiff: factdiff.c mokosrec2bin: mokosrec2bin.c +pirimei: pirimei.c + ${CC} ${CFLAGS} -o $@ $@.c -lcrypto + clean: rm -f ${PROGS} *.o *errs *.out diff -r d05b2e790e6b -r 3f38da3933c2 pirimei.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pirimei.c Fri Nov 29 00:39:02 2013 +0000 @@ -0,0 +1,103 @@ +/* + * This program recovers the IMEI of a Pirelli DP-L10 phone from a dump of + * its factory block (last 64 KiB sector of the 2nd flash chip select) and + * the corresponding dieid file as written by fc-loadtool. + * + * The location of the 16-byte encrypted IMEI record within the factory block + * (at offset 0x504) has been figured out with the help of the factdiff.c + * program, and the magic decryption & verification algorithm has been found in + * g23m/condat/com/src/comlib/cl_imei.c in the Leonardo semi-src by Sotovik. + */ + +#include +#include +#include +#include +#include + +DES_cblock ciphertext[2], dieid_key, decrypted[2]; +DES_key_schedule keysched; + +read_ciphertext(filename) + char *filename; +{ + FILE *f; + + f = fopen(filename, "r"); + if (!f) { + perror(filename); + exit(1); + } + fseek(f, 0x504L, 0); + fread(ciphertext, 8, 2, f); + fclose(f); +} + +decode_hexdigit(ch) +{ + if (isdigit(ch)) + return(ch - '0'); + else if (isalpha(ch)) + return(ch - 'A' + 10); + else + return(ch - 'a' + 10); +} + +read_dieid_file(filename) + char *filename; +{ + FILE *f; + int i; + char lb[64]; + + f = fopen(filename, "r"); + if (!f) { + perror(filename); + exit(1); + } + for (i = 0; i < 4; i++) { + fgets(lb, sizeof lb, f); + if (!isxdigit(lb[0]) || !isxdigit(lb[1]) || !isxdigit(lb[2]) || + !isxdigit(lb[3]) || !isxdigit(lb[4]) || !isxdigit(lb[5]) || + !isxdigit(lb[6]) || !isxdigit(lb[7]) || + lb[8] != ':' || lb[9] != ' ' || + !isxdigit(lb[10]) || !isxdigit(lb[11]) || + !isxdigit(lb[12]) || !isxdigit(lb[13]) || lb[14] != '\n') { + fprintf(stderr, "%s, line %d: differs from expected\n", + filename, i + 1); + exit(1); + } + dieid_key[i*2] = (decode_hexdigit(lb[12]) << 4) | + decode_hexdigit(lb[13]); + dieid_key[i*2+1] = 0; + } + 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]); +} + +main(argc, argv) + char **argv; +{ + if (argc != 3) { + fprintf(stderr, "usage: %s fact.bin dieid\n", argv[0]); + exit(1); + } + read_ciphertext(argv[1]); + read_dieid_file(argv[2]); + print_des_cblock("Key derived from die ID", &dieid_key); + print_des_cblock("Ciphertext block 1", &ciphertext[0]); + print_des_cblock("Ciphertext block 2", &ciphertext[1]); + DES_set_key_unchecked(&dieid_key, &keysched); + DES_ecb_encrypt(&ciphertext[0], &decrypted[0], &keysched, DES_DECRYPT); + print_des_cblock("1st decrypted block", &decrypted[0]); + DES_ecb_encrypt(&ciphertext[1], &decrypted[1], &keysched, DES_DECRYPT); + print_des_cblock("2nd decrypted block", &decrypted[1]); + exit(0); +}