Talos Vulnerability Report

TALOS-2016-0222

Hopper Disassembler ELF Section Header Size Code Execution Vulnerability

October 18, 2016
CVE Number

CVE-2016-8390

Summary

An exploitable out of bounds write vulnerability exists in the parsing of ELF Section Headers of Hopper App. A specially crafted ELF file can cause attacker controlled pointer arithmetic resulting in a partially controlled out of bounds write. An attacker can craft an ELF file with sepecific section headers to trigger this vulnerability.

Tested Versions

Hopper Dissassembler 3.11.20

Product URLs

https://www.hopperapp.com/

CVSSv3 Score

7.5 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H

Details

Hopper is a popular disassembler used for analysis of disassembly of various binary formats. During the parsing of ELF section headers, there is a user controlled size passed in that is not validated to be correct. This is then used later, causing the program to access memory out of bounds and leads to the vulnerable conditon.

There are two initial crashes shown below:

RAX: 0x7fffbaf9fab0 --> 0x101000101010100
R14: 0xb16b00b5

   0x7ffff65c96ac:    movzx  ecx,al
   0x7ffff65c96af:    mov    r14d,r15d ; user_controlled_int
   0x7ffff65c96b2:    mov    rax,QWORD PTR [rbp-source_buffer]
=> 0x7ffff65c96b9:    cmp    BYTE PTR [rax+r14*1],0x0



RAX: 0x80003811d825

  0x7ffff3491d06 <strlen+22>:    and    rcx,0xfff
  0x7ffff3491d0d <strlen+29>:    cmp    rcx,0xfcf
  0x7ffff3491d14 <strlen+36>:    ja     0x7ffff3491d80 <strlen+144>
=> 0x7ffff3491d16 <strlen+38>:    movdqu xmm4,XMMWORD PTR [rax]

Here we see the program is crashing on a null check ensuring the supplied value is not 0 and in another scenario it is crashing due to an invalid string being passed into strlen. After some reversing we can detect where the r14 value has come from and can also determine what is causing the out of bounds access in the second crash

call    [rbp+var_2328]  ; readint64
mov     [rbp+user_controlled_64int], rax

We can see this value is an int which is read in directly from the program itself and then used without any validation. This 64-bit value is actually read from the binary’s section header table and is easily controlled by the attacker. Below is an example section header with the relevant pieces changed.

idx=26 vaddr=0xffffffffbad0c0de paddr=0x000010a0 sz=36 vsz=36 perm=----- name=.comment
…
idx=42 vaddr=0x00000000 paddr=0xffffffffdefeca7e sz=0 vsz=0 perm=m-rw- name=GNU_STACK
idx=43 vaddr=0x00600e10 paddr=0x00000e10 sz=1004211380129038336 vsz=0 perm=m-r-- name=GNU_RELRO

Now investigating the second crashing point we can see that our arbitrary value is used to calculate out the pointer to be passed into a string function. If this value is pointing out of bounds the strlen crash occurs.

add     rdx, [rbp+user_controlled_64int]
add     rdx, [rbp+var_2330] [1]
mov     rdi, rax
lea     rsi, off_1A55220
call    _objc_msgSend ; "stringWithUTF8String:"

We see that this function is attempting to copy the provided attacker controlled string into another buffer in memory. Knowing this we can see that we can point this string anywhere in the program and copy arbitray contents creating an out of bounds write scenario. This could then be leveraged by an attacker to potentially gain remote code exection later in the program.

Timeline

2016-10-13 - Vendor Disclosure
2016-10-14 - Patch Fixed
2016-10-18 - Public Release

Credit

Discovered by Tyler Bohan and Cory Duplantis of Cisco Talos.