/* ベクタ列挙内でオンになっているビットに当たる平文のペアを出力する。 */ void print_vector(char *vector) { int i, a, b, val; for(i=0; i < 9025; i++) { if(get_vector_bit(vector, i) == 1) { // ビットがオンである場合、 a = i / 95; // 平文のペアを b = i - (a * 95); // 算出し、 printf("%c%c ",a+32, b+32); // 出力する。 } } printf("\n"); }
// side-effect free from here on // note that bytes are sliced and unsliced with reversed endianness inline void crypto1_bs_convert_states(bitslice_t bitsliced_states[], state_t regular_states[]){ size_t bit_idx = 0, slice_idx = 0; state_t values[MAX_BITSLICES]; memset(values, 0x0, sizeof(values)); for(slice_idx = 0; slice_idx < MAX_BITSLICES; slice_idx++){ for(bit_idx = 0; bit_idx < STATE_SIZE; bit_idx++){ bool bit = get_vector_bit(slice_idx, bitsliced_states[bit_idx]); values[slice_idx].value <<= 1; values[slice_idx].value |= bit; } // swap endianness values[slice_idx].value = rev_state_t(values[slice_idx].value); // roll off unused bits values[slice_idx].value >>= ((sizeof(state_t)*8)-STATE_SIZE); } memcpy(regular_states, values, sizeof(values)); }
/* 生成された4char.ppmファイルを使用して4文字のパスワードを解読する。 */ int main(int argc, char *argv[]) { char *pass, plain[5]; unsigned char bin_vector1[WIDTH], bin_vector2[WIDTH], temp_vector[WIDTH]; char prob_vector1[2][9025]; char prob_vector2[2][9025]; int a, b, i, j, len, pv1_len=0, pv2_len=0; FILE *fd; if(argc < 1) barf("使用方法: %s <パスワードハッシュ>(4char.ppmファイルを使用)\n", argv[0]); if(!(fd = fopen("4char.ppm", "r"))) barf("エラー: PPM ファイルを読み込みモードでオープンできませんでした。\n", NULL); pass = argv[1]; // 最初の引数はパスワードハッシュ printf("最初の2文字に対して考えられる平文のバイトのフィルタリング:\n"); fseek(fd,(DCM*0)+enum_hashtriplet(pass[2], pass[3], pass[4])*WIDTH, SEEK_SET); fread(bin_vector1, WIDTH, 1, fd); // ハッシュの2-4バイト目に関連付けられたベクタを読み込む。 len = count_vector_bits(bin_vector1); printf("4つのベクタのうち1つのみ:\t%d 個の平文のペア(占有率は %0.2f%% )\n", len, len*100.0/9025.0); fseek(fd,(DCM*1)+enum_hashtriplet(pass[4], pass[5], pass[6])*WIDTH, SEEK_SET); fread(temp_vector, WIDTH, 1, fd); // ハッシュの4-6バイト目に関連付けられたベクタを読み込む。 merge(bin_vector1, temp_vector); // 最初のベクタに結合する。 len = count_vector_bits(bin_vector1); printf("ベクタ1と2は結合済み:\t%d 個の平文のペア(占有率は %0.2f%% )\n", len, len*100.0/9025.0); fseek(fd,(DCM*2)+enum_hashtriplet(pass[6], pass[7], pass[8])*WIDTH, SEEK_SET); fread(temp_vector, WIDTH, 1, fd); // ハッシュの6-8バイト目に関連付けられたベクタを読み込む。 merge(bin_vector1, temp_vector); // 最初の2つのベクタに結合する。 len = count_vector_bits(bin_vector1); printf("最初の3つのベクタは結合済み:\t%d 個の平文のペア(占有率は %0.2f%% )\n", len, len*100.0/9025.0); fseek(fd,(DCM*3)+enum_hashtriplet(pass[8], pass[9],pass[10])*WIDTH, SEEK_SET); fread(temp_vector, WIDTH, 1, fd); // ハッシュの8-10バイト目に関連付けられたベクタを読み込む。 merge(bin_vector1, temp_vector); // 他のベクタに結合する。 len = count_vector_bits(bin_vector1); printf("4つのベクタすべては結合済み:\t%d 個の平文のペア(占有率は %0.2f%% )\n", len, len*100.0/9025.0); printf("最初の2バイトに対して考えられる平文のペア:\n"); print_vector(bin_vector1); printf("\n最後の2文字に対して可能\な平文のフィルタリング:\n"); fseek(fd,(DCM*4)+enum_hashtriplet(pass[2], pass[3], pass[4])*WIDTH, SEEK_SET); fread(bin_vector2, WIDTH, 1, fd); // ハッシュの2-4バイト目に関連付けられたベクタを読み込む。 len = count_vector_bits(bin_vector2); printf("4つのベクタのうち1つのみ::\t%d 個の平文のペア(占有率は %0.2f%% )\n", len, len*100.0/9025.0); fseek(fd,(DCM*5)+enum_hashtriplet(pass[4], pass[5], pass[6])*WIDTH, SEEK_SET); fread(temp_vector, WIDTH, 1, fd); // ハッシュの4-6バイト目に関連付けられたベクタを読み込む。 merge(bin_vector2, temp_vector); // 最初のベクタに結合する。 len = count_vector_bits(bin_vector2); printf("ベクタ1と2は結合済み:\t%d 個の平文のペア(占有率は %0.2f%% )\n", len, len*100.0/9025.0); fseek(fd,(DCM*6)+enum_hashtriplet(pass[6], pass[7], pass[8])*WIDTH, SEEK_SET); fread(temp_vector, WIDTH, 1, fd); // ハッシュの6-8バイト目に関連付けられたベクタを読み込む。 merge(bin_vector2, temp_vector); // 最初の2つのベクタに結合する。 len = count_vector_bits(bin_vector2); printf("最初の3つのベクタは結合済み:\t%d 個の平文のペア(占有率は %0.2f%% )\n", len, len*100.0/9025.0); fseek(fd,(DCM*7)+enum_hashtriplet(pass[8], pass[9],pass[10])*WIDTH, SEEK_SET); fread(temp_vector, WIDTH, 1, fd); // ハッシュの8-10バイト目に関連付けられたベクタを読み込む。 merge(bin_vector2, temp_vector); // その他のベクタに結合する。 len = count_vector_bits(bin_vector2); printf("4つのベクタすべては結合済み:\t%d 個の平文のペア(占有率は %0.2f%% )\n", len, len*100.0/9025.0); printf("最後の2バイトについて考えられる平文のペア:\n"); print_vector(bin_vector2); printf("確率ベクタを作成中です...\n"); for(i=0; i < 9025; i++) { // 考えられる最初の2つの平文バイトを検索する。 if(get_vector_bit(bin_vector1, i)==1) {; prob_vector1[0][pv1_len] = i / 95; prob_vector1[1][pv1_len] = i - (prob_vector1[0][pv1_len] * 95); pv1_len++; } } for(i=0; i < 9025; i++) { // 考えられる最後の2つの平文バイトを検索する。 if(get_vector_bit(bin_vector2, i)) { prob_vector2[0][pv2_len] = i / 95; prob_vector2[1][pv2_len] = i - (prob_vector2[0][pv2_len] * 95); pv2_len++; } } printf("残る %d の可能\性を解読しています...\n", pv1_len*pv2_len); for(i=0; i < pv1_len; i++) { for(j=0; j < pv2_len; j++) { plain[0] = prob_vector1[0][i] + 32; plain[1] = prob_vector1[1][i] + 32; plain[2] = prob_vector2[0][j] + 32; plain[3] = prob_vector2[1][j] + 32; plain[4] = 0; if(strcmp(crypt(plain, "je"), pass) == 0) { printf("パスワード: %s\n", plain); i = 31337; j = 31337; } } } if(i < 31337) printf("パスワードの salt が 'je' でないか、長さが 4 桁ではありません。\n"); fclose(fd); }
/* 引き渡されたベクタ内における平文のペアの数を数える。 */ int count_vector_bits(char *vector) { int i, count=0; for(i=0; i < 9025; i++) count += get_vector_bit(vector, i); return count; }