While developing an exploit for the Samba lsa_io_trans_names() heap overflow for the Mac OS X platform, we discovered that the szone_free() function has some interesting behavior.
The szone_free() function can be abused to overwrite one of the function pointers in the initial_malloc_zones structure and achieve arbitrary code execution. Exploitation is not straightforward, however, due to how the szone_free() function operates.
A partial disassembly of the szone_free() function can be found below:
<szone_free+2898>: mov %edi,0x8(%esi) <szone_free+2901>: mov 0x4(%esi),%eax <szone_free+2904>: xor %edi,%eax <szone_free+2906>: xor $0x357b,%eax <szone_free+2911>: mov %eax,(%esi) <szone_free+2913>: test %edi,%edi <szone_free+2915>: je 0x90005e8d <szone_free+2931> <szone_free+2917>: mov %esi,0x4(%edi) <szone_free+2920>: xor 0x8(%edi),%esi <szone_free+2923>: xor $0x357b,%esi <szone_free+2929>: mov %esi,(%edi)
This disassembly can be represented by the following C language code block:
*((int *)(esi+8)) = edi; eax = *((int *)(esi+4)); eax = edi ^ eax; eax = 0x357b ^ eax; *((int *)esi) = eax; *((int *)(edi+4)) = esi; esi = *((int *)(edi+8)) ^ esi; esi = 0x357b ^ esi; *((int *)edi) = esi;
This can be further simplified to:
*((int *)(esi+8)) = edi; *((int *)esi) = 0x357b ^ ( edi ^ *((int *)(esi+4)) ); *((int *)(edi+4)) = esi; *((int *)edi) = 0x357b ^ ( *((int *)(edi+8)) ^ esi );
As we can see, this code allows us to use the mov instructions at zone_free+2898 or szone_free+2917 to write to the initial_malloc_zones structure.
However, this code will also write the output of a sequence of xor operations to the addresses stored in the esi and edi registers. This will cause the initial four bytes of our target address to be overwritten with garbage instructions, resulting in an illegal instruction exception or segmentation fault.
To avoid a crash, we have to find a nop block that satisfies these conditions and results in a valid nop instruction being written to the beginning of our target address. After some calculations, we discovered that a nop block of 0x42 (incl %edx) and the address of 0x1800004 results in a xor output that is also a valid nop-like instruction:
0x357b ^ ( 0x1800004 ^ 0x42424242 ) = 0x43c2773d
This will result in the following instruction block being executed as the first few bytes of our target address (the 0x42 at the end is part of the nop block):
0: 3d 77 c2 43 42 cmpl $0x4243c277,%eax
Using this technique we can overwrite only the function pointers for the size() and malloc() routines in the initial_malloc_zones structure. Unfortunately, overwriting the malloc() pointer in this fashion leads to another problem.
If we use the mov intruction at szone_free+2898 (which implies the use of malloc() pointer) to write to the initial_malloc_zones structure, the caller will write the address 0x1800004 four bytes past our target address, resulting in following code block being executed:
0: 3d 77 c2 43 04 cmpl $0x443c277,%eax 5: 00 80 01 42 42 42 addb %al,0x42424201(%eax)
This will likely result in a segmentation fault, because the value of eax + 0x42424201 does not point to a valid memory location at the time of execution.
To avoid this problem we will need to use the mov instruction at szone_free+2917 (which implies the use of size() pointer) instead. When using the mov instruction at szone_free+2917, the address 0x1800004 will be written eight bytes past our target address, resulting in the following code block being executed:
0: 3d 77 c2 43 42 cmpl $0x4243c277,%eax 5: 42 incl %edx 6: 42 incl %edx 7: 42 incl %edx 8: 04 00 addb $0x0,%al a: 80 01 42 addb $0x42,(%ecx)
This code block satisfies all our requirements and will execute without problems because the ecx register points to valid and writable memory location (0x1800000 initial_malloc_zones) at the time of execution. Any shellcode appended to the end of this block will now be reached and executed.
This technique is useful for exploiting the Samba vulnerability, but may be useful for other heap overflows on the Mac OS X operating system. Please let us know if you have any comments, suggestions, or improvements.