changeset 59:3f38da3933c2

Pirelli's IMEI obfuscation cracked!
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Fri, 29 Nov 2013 00:39:02 +0000
parents d05b2e790e6b
children 1e797f846563
files .hgignore Makefile pirimei.c
diffstat 3 files changed, 111 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- 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$
--- 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
--- /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 <sys/types.h>
+#include <openssl/des.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+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);
+}