148 lines
5.5 KiB
Python
Executable File
148 lines
5.5 KiB
Python
Executable File
#/usr/bin/env python
|
|
|
|
import getopt
|
|
import struct
|
|
import immutils
|
|
from immlib import *
|
|
|
|
copyright="(C) Immunity, Inc."
|
|
DESC = "Dumps Acrobat Reader Cache state"
|
|
|
|
class AdobeHeap:
|
|
def __init__(self,AcroPool):
|
|
'''
|
|
AcroManagingPool (hardcoded address depens on version of the AcroRd32.dll)
|
|
From this address it's possible to access all managing structures of their custom heap implementation.
|
|
'''
|
|
self.AcroPool = AcroPool
|
|
self.imm = Debugger()
|
|
self.pAcroCacheList = []
|
|
self.CacheHeadersInfo = []
|
|
self.AcroManagingPool()
|
|
|
|
def AcroManagingPool(self):
|
|
self.AcroPool += 0xC #Reserved
|
|
self.mem = self.imm.readMemory(self.AcroPool,128) #Managing structures for AcroCache
|
|
self.lpCacheManaging = struct.unpack("32L",self.mem)
|
|
self.AcroPool += (0x90 - 0xC) #Header of the first AcroBlock
|
|
self.FirstAcroBlock = self.imm.readLong(self.AcroPool)
|
|
|
|
def CacheManager(self,addr):
|
|
self.AcroPool = self.imm.readMemory(addr,0x10)
|
|
(pAcroPool,pFreeBlocksList,pAcroCacheList,blocksize) = struct.unpack("4L",self.AcroPool)
|
|
self.imm.log("pAcroPool: 0x%08x pFreeBlocksList: 0x%08x pAcroCacheList: 0x%08x blocksize: 0x%08x" % (pAcroPool,pFreeBlocksList,pAcroCacheList,\
|
|
blocksize), address = pAcroCacheList)
|
|
return pAcroCacheList
|
|
|
|
def CacheHeader(self,addr):
|
|
self.AcroPool = self.imm.readMemory(addr,0x18)
|
|
(pCacheManager,allocatedBlocks,flag,blink,flink,size) = struct.unpack("6L",self.AcroPool)
|
|
|
|
self.imm.log("CacheManager: 0x%08x AllocatedBlocks: 0x%08x Flags: 0x%08x BLINK: 0x%08x FLINK: 0x%08x Size: 0x%08x" % (pCacheManager,allocatedBlocks\
|
|
,flag,blink,flink,size), address = addr)
|
|
return flink
|
|
|
|
def walkCache(self,addr):
|
|
isAcroBlock = False
|
|
isCache = False
|
|
|
|
flag = self.imm.readLong(addr+0x8)
|
|
if flag == 2:
|
|
isAcroBlock = True
|
|
size = self.imm.readLong(addr+0x18)
|
|
elif flag == 0:
|
|
isCache = True
|
|
size = self.imm.readLong(addr+0x14)
|
|
self.imm.log("")
|
|
self.imm.log("***Walking through 0x%08x bytes cache***"%size)
|
|
|
|
i = 0
|
|
while 1:
|
|
Flink = self.imm.readLong(addr+0x10)
|
|
AllocatedBlocks = self.imm.readLong(addr+0x04)
|
|
AcroBlockSize = self.imm.readLong(addr+0x14)
|
|
if not Flink:
|
|
self.imm.log("***Walk Done***")
|
|
break
|
|
if isCache:
|
|
self.imm.log("Cache[%d]: 0x%08x | Allocated Blocks: [%d/128]" % (i,addr,AllocatedBlocks), address = addr)
|
|
elif isAcroBlock:
|
|
self.imm.log("AcroBlock: 0x%08x | Size: 0x08%x" % (Flink,AcroBlockSize), address = Flink)
|
|
addr = Flink
|
|
i += 1
|
|
|
|
def getCacheManagers(self):
|
|
self.imm.log("")
|
|
self.imm.log("CacheManagers List:")
|
|
i=0
|
|
for x in self.lpCacheManaging:
|
|
self.imm.log("lpCacheManaging[%d]: 0x%08x" % (i,x))
|
|
i += 1
|
|
|
|
def getCacheManagersInfo(self):
|
|
self.imm.log("")
|
|
self.imm.log("[Cache Managers Info]")
|
|
for x in self.lpCacheManaging:
|
|
self.pAcroCacheList.append(self.CacheManager(x))
|
|
|
|
def getCacheHeaders(self):
|
|
self.imm.log("")
|
|
self.imm.log("[Cache Headers]")
|
|
for x in self.pAcroCacheList:
|
|
try:
|
|
self.CacheHeadersInfo.append(self.CacheHeader(x))
|
|
except:
|
|
pass
|
|
|
|
def dumpCache(self):
|
|
self.getCacheManagers()
|
|
self.getCacheManagersInfo()
|
|
self.getCacheHeaders()
|
|
self.pAcroCacheList.pop(0) #unused entry
|
|
|
|
for x in self.pAcroCacheList:
|
|
self.walkCache(x)
|
|
|
|
def DumpAcroBlocks(self):
|
|
addr = self.FirstAcroBlock
|
|
self.AcroPool = self.imm.readMemory(addr,0x18)
|
|
(pAcroPool,reserved,flag,blink,flink,size) = struct.unpack("6L",self.AcroPool)
|
|
self.walkCache(flink)
|
|
|
|
|
|
def usage(imm):
|
|
imm.log("!acrocache")
|
|
imm.log(" -c Dump AcroCache state")
|
|
imm.log(" -f CACHEBLOCKADDR Follow CacheBlocks of same size and show allocations count")
|
|
imm.log(" -b Dump AcroBlocks")
|
|
|
|
def main(args):
|
|
imm = Debugger()
|
|
pAcroManagingPool = 0x014D38A0 #Acrobat Reader 9.4.0
|
|
|
|
try:
|
|
AcroManagingPool = imm.readLong(pAcroManagingPool)
|
|
except:
|
|
return "Couldn't read from AcroManagingPool pointer. Are you on Reader 9.4.0?"
|
|
adobe = AdobeHeap(AcroManagingPool)
|
|
|
|
|
|
if not args:
|
|
usage(imm)
|
|
try:
|
|
opts, argo = getopt.getopt(args, "bcf:")
|
|
except getopt.GetoptError:
|
|
usage(imm)
|
|
for o,a in opts:
|
|
if o == "-f":
|
|
try:
|
|
adobe.walkCache(int(a, 16))
|
|
except ValueError, msg:
|
|
return "Invalid address: %s" % a
|
|
if o == "-b":
|
|
adobe.DumpAcroBlocks()
|
|
if o == "-c":
|
|
adobe.dumpCache()
|
|
|
|
return "done"
|