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.
Hopper Dissassembler 3.11.20
7.5 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
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]  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.
2016-10-13 - Vendor Disclosure
2016-10-14 - Patch Fixed
2016-10-18 - Public Release
Discovered by Tyler Bohan and Cory Duplantis of Cisco Talos.