view imeibrute.c @ 109:e40592990516

C156 boot code cracked
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 31 Mar 2014 19:06:33 +0000
parents 1e797f846563
children
line wrap: on
line source

/*
 * 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);
}