Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
VLC_CVE-2021-25804_Analysis — CVE-2021-25804, VLC AVI 파서 취약점에 대한 심층 기술 분석. 근본 원인, 패치 차이(diff), 그리고 보안 연구자를 위한 익스플로잇 기본 요소를 포함합니다. | Kitploit
도구/GitHubGitHub/dshankle/vlc_cve-2021-25804_analysis
Vulnerability AnalysisCode AnalysisExploitationBinary AnalysisPapers & ResearchLearning & Education
GitHubdshankle/vlc_cve-2021-25804_analysis

VLC_CVE-2021-25804_Analysis

CVE-2021-25804, VLC AVI 파서 취약점에 대한 심층 기술 분석. 근본 원인, 패치 차이(diff), 그리고 보안 연구자를 위한 익스플로잇 기본 요소를 포함합니다.

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
저장소 보기
3년 전아직 검토되지 않음

AVI 파일은 여러 개의 트랙을 가질 수 있습니다. 예를 들어 오디오 트랙과 비디오 트랙이 있습니다.

임의 개수의 트랙을 파싱하려면 VLC는 먼저 주어진 트랙이 완료되었고 재생 가능한지 확인해야 합니다. 이를 위해 두 개의 변수가 설정됩니다. 둘 다 이름이 i_track입니다.

변수 p_sys는 우리의 목적에 있어 avi 파일을 나타냅니다. 따라서 완료되고 재생 가능한 트랙을 참조하는 데 사용되는 "공식" i_track 변수는 p_sys->i_track입니다. 이 변수는 다음 매크로로 초기화됩니다:

root@kitploit:~
```
TAB_INIT(p_sys->i_track, p_sys->track);
//#define TAB_INIT( count, tab ) do {(count) = 0; (tab) = NULL; } while(0)
```

한편, 두 번째 i_track 변수는 완료/재생 가능 여부와 관계없이 모든 트랙을 세기 위해 설정됩니다.

root@kitploit:~
```
i_track = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl, true );
```

두 번째 i_track은 'strl'로 시작하는 모든 청크를 나타냅니다. 이 변수는 일련의 검사를 통과한 경우에만 p_sys->i_track 변수를 설정하는 'for' 루프를 제어합니다:

root@kitploit:~
```
for( unsigned i = 0 ; i < i_track; i++ )
{
    ...

TAB_APPEND( p_sys->i_track, p_sys->track, tk );
//#define TAB_APPEND( count, tab, p ) {TAB_APPEND_CAST( , count, tab, p )}
//TAB_APPEND_CAST( ,p_sys->i_track, p_sys->track, tk)
        //if( (count) > 0 ) (tab) = cast realloc( tab, sizeof( *(tab) ) * ( (count) + 1 ) ); 
        //else  (tab) = cast malloc( sizeof( *(tab) ) );    
        //if( !(tab) ) abort();                       
        //(tab)[count] = (p);                         
        //(count)++; //p_sys->i_track incremented here
}
```

이후의 'for' 루프에서 p_sys->i_track 변수는 AVI_ChunkFind 호출 시 청크 번호로 사용됩니다. 이 함수는 주어진 FOURCC 청크 값과 일치하는 n번째 청크를 반환하며, 여기서는 'strl'입니다:

root@kitploit:~
```
for( unsigned i = 0 ; i < p_sys->i_track; i++ )
{
    avi_track_t         *tk = p_sys->track[i];

    if( tk->fmt.i_cat != AUDIO_ES ||
        tk->idx.i_size < 1 ||
        tk->i_scale != 1 ||
        tk->i_samplesize != 0 )
        continue;
        
    //CVE-2021-25804
    avi_chunk_list_t *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i, true );
    //subsequently changed to: avi_chunk_list_t *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, tk->fmt.i_id, true );

    avi_chunk_strf_t *p_strf = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0, false );
    if( !p_strf || p_strf->i_cat != AUDIO_ES )
        continue;

    const WAVEFORMATEX *p_wf = p_strf->u.p_wf;
```

p_sys->i_track은 완료된 트랙의 올바른 개수를 세지만, 어떤 청크 번호로 설정되었는지는 추적하지 않습니다. 즉, 유효한 strl 청크 앞에 유효하지 않은 strl 청크가 있는 경우, 첫 번째 청크는 트랙 객체를 설정할 때 올바르게 무시되지만 ChunkFind가 호출되면 여전히 첫 번째 유효하지 않은 청크를 선택하게 됩니다.

CVE-2021-25804가 생성된 후, ChunkFind의 청크 번호 변수를 i에서 tk->fmt.i_id로 변경하여 문제가 패치되었습니다. tk->fmt.i_id는 앞서 살펴본 TAB_APPEND() 호출 바로 위에서 처음 설정됩니다:

root@kitploit:~
```
tk->fmt.i_id = i;

if( p_strn && p_strn->p_str )
    tk->fmt.psz_description = FromACP( p_strn->p_str );
//see es_format_truncated.c 
tk->p_es = es_out_Add( p_demux->out, &tk->fmt );


TAB_APPEND( p_sys->i_track, p_sys->track, tk );
```

tk->fmt.i_id가 i로 설정되어 완료된 청크가 ChunkFind()에서 선택되어야 하므로 이 문제가 해결된 것처럼 보입니다. 그러나 테스트 결과 문제가 되는 ChunkFind() 호출 시점에 tk->fmt.i_id 값이 실제로 -1로 설정되어 있음이 밝혀졌습니다. 이는 es_format_Init() 호출 중에 설정된 초기화 값입니다:

root@kitploit:~
```
void es_format_Init( es_format_t *fmt,
                 int i_cat, vlc_fourcc_t i_codec )
{
    memset(fmt, 0, sizeof (*fmt));
    fmt->i_cat                  = i_cat;
    fmt->i_codec                = i_codec;
    fmt->i_profile              = -1;
    fmt->i_level                = -1;
    fmt->i_id                   = -1;
    fmt->i_priority             = ES_PRIORITY_SELECTABLE_MIN;
    fmt->psz_language           = NULL;
    fmt->psz_description        = NULL;
    fmt->p_extra_languages      = NULL;

    if (fmt->i_cat == VIDEO_ES)
        video_format_Init(&fmt->video, 0);

    fmt->b_packetized           = true;
    fmt->p_extra                = NULL;
}

```

이 초기화는 fmt->i_id가 i로 설정되는 것과 동일한 'for' 루프에서 발생합니다.

root@kitploit:~
```
    for( unsigned i = 0 ; i < i_track; i++ )
{
    ...
     switch( p_strh->i_type )
    {
        case( AVIFOURCC_auds ):
        {
            es_format_Init( &tk->fmt, AUDIO_ES, 0 );
            ...
        }
            ...
    }
    tk->fmt.i_id = i;

    if( p_strn && p_strn->p_str )
        tk->fmt.psz_description = FromACP( p_strn->p_str );

    tk->p_es = es_out_Add( p_demux->out, &tk->fmt );

    TAB_APPEND( p_sys->i_track, p_sys->track, tk );
}

```
도구 다운로드