⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 css.c

📁 python的多媒体包,可以实现很多漂亮的功能哦
💻 C
📖 第 1 页 / 共 4 页
字号:
 * 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 pices 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;

    _dvdcss_debug( dvdcss, "cracking title key" );

    i_tries = 0;
    i_success = 0;

    do
    {
        i_ret = dvdcss->pf_seek( dvdcss, i_pos );

        if( i_ret != i_pos )
        {
            _dvdcss_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 )
            {
                _dvdcss_debug( dvdcss, "read returned 0 (end of device?)" );
            }
            else if( !b_read_error )
            {
                _dvdcss_debug( dvdcss, "read error, resorting to secret "
                                       "arcanes to recover" );

                /* 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 ) )
        {
            _dvdcss_debug( dvdcss, "non MPEG block found (end of title)" );
            break;
        }

        if( p_buf[0x0d] & 0x07 )
            _dvdcss_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 ) )
        {
            _dvdcss_debug( dvdcss, "still cracking..." );
        }

        /* 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 )
    {
        _dvdcss_debug( dvdcss, "end of title reached" );
    }

    { /* Print some statistics. */
        char psz_info[128];
        snprintf( psz_info, sizeof(psz_info),
                  "%d of %d attempts successful, %d of %d blocks scrambled",
                  i_success, i_tries, i_encrypted, i_reads );
        _dvdcss_debug( dvdcss, psz_info );
    }

    if( i_success > 0 /* b_stop_scanning */ )
    {
        _dvdcss_debug( dvdcss, "vts key initialized" );
        return 1;
    }

    if( i_encrypted == 0 && i_reads > 0 )
    {
        memset( p_titlekey, 0, KEY_SIZE );
        _dvdcss_debug( dvdcss, "file was unscrambled" );
        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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -