Null pointer dereference vulnerability in the function be_uint32_read() – advancecomp-2.1

Loginsoft-2018-1049

February 13, 2019

CVE Number

CVE-2019-8379

CWE

CWE-476: NULL Pointer Dereference

Product Details

AdvanceCOMP contains recompression utilities for your .zip archives,.png images, .mng video clips and .gz files.
URL: https://sourceforge.net/projects/advancemame/

Vulnerable Versions

2.1

Vulnerability Details

During our research on advancecomp, we found null pointer dereference in this function be_uint32_read() located in endianrw.h. The same can be triggered by sending a crafted abc file to the binary. It allows an attacker to cause Denial of Service (Segmentation fault) or possibly have unspecified other impact when a victim opens a specially crafted file.

SYNOPSIS

As per our research the vulnerability exists in function be_uint32_read( ) at file endianrw.h . The function mng_print( ) takes the arguments as string and path which invokes the function png_print_chunk () takes a part of png data, while checking the switch case statement ,if the type value in switch case is at address 0x4d484452, When a crafted file is passed to the binary advmng while reading the data in function be_uint_read( ) at return (unsigned)ptr8[3] | (unsigned)ptr8[2] << 8 | (unsigned)ptr8[1] << 16 | (unsigned)ptr8[0] << 24;
The value of data in ptr is NULL which is of type pointer, while dereferencing to data the vulnerability Null pointer dereference is triggered.

Vulnerable code
switch (type) {
        case ADV_MNG_CN_MHDR :
       cout << " width:" << be_uint32_read(data+0) << " height:" << be_uint32_read(data+4) << " frequency:" << be_uint32_read(data+8);
return (unsigned)ptr8[3] | (unsigned)ptr8[2] << 8 | (unsigned)ptr8[1] << 16 | (unsigned)ptr8[0] << 24;
Analysis

 

198     return (unsigned)ptr8[3] | (unsigned)ptr8[2] << 8 | (unsigned)ptr8[1] << 16 | (unsigned)ptr8[0] << 24;
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ registers ]────
$rax   : 0x3               
$rbx   : 0x6567e0            →  0x00007ffff7bb4960  →  0x00007ffff7943c00  →  <std::basic_ostream mov rax, QWORD PTR [rip+0x272721]        # 0x7ffff7bb6328
$rcx   : 0x3a687464        
$rdx   : 0x7ffff7bb4960      →  0x00007ffff7943c00  →  <std::basic_ostream mov rax, QWORD PTR [rip+0x272721]        # 0x7ffff7bb6328
$rsp   : 0x7fffffffdb00      →  0x00007fffffffdb50  →  0x00007fffffffdc20  →  0x00007fffffffdc90  →  0x00007fffffffdd70  →  0x00007fffffffddc0  →  0x00000000004439e0  →   push r15
$rbp   : 0x7fffffffdb00      →  0x00007fffffffdb50  →  0x00007fffffffdc20  →  0x00007fffffffdc90  →  0x00007fffffffdd70  →  0x00007fffffffddc0  →  0x00000000004439e0  →   push r15
$rsi   : 0x0               
$rdi   : 0x0               
$rip   : 0x409372            →   movzx eax, BYTE PTR [rax]
$r8    : 0x7               
$r9    : 0x7ffff730b620      →  0x00000000fbad2a84
$r10   : 0x1               
$r11   : 0x1002            
$r12   : 0x4031c0            →   xor ebp, ebp
$r13   : 0x7fffffffdea0      →  0x000000000000000c
$r14   : 0x0               
$r15   : 0x0               
$eflags: [carry PARITY adjust zero sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$gs: 0x0000  $cs: 0x0033  $ss: 0x002b  $ds: 0x0000  $fs: 0x0000  $es: 0x0000  
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ stack ]────
0x00007fffffffdb00│+0x00: 0x00007fffffffdb50  →  0x00007fffffffdc20  →  0x00007fffffffdc90  →  0x00007fffffffdd70  →  0x00007fffffffddc0  →  0x00000000004439e0  →   push r15     ← $rsp, $rbp
0x00007fffffffdb08│+0x08: 0x0000000000409e79  →   mov esi, eax
0x00007fffffffdb10│+0x10: 0x0000000000000000
0x00007fffffffdb18│+0x18: 0x4d48445200000000
0x00007fffffffdb20│+0x20: 0x00007fffffffdb80  →  0x0000000000000000
0x00007fffffffdb28│+0x28: 0x000000000066ac50  →  0x0000000000000001
0x00007fffffffdb30│+0x30: 0x005244484dffdb50
0x00007fffffffdb38│+0x38: 0x27f2a27d5f1e4400
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ code:i386:x86-64 ]────
     0x409364  rex.RB call 0xfffffffff8861cb2
     0x40936a  mov    rax, QWORD PTR [rbp-0x8]
     0x40936e  add    rax, 0x3
 →   0x409372  movzx  eax, BYTE PTR [rax]
     0x409375  movzx  eax, al
     0x409378  mov    rdx, QWORD PTR [rbp-0x8]
     0x40937c  add    rdx, 0x2
     0x409380  movzx  edx, BYTE PTR [rdx]
     0x409383  movzx  edx, dl
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ source:lib/endianrw.h+198 ]────
    193  {
    194  #ifdef USE_MSB
    195     return cpu_uint32_read(ptr);
    196  #else
    197     const unsigned char* ptr8 = (const unsigned char*)ptr;
        // ptr8=0x00007fffffffdaf8  →  0x0000000000000000
 →  198     return (unsigned)ptr8[3] | (unsigned)ptr8[2] << 8 | (unsigned)ptr8[1] << 16 | (unsigned)ptr8[0] << 24;
    199  #endif
    200  }
    201  /*@}*/
    202  
    203  /** \name Write
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]────
[#0] Id 1, Name: "advmng", stopped, reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]────
[#0] 0x409372 → Name: be_uint32_read(ptr=0x0)
[#1] 0x409e79 → Name: png_print_chunk(type=0x4d484452, data=0x0, size=0x0)
[#2] 0x405c3b → Name: mng_print(path="/home/loginsoft/$POC")
[#3] 0x4077d4 → Name: list_all(argc=0x1, argv=0x7fffffffdf00)
[#4] 0x40861e → Name: process(argc=0xc, argv=0x7fffffffdea8)
[#5] 0x40895e → Name: main(argc=0xc, argv=0x7fffffffdea8)
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Tested environment

64-bit ubuntu 16.04 LTS

Proof of Concept

- advmng -l -0 -1 -2 -3 -4 -i 8 -r -e $POC

Timeline

Vendor Disclosure: 03-01-2019
Public Disclosure: 13-02-2019

Credit

Discovered by ACE Team – Loginsoft