css.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,697 行 · 第 1/4 页
C
1,697 行
free( BigTable ); return 0;}/***************************************************************************** * RecoverTitleKey: (title) key recovery from cipher and plain text * Function designed by Frank Stevenson ***************************************************************************** * Called from Attack* which are in turn called by CrackTitleKey. Given * a guessed(?) plain text and the cipher text. Returns -1 on failure. *****************************************************************************/static int RecoverTitleKey( int i_start, uint8_t const *p_crypted, uint8_t const *p_decrypted, uint8_t const *p_sector_seed, uint8_t *p_key ){ uint8_t p_buffer[10]; unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6; unsigned int i_try; unsigned int i_candidate; unsigned int i, j; int i_exit = -1; for( i = 0 ; i < 10 ; i++ ) { p_buffer[i] = p_css_tab1[p_crypted[i]] ^ p_decrypted[i]; } for( i_try = i_start ; i_try < 0x10000 ; i_try++ ) { i_t1 = i_try >> 8 | 0x100; i_t2 = i_try & 0xff; i_t3 = 0; /* not needed */ i_t5 = 0; /* iterate cipher 4 times to reconstruct LFSR2 */ for( i = 0 ; i < 4 ; i++ ) { /* advance LFSR1 normaly */ i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1]; i_t2 = i_t1 >> 1; i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4; i_t4 = p_css_tab5[i_t4]; /* deduce i_t6 & i_t5 */ i_t6 = p_buffer[i]; if( i_t5 ) { i_t6 = ( i_t6 + 0xff ) & 0x0ff; } if( i_t6 < i_t4 ) { i_t6 += 0x100; } i_t6 -= i_t4; i_t5 += i_t6 + i_t4; i_t6 = p_css_tab4[ i_t6 ]; /* feed / advance i_t3 / i_t5 */ i_t3 = ( i_t3 << 8 ) | i_t6; i_t5 >>= 8; } i_candidate = i_t3; /* iterate 6 more times to validate candidate key */ for( ; i < 10 ; i++ ) { i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1]; i_t2 = i_t1 >> 1; i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4; i_t4 = p_css_tab5[i_t4]; i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^ i_t3 ) >> 8 ) ^ i_t3 ) >> 5 ) & 0xff; i_t3 = ( i_t3 << 8 ) | i_t6; i_t6 = p_css_tab4[i_t6]; i_t5 += i_t6 + i_t4; if( ( i_t5 & 0xff ) != p_buffer[i] ) { break; } i_t5 >>= 8; } if( i == 10 ) { /* Do 4 backwards steps of iterating t3 to deduce initial state */ i_t3 = i_candidate; for( i = 0 ; i < 4 ; i++ ) { i_t1 = i_t3 & 0xff; i_t3 = ( i_t3 >> 8 ); /* easy to code, and fast enough bruteforce * search for byte shifted in */ for( j = 0 ; j < 256 ; j++ ) { i_t3 = ( i_t3 & 0x1ffff ) | ( j << 17 ); i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^ i_t3 ) >> 8 ) ^ i_t3 ) >> 5 ) & 0xff; if( i_t6 == i_t1 ) { break; } } } i_t4 = ( i_t3 >> 1 ) - 4; for( i_t5 = 0 ; i_t5 < 8; i_t5++ ) { if( ( ( i_t4 + i_t5 ) * 2 + 8 - ( (i_t4 + i_t5 ) & 7 ) ) == i_t3 ) { p_key[0] = i_try>>8; p_key[1] = i_try & 0xFF; p_key[2] = ( ( i_t4 + i_t5 ) >> 0 ) & 0xFF; p_key[3] = ( ( i_t4 + i_t5 ) >> 8 ) & 0xFF; p_key[4] = ( ( i_t4 + i_t5 ) >> 16 ) & 0xFF; i_exit = i_try + 1; } } } } if( i_exit >= 0 ) { p_key[0] ^= p_sector_seed[0]; p_key[1] ^= p_sector_seed[1]; p_key[2] ^= p_sector_seed[2]; p_key[3] ^= p_sector_seed[3]; p_key[4] ^= p_sector_seed[4]; } return i_exit;}/****************************************************************************** * Various pieces for the title crack engine. ****************************************************************************** * The length of the PES packet is located at 0x12-0x13. * The the copyrigth protection bits are located at 0x14 (bits 0x20 and 0x10). * The data of the PES packet begins at 0x15 (if there isn't any PTS/DTS) * or at 0x?? if there are both PTS and DTS's. * The seed value used with the unscrambling key is the 5 bytes at 0x54-0x58. * The scrabled part of a sector begins at 0x80. *****************************************************************************//* Statistics */static int i_tries = 0, i_success = 0;/***************************************************************************** * CrackTitleKey: try to crack title key from the contents of a VOB. ***************************************************************************** * This function is called by _dvdcss_titlekey to find a title key, if we've * chosen to crack title key instead of decrypting it with the disc key. * The DVD should have been opened and be in an authenticated state. * i_pos is the starting sector, i_len is the maximum number of sectors to read *****************************************************************************/static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, dvd_key_t p_titlekey ){ uint8_t p_buf[ DVDCSS_BLOCK_SIZE ]; const uint8_t p_packstart[4] = { 0x00, 0x00, 0x01, 0xba }; int i_reads = 0; int i_encrypted = 0; int b_stop_scanning = 0; int b_read_error = 0; int i_ret; print_debug( dvdcss, "cracking title key at block %i", i_pos ); i_tries = 0; i_success = 0; do { i_ret = dvdcss->pf_seek( dvdcss, i_pos ); if( i_ret != i_pos ) { print_error( dvdcss, "seek failed" ); } i_ret = dvdcss_read( dvdcss, p_buf, 1, DVDCSS_NOFLAGS ); /* Either we are at the end of the physical device or the auth * have failed / were not done and we got a read error. */ if( i_ret <= 0 ) { if( i_ret == 0 ) { print_debug( dvdcss, "read returned 0 (end of device?)" ); } else if( !b_read_error ) { print_debug( dvdcss, "read error at block %i, resorting to " "secret arcanes to recover", i_pos ); /* Reset the drive before trying to continue */ _dvdcss_close( dvdcss ); _dvdcss_open( dvdcss ); b_read_error = 1; continue; } break; } /* Stop when we find a non MPEG stream block. * (We must have reached the end of the stream). * For now, allow all blocks that begin with a start code. */ if( memcmp( p_buf, p_packstart, 3 ) ) { print_debug( dvdcss, "non MPEG block found at block %i " "(end of title)", i_pos ); break; } if( p_buf[0x0d] & 0x07 ) print_debug( dvdcss, "stuffing in pack header" ); /* PES_scrambling_control does not exist in a system_header, * a padding_stream or a private_stream2 (and others?). */ if( p_buf[0x14] & 0x30 && ! ( p_buf[0x11] == 0xbb || p_buf[0x11] == 0xbe || p_buf[0x11] == 0xbf ) ) { i_encrypted++; if( AttackPattern(p_buf, i_reads, p_titlekey) > 0 ) { b_stop_scanning = 1; }#if 0 if( AttackPadding(p_buf, i_reads, p_titlekey) > 0 ) { b_stop_scanning = 1; }#endif } i_pos++; i_len--; i_reads++; /* Emit a progress indication now and then. */ if( !( i_reads & 0xfff ) ) { print_debug( dvdcss, "at block %i, still cracking...", i_pos ); } /* Stop after 2000 blocks if we haven't seen any encrypted blocks. */ if( i_reads >= 2000 && i_encrypted == 0 ) break; } while( !b_stop_scanning && i_len > 0); if( !b_stop_scanning ) { print_debug( dvdcss, "end of title reached" ); } /* Print some statistics. */ print_debug( dvdcss, "successful attempts %d/%d, scrambled blocks %d/%d", i_success, i_tries, i_encrypted, i_reads ); if( i_success > 0 /* b_stop_scanning */ ) { print_debug( dvdcss, "vts key initialized" ); return 1; } if( i_encrypted == 0 && i_reads > 0 ) { memset( p_titlekey, 0, KEY_SIZE ); print_debug( dvdcss, "no scrambled sectors found" ); return 0; } memset( p_titlekey, 0, KEY_SIZE ); return -1;}/****************************************************************************** * The original Ethan Hawke (DeCSSPlus) attack (modified). ****************************************************************************** * Tries to find a repeating pattern just before the encrypted part starts. * Then it guesses that the plain text for first encrypted bytes are * a contiuation of that pattern. *****************************************************************************/static int AttackPattern( uint8_t const p_sec[ DVDCSS_BLOCK_SIZE ], int i_pos, uint8_t *p_key ){ unsigned int i_best_plen = 0; unsigned int i_best_p = 0; unsigned int i, j; /* For all cycle length from 2 to 48 */ for( i = 2 ; i < 0x30 ; i++ ) { /* Find the number of bytes that repeats in cycles. */ for( j = i + 1; j < 0x80 && ( p_sec[0x7F - (j%i)] == p_sec[0x7F - j] ); j++ ) { /* We have found j repeating bytes with a cycle length i. */ if( j > i_best_plen ) { i_best_plen = j; i_best_p = i; } } } /* We need at most 10 plain text bytes?, so a make sure that we * have at least 20 repeated bytes and that they have cycled at * least one time. */ if( ( i_best_plen > 3 ) && ( i_best_plen / i_best_p >= 2) ) { int res; i_tries++; memset( p_key, 0, KEY_SIZE ); res = RecoverTitleKey( 0, &p_sec[0x80], &p_sec[ 0x80 - (i_best_plen / i_best_p) * i_best_p ], &p_sec[0x54] /* key_seed */, p_key ); i_success += ( res >= 0 );#if 0 if( res >= 0 ) { fprintf( stderr, "key is %02x:%02x:%02x:%02x:%02x ", p_key[0], p_key[1], p_key[2], p_key[3], p_key[4] ); fprintf( stderr, "at block %5d pattern len %3d period %3d %s\n", i_pos, i_best_plen, i_best_p, (res>=0?"y":"n") ); }#endif return ( res >= 0 ); } return 0;}#if 0/****************************************************************************** * Encrypted Padding_stream attack. ****************************************************************************** * DVD specifies that there must only be one type of data in every sector. * Every sector is one pack and so must obviously be 2048 bytes long. * For the last pice of video data before a VOBU boundary there might not * be exactly the right amount of data to fill a sector. Then one has to * pad the pack to 2048 bytes. For just a few bytes this is done in the * header but for any large amount you insert a PES packet from the * Padding stream. This looks like 0x00 00 01 be xx xx ff ff ... * where xx xx is the length of the padding stream. *****************************************************************************/static int AttackPadding( uint8_t const p_sec[ DVDCSS_BLOCK_SIZE ], int i_pos, uint8_t *p_key ){ unsigned int i_pes_length; /*static int i_tries = 0, i_success = 0;*/ i_pes_length = (p_sec[0x12]<<8) | p_sec[0x13]; /* Coverd by the test below but usfull for debuging. */ if( i_pes_length == DVDCSS_BLOCK_SIZE - 0x14 ) return 0; /* There must be room for at least 4? bytes of padding stream, * and it must be encrypted. * sector size - pack/pes header - padding startcode - padding length */ if( ( DVDCSS_BLOCK_SIZE - 0x14 - 4 - 2 - i_pes_length < 4 ) || ( p_sec[0x14 + i_pes_length + 0] == 0x00 && p_sec[0x14 + i_pes_length + 1] == 0x00 && p_sec[0x14 + i_pes_length + 2] == 0x01 ) ) { fprintf( stderr, "plain %d %02x:%02x:%02x:%02x (type %02x sub %02x)\n", DVDCSS_BLOCK_SIZE - 0x14 - 4 - 2 - i_pes_length, p_sec[0x14 + i_pes_length + 0], p_sec[0x14 + i_pes_length + 1], p_sec[0x14 + i_pes_length + 2], p_sec[0x14 + i_pes_length + 3], p_sec[0x11], p_sec[0x17 + p_sec[0x16]]); return 0; } /* If we are here we know that there is a where in the pack a encrypted PES header is (startcode + length). It's never more than two packets in the pack, so we 'know' the length. The plaintext at offset (0x14 + i_pes_length) will then be 00 00 01 e0/bd/be xx xx, in the case of be the following bytes are also known. */ /* An encrypted SPU PES packet with another encrypted PES packet following. Normaly if the following was a padding stream that would be in plain text. So it will be another SPU PES packet. */ if( p_sec[0x11] == 0xbd && p_sec[0x17 + p_sec[0x16]] >= 0x20 && p_sec[0x17 + p_sec[0x16]] <= 0x3f ) { i_tries++; } /* A Video PES packet with another encrypted PES packet following. * No reason execpt for time stamps to break the data into two packets. * So it's likely that the following PES packet is a padding stream. */ if( p_sec[0x11] == 0xe0 ) { i_tries++; } if( 1 ) { /*fprintf( stderr, "key is %02x:%02x:%02x:%02x:%02x ", p_key[0], p_key[1], p_key[2], p_key[3], p_key[4] );*/ fprintf( stderr, "at block %5d padding len %4d " "type %02x sub %02x\n", i_pos, i_pes_length, p_sec[0x11], p_sec[0x17 + p_sec[0x16]]); } return 0;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?