changeset 60:1e797f846563

imeibrute written
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Fri, 29 Nov 2013 01:39:31 +0000
parents 3f38da3933c2
children 2bc45eb8818d
files .hgignore Makefile imeibrute.c
diffstat 3 files changed, 107 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- 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$
 
--- 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
--- /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 <sys/types.h>
+#include <openssl/des.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+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);
+}