def writeMemValue(self, addr, value, size): #FIXME change this (and all uses of it) to passing in format... #FIXME: Remove byte check and possibly half-word check. (possibly all but word?) mask = e_bits.u_maxes[size] bytes = e_bits.buildbytes(value & mask, size, self.getEndian()) self.writeMemory(addr, bytes)
def __init__(self, vw, logwrite=False, logread=False): self.vw = vw self.funcva = None # Set if using runFunction self.hooks = {} self.taints = {} self.taintva = itertools.count(0x41560000, 8192) self.uninit_use = {} self.logwrite = logwrite self.logread = logread self.path = self.newCodePathNode() self.curpath = self.path self.opcache = {} self.emumon = None self.psize = self.getPointerSize() self.stack_map_mask = e_bits.sign_extend(0xfff00000, 4, vw.psize) self.stack_map_base = e_bits.sign_extend(0xbfb00000, 4, vw.psize) self.stack_pointer = self.stack_map_base + 4096 # Possibly need an "options" API? self._safe_mem = True # Should we be forgiving about memory accesses? self._func_only = True # is this emulator meant to stay in one function scope? # Map in a memory map for the stack self.addMemoryMap(self.stack_map_base, 6, "[stack]", init_stack_map) # Map in all the memory associated with the workspace for va, size, perms, fname in vw.getMemoryMaps(): offset, bytes = vw.getByteDef(va) self.addMemoryMap(va, perms, fname, bytes) for regidx in self.taintregs: rname = self.getRegisterName(regidx) regval = self.setVivTaint('uninitreg', regidx) self.setRegister(regidx, regval) self.setStackCounter(self.stack_pointer) # Create some pre-made taints for positive stack indexes # NOTE: This is *ugly* for speed.... taints = [ self.setVivTaint('funcstack', i * self.psize) for i in xrange(20) ] taintbytes = ''.join( [e_bits.buildbytes(taint, self.psize) for taint in taints]) self.writeMemory(self.stack_pointer, taintbytes) for name in dir(self): val = getattr(self, name, None) if val == None: continue impname = getattr(val, '__imphook__', None) if impname == None: continue self.hooks[impname] = val
def __init__(self, vw, logwrite=False, logread=False): self.vw = vw self.funcva = None # Set if using runFunction self.emustop = False self.hooks = {} self.taints = {} self.taintva = itertools.count(0x41560000, 8192) self.uninit_use = {} self.logwrite = logwrite self.logread = logread self.path = self.newCodePathNode() self.curpath = self.path self.opcache = {} self.emumon = None self.psize = self.getPointerSize() self.stack_map_mask = e_bits.sign_extend(0xfff00000, 4, vw.psize) self.stack_map_base = e_bits.sign_extend(0xbfb00000, 4, vw.psize) self.stack_pointer = self.stack_map_base + 4096 # Possibly need an "options" API? self._safe_mem = True # Should we be forgiving about memory accesses? self._func_only = True # is this emulator meant to stay in one function scope? # Map in a memory map for the stack self.addMemoryMap(self.stack_map_base, 6, "[stack]", init_stack_map) # Map in all the memory associated with the workspace for va, size, perms, fname in vw.getMemoryMaps(): offset, bytes = vw.getByteDef(va) self.addMemoryMap(va, perms, fname, bytes) for regidx in self.taintregs: rname = self.getRegisterName(regidx) regval = self.setVivTaint( 'uninitreg', regidx ) self.setRegister(regidx, regval) self.setStackCounter(self.stack_pointer) # Create some pre-made taints for positive stack indexes # NOTE: This is *ugly* for speed.... taints = [ self.setVivTaint('funcstack', i * self.psize) for i in xrange(20) ] taintbytes = ''.join([ e_bits.buildbytes(taint,self.psize) for taint in taints ]) self.writeMemory(self.stack_pointer, taintbytes ) for name in dir(self): val = getattr(self, name, None) if val == None: continue impname = getattr(val, '__imphook__',None) if impname == None: continue self.hooks[impname] = val
def initStackMemory(self, stacksize=init_stack_size): ''' Setup and initialize stack memory. You may call this prior to emulating instructions. ''' if self.stack_map_base is None: self.stack_map_mask = e_bits.sign_extend(0xfff00000, 4, self.vw.psize) self.stack_map_base = e_bits.sign_extend(0xbfb00000, 4, self.vw.psize) self.stack_map_top = self.stack_map_base + stacksize self.stack_pointer = self.stack_map_top stack_map = init_stack_map if stacksize != init_stack_size: stack_map = b'\xfe' * stacksize # Map in a memory map for the stack self.addMemoryMap(self.stack_map_base, 6, "[stack]", stack_map) self.setStackCounter(self.stack_pointer) # Create some pre-made taints for positive stack indexes # NOTE: This is *ugly* for speed.... taints = [ self.setVivTaint('funcstack', i * self.psize) for i in range(20) ] taintbytes = b''.join( [e_bits.buildbytes(taint, self.psize) for taint in taints]) self.stack_pointer -= len(taintbytes) self.setStackCounter(self.stack_pointer) self.writeMemory(self.stack_pointer, taintbytes) else: existing_map_size = self.stack_map_top - self.stack_map_base new_map_size = stacksize - existing_map_size if new_map_size < 0: raise RuntimeError('cannot shrink stack') new_map_top = self.stack_map_base new_map_base = new_map_top - new_map_size stack_map = b''.join([ struct.pack('<I', new_map_base + (i * 4)) for i in range(new_map_size) ]) self.addMemoryMap(new_map_base, 6, "[stack]", stack_map) self.stack_map_base = new_map_base
def readMemory(self, va, size): if self.logread: rlog = vg_path.getNodeProp(self.curpath, 'readlog') rlog.append((self.getProgramCounter(), va, size)) # If they read an import entry, start a taint... loc = self.vw.getLocation(va) if loc != None: lva, lsize, ltype, ltinfo = loc if ltype == LOC_IMPORT and lsize == size: # They just read an import. ret = self.setVivTaint('import', loc) return e_bits.buildbytes(ret, lsize) self._useVirtAddr(va) # Read from the emulator's pages if we havent resolved it yet probeok = self.probeMemory(va, size, e_mem.MM_READ) if self._safe_mem and not probeok: return 'A' * size return e_mem.MemoryObject.readMemory(self, va, size)
def readMemory(self, va, size): if self.logread: rlog = vg_path.getNodeProp(self.curpath, 'readlog') rlog.append((self.getProgramCounter(),va,size)) # If they read an import entry, start a taint... loc = self.vw.getLocation(va) if loc != None: lva, lsize, ltype, ltinfo = loc if ltype == LOC_IMPORT and lsize == size: # They just read an import. ret = self.setVivTaint('import', loc) return e_bits.buildbytes(ret, lsize) self._useVirtAddr(va) # Read from the emulator's pages if we havent resolved it yet probeok = self.probeMemory(va, size, e_mem.MM_READ) if self._safe_mem and not probeok: return 'A' * size return e_mem.MemoryObject.readMemory(self, va, size)
def initStackMemory(self, stacksize=init_stack_size): ''' Setup and initialize stack memory. You may call this prior to emulating instructions. ''' if self.stack_map_base is None: self.stack_map_mask = e_bits.sign_extend(0xfff00000, 4, self.vw.psize) self.stack_map_base = e_bits.sign_extend(0xbfb00000, 4, self.vw.psize) self.stack_map_top = self.stack_map_base + stacksize self.stack_pointer = self.stack_map_top stack_map = init_stack_map if stacksize != init_stack_size: stack_map = b'\xfe' * stacksize # Map in a memory map for the stack self.addMemoryMap(self.stack_map_base, 6, "[stack]", stack_map) self.setStackCounter(self.stack_pointer) # Create some pre-made taints for positive stack indexes # NOTE: This is *ugly* for speed.... taints = [ self.setVivTaint('funcstack', i * self.psize) for i in xrange(20) ] taintbytes = ''.join([ e_bits.buildbytes(taint,self.psize) for taint in taints ]) self.writeMemory(self.stack_pointer, taintbytes) else: existing_map_size = self.stack_map_top - self.stack_map_base new_map_size = stacksize - existing_map_size if new_map_size < 0: raise RuntimeError('cannot shrink stack') new_map_top = self.stack_map_base new_map_base = new_map_top - new_map_size stack_map = ''.join([struct.pack('<I', new_map_base+(i*4)) for i in xrange(new_map_size)]) self.addMemoryMap(new_map_base, 6, "[stack]", stack_map) self.stack_map_base = new_map_base
def writeMemValue(self, addr, val, size): ''' Write a number from memory of the given size. ''' bytez = e_bits.buildbytes(val, size, self.getEndian()) return self.writeMemory(addr, bytez)
if leakfind_heap not in haddrs: vdb.vprint("0x%.8x is NOT a valid heap!" % leakfind_heap) return h = win32heap.Win32Heap(t, leakfind_heap) for seg in h.getSegments(): for chunk in seg.getChunks(): if chunk.address == seg.address: continue # Obviously, only check for leaks if they are in use... # FIXME we will need to check the lookaside also... if not chunk.isBusy(): continue addr = chunk.getDataAddress() # FIXME get size and endian from trace pat = e_bits.buildbytes(addr, 4) l = t.searchMemory(pat) if len(l) == 0: vdb.vprint("0x%.8x may be leaked!" % addr) else: vdb.vprint("Heap\t\tSegment") for heap in win32heap.getHeaps(t): flags = " ".join(heap.getFlagNames()) for s in heap.getSegments(): vdb.vprint("0x%.8x\t0x%.8x\t%s" % (heap.address, s.address, flags)) IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040 def showaslr(vdb, base, libname): t = vdb.getTrace()
def heaps(vdb, line): """ Show Win32 Heap Information. Usage: heaps [-F <heapaddr>] [-C <address>] [-L <segmentaddr>] -F <heapaddr> print the freelist for the heap -C <address> Find and print the heap chunk containing <address> -S <segmentaddr> Print the chunks for the given heap segment -L <heapaddr> Print the look aside list for the given heap -V Validate the heaps (check next/prev sizes and free list) -l <heapaddr> Leak detection (list probable leaked chunks) -U <heapaddr> Show un-commited ranges for the specified heap -b <heapaddr|all> Print LFH information for given heap or all (no options lists heaps and segments) """ t = vdb.getTrace() t.requireAttached() if t.getMeta('Architecture') == 'amd64': vdb.vprint("WARNING: not all 64bit heap stuff works quite right yet!") argv = e_cli.splitargs(line) freelist_heap = None chunkfind_addr = None chunklist_seg = None lookaside_heap = None leakfind_heap = None uncommit_heap = None buckets_heap = None try: opts, args = getopt.getopt(argv, "F:C:S:L:l:U:V:b:") except Exception: return vdb.do_help('heaps') for opt, optarg in opts: if opt == "-F": freelist_heap = t.parseExpression(optarg) elif opt == "-C": chunkfind_addr = t.parseExpression(optarg) elif opt == "-L": lookaside_heap = t.parseExpression(optarg) elif opt == "-S": chunklist_seg = t.parseExpression(optarg) elif opt == "-V": return validate_heaps(vdb) elif opt == "-l": leakfind_heap = t.parseExpression(optarg) elif opt == '-U': uncommit_heap = t.parseExpression(optarg) elif opt == '-b': if optarg == 'all': buckets_heap = 'all' else: buckets_heap = t.parseExpression(optarg) if lookaside_heap is not None: haddrs = [h.address for h in win32heap.getHeaps(t)] if lookaside_heap not in haddrs: vdb.vprint("0x%.8x is NOT a valid heap!" % lookaside_heap) return heap = win32heap.Win32Heap(t, lookaside_heap) vdb.vprint('[Index] [Chunks]') for i, l in enumerate(heap.getLookAsideLists()): vdb.vprint("[%d]" % i) for c in l: vdb.vprint(" %s" % (repr(c))) elif uncommit_heap is not None: haddrs = [h.address for h in win32heap.getHeaps(t)] if uncommit_heap not in haddrs: vdb.vprint("0x%.8x is NOT a valid heap!" % uncommit_heap) return heap = win32heap.Win32Heap(t, uncommit_heap) ucrdict = heap.getUCRDict() addrs = list(ucrdict.keys()) addrs.sort() if len(addrs) == 0: vdb.vprint('Heap 0x%.8x has 0 uncommited-ranges!' % uncommit_heap) return vdb.vprint('Uncommited ranges for heap: 0x%.8x' % uncommit_heap) for ucraddr in addrs: size = ucrdict.get(ucraddr) vdb.vprint('0x%.8x (%d)' % (ucraddr, size)) return elif freelist_heap is not None: haddrs = [h.address for h in win32heap.getHeaps(t)] if freelist_heap not in haddrs: vdb.vprint("0x%.8x is NOT a valid heap!" % freelist_heap) return heap = win32heap.Win32Heap(t, freelist_heap) for i, l in enumerate(heap.getFreeLists()): if len(l): vdb.vprint("Freelist Index: %d" % i) for c in l: vdb.vprint(" %s" % repr(c)) elif chunkfind_addr is not None: heap, seg, chunk = win32heap.getHeapSegChunk(t, chunkfind_addr) vdb.vprint("Address 0x%.8x found in:" % (chunkfind_addr, )) vdb.vprint("Heap: 0x%.8x" % (heap.address)) vdb.vprint("Segment: 0x%.8x" % (seg.address)) vdb.vprint("Chunk: 0x%.8x (%d) FLAGS: %s" % (chunk.address, len(chunk), chunk.reprFlags())) elif chunklist_seg is not None: for heap in win32heap.getHeaps(t): for seg in heap.getSegments(): if chunklist_seg == seg.address: vdb.vprint("Chunks for segment at 0x%.8x (X == in use)" % chunklist_seg) for chunk in seg.getChunks(): c = " " if chunk.isBusy(): c = "X" vdb.vprint("0x%.8x %s (%d)" % (chunk.address, c, len(chunk))) return vdb.vprint("Segment 0x%.8x not found!" % chunklist_seg) elif leakfind_heap is not None: # FIXME do this the slow way for now... haddrs = [h.address for h in win32heap.getHeaps(t)] if leakfind_heap not in haddrs: vdb.vprint("0x%.8x is NOT a valid heap!" % leakfind_heap) return h = win32heap.Win32Heap(t, leakfind_heap) for seg in h.getSegments(): for chunk in seg.getChunks(): if chunk.address == seg.address: continue # Obviously, only check for leaks if they are in use... # FIXME we will need to check the lookaside also... if not chunk.isBusy(): continue addr = chunk.getDataAddress() # FIXME get size and endian from trace pat = e_bits.buildbytes(addr, 4) l = t.searchMemory(pat) if len(l) == 0: vdb.vprint("0x%.8x may be leaked!" % addr) elif buckets_heap is not None: headers = '{0:10} {1:10} {2:10} {3:>8} {4:>8} {5:>8} {6:>8}'.format( 'Heap', 'SubSeg', 'UserData', 'Index', 'Size', 'Total', 'Free') vdb.vprint(headers) for heap in win32heap.getHeaps(t): if buckets_heap != heap.address and buckets_heap != 'all': continue if heap.isLFH(): lfh = heap.getLFH() for s in lfh.getSubsegments(): row = '{0:<#10x} {1:<#10x} {2:<#10x} {3:>#8x} {4:>#8x} {5:>#8x} {6:>#8x}'.format( heap.address, s.address, s.getUserBlocks(), s.getSizeIndex(), s.getBucketSize(), s.getBlockCount(), s.getFreeBlockCount()) vdb.vprint(row) else: row = '{0:<#10x} {1:<10} {2:^10} {3:>8} {4:>8} {5:>8} {5:>8}'.format( heap.address, 'No LFH', '-', '-', '-', '-') vdb.vprint(row) else: vdb.vprint("Heap\t\tSegment") for heap in win32heap.getHeaps(t): lfh = '' flags = " ".join(heap.getFlagNames()) if heap.isLFH(): lfh = 'LFH' for s in heap.getSegments(): vdb.vprint("0x%.8x\t0x%.8x\t%s\t%s" % (heap.address, s.address, flags, lfh))
def do_search(self, line): ''' search memory for patterns. search [options] <pattern> -e <codec> encode the pattern with a codec (hex, utf-16le, etc) -X pattern is in hex (ie. 41414242 is AABB) -E pattern is an envi memory expression (numeric search) -r pattern is a regular expression -R <baseexpr:sizeexpr> search a range of memory (base + size) -c show context (32 bytes) after each hit ''' parser = VOptionParser() parser.add_option('-e', action='store', dest='encode_as') parser.add_option('-X', action='store_true', dest='is_hex') parser.add_option('-E', action='store_true', dest='is_expr') parser.add_option('-r', action='store_true', dest='is_regex') parser.add_option('-R', action='store', dest='range_search') parser.add_option('-c', action='store_const', dest='num_context_bytes', const=32) argv = shlex.split(line) try: options, args = parser.parse_args(argv) except Exception as e: self.vprint(repr(e)) return self.do_help('search') pattern = (' '.join(args)).encode('utf-8') if len(pattern) == 0: self.vprint('you must specify a pattern') return self.do_help('search') if options.is_expr: sval = self.parseExpression(pattern) endian = self.memobj.getEndian() size = self.memobj.getPointerSize() pattern = e_bits.buildbytes(sval, size, bigend=endian) if options.is_hex: pattern = binascii.unhexlify(pattern) if options.encode_as is not None: if options.encode_as == 'hex': pattern = e_common.hexify(pattern) else: import codecs patternutf8 = pattern.decode('utf-8') pattern = codecs.encode(patternutf8, encoding=options.encode_as) if options.range_search: try: addrexpr, sizeexpr = options.range_search.split(":") except Exception as e: self.vprint(repr(e)) return self.do_help('search') addr = self.parseExpression(addrexpr) size = self.parseExpression(sizeexpr) self.canvas.addText('searching from ') self.canvas.addVaText('0x%.8x' % addr, addr) self.canvas.addText(' for %d bytes\n' % size) res = self.memobj.searchMemoryRange(pattern, addr, size, regex=options.is_regex) else: self.vprint('searching all memory...') res = self.memobj.searchMemory(pattern, regex=options.is_regex) if len(res) == 0: self.vprint('pattern not found: %s (%s)' % (e_common.hexify(pattern), repr(pattern))) return brend = e_render.ByteRend() self.vprint('matches for: %s (%s)' % (e_common.hexify(pattern), repr(pattern))) for va in res: mbase,msize,mperm,mfile = self.memobj.getMemoryMap(va) pname = e_mem.reprPerms(mperm) sname = self.reprPointer(va) self.canvas.addVaText('0x%.8x' % va, va) self.canvas.addText(': ') self.canvas.addText('%s ' % pname) self.canvas.addText(sname) if options.num_context_bytes is not None: self.canvas.addText('\n') self.canvas.renderMemory(va, options.num_context_bytes, rend=brend) self.canvas.addText('\n') self.vprint('done (%d results).' % len(res))
if leakfind_heap not in haddrs: vdb.vprint("0x%.8x is NOT a valid heap!" % leakfind_heap) return h = win32heap.Win32Heap(t, leakfind_heap) for seg in h.getSegments(): for chunk in seg.getChunks(): if chunk.address == seg.address: continue # Obviously, only check for leaks if they are in use... # FIXME we will need to check the lookaside also... if not chunk.isBusy(): continue addr = chunk.getDataAddress() # FIXME get size and endian from trace pat = e_bits.buildbytes(addr, 4) l = t.searchMemory(pat) if len(l) == 0: vdb.vprint("0x%.8x may be leaked!" % addr) else: vdb.vprint("Heap\t\tSegment") for heap in win32heap.getHeaps(t): flags = " ".join(heap.getFlagNames()) for s in heap.getSegments(): vdb.vprint("0x%.8x\t0x%.8x\t%s" % (heap.address, s.address, flags)) IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040
def heaps(vdb, line): """ Show Win32 Heap Information. Usage: heaps [-F <heapaddr>] [-C <address>] [-L <segmentaddr>] -F <heapaddr> print the freelist for the heap -C <address> Find and print the heap chunk containing <address> -S <segmentaddr> Print the chunks for the given heap segment -L <heapaddr> Print the look aside list for the given heap -V Validate the heaps (check next/prev sizes and free list) -l <heapaddr> Leak detection (list probable leaked chunks) -U <heapaddr> Show un-commited ranges for the specified heap -b <heapaddr|all> Print LFH information for given heap or all (no options lists heaps and segments) """ t = vdb.getTrace() t.requireAttached() if t.getMeta('Architecture') == 'amd64': vdb.vprint("WARNING: not all 64bit heap stuff works quite right yet!") argv = e_cli.splitargs(line) freelist_heap = None chunkfind_addr = None chunklist_seg = None lookaside_heap = None leakfind_heap = None uncommit_heap = None buckets_heap = None try: opts,args = getopt.getopt(argv, "F:C:S:L:l:U:V:b:") except Exception as e: return vdb.do_help('heaps') for opt,optarg in opts: if opt == "-F": freelist_heap = t.parseExpression(optarg) elif opt == "-C": chunkfind_addr = t.parseExpression(optarg) elif opt == "-L": lookaside_heap = t.parseExpression(optarg) elif opt == "-S": chunklist_seg = t.parseExpression(optarg) elif opt == "-V": return validate_heaps(vdb) elif opt == "-l": leakfind_heap = t.parseExpression(optarg) elif opt == '-U': uncommit_heap = t.parseExpression(optarg) elif opt == '-b': if optarg == 'all': buckets_heap = 'all' else: buckets_heap = t.parseExpression(optarg) if lookaside_heap != None: haddrs = [h.address for h in win32heap.getHeaps(t)] if lookaside_heap not in haddrs: vdb.vprint("0x%.8x is NOT a valid heap!" % lookaside_heap) return heap = win32heap.Win32Heap(t, lookaside_heap) vdb.vprint('[Index] [Chunks]') for i,l in enumerate(heap.getLookAsideLists()): vdb.vprint("[%d]" % i) for c in l: vdb.vprint(" %s" % (repr(c))) elif uncommit_heap != None: haddrs = [h.address for h in win32heap.getHeaps(t)] if uncommit_heap not in haddrs: vdb.vprint("0x%.8x is NOT a valid heap!" % uncommit_heap) return heap = win32heap.Win32Heap(t, uncommit_heap) ucrdict = heap.getUCRDict() addrs = list(ucrdict.keys()) addrs.sort() if len(addrs) == 0: vdb.vprint('Heap 0x%.8x has 0 uncommited-ranges!' % uncommit_heap) return vdb.vprint('Uncommited ranges for heap: 0x%.8x' % uncommit_heap) for ucraddr in addrs: size = ucrdict.get(ucraddr) vdb.vprint('0x%.8x (%d)' % (ucraddr, size)) return elif freelist_heap != None: haddrs = [h.address for h in win32heap.getHeaps(t)] if freelist_heap not in haddrs: vdb.vprint("0x%.8x is NOT a valid heap!" % freelist_heap) return heap = win32heap.Win32Heap(t, freelist_heap) for i,l in enumerate(heap.getFreeLists()): if len(l): vdb.vprint("Freelist Index: %d" % i) for c in l: vdb.vprint(" %s" % repr(c)) elif chunkfind_addr != None: heap,seg,chunk = win32heap.getHeapSegChunk(t, chunkfind_addr) vdb.vprint("Address 0x%.8x found in:" % (chunkfind_addr,)) vdb.vprint("Heap: 0x%.8x" % (heap.address)) vdb.vprint("Segment: 0x%.8x" % (seg.address)) vdb.vprint("Chunk: 0x%.8x (%d) FLAGS: %s" % (chunk.address, len(chunk),chunk.reprFlags())) elif chunklist_seg != None: for heap in win32heap.getHeaps(t): for seg in heap.getSegments(): if chunklist_seg == seg.address: vdb.vprint("Chunks for segment at 0x%.8x (X == in use)" % chunklist_seg) for chunk in seg.getChunks(): c = " " if chunk.isBusy(): c = "X" vdb.vprint("0x%.8x %s (%d)" % (chunk.address,c,len(chunk))) return vdb.vprint("Segment 0x%.8x not found!" % chunklist_seg) elif leakfind_heap != None: # FIXME do this the slow way for now... haddrs = [h.address for h in win32heap.getHeaps(t)] if leakfind_heap not in haddrs: vdb.vprint("0x%.8x is NOT a valid heap!" % leakfind_heap) return h = win32heap.Win32Heap(t, leakfind_heap) for seg in h.getSegments(): for chunk in seg.getChunks(): if chunk.address == seg.address: continue # Obviously, only check for leaks if they are in use... # FIXME we will need to check the lookaside also... if not chunk.isBusy(): continue addr = chunk.getDataAddress() # FIXME get size and endian from trace pat = e_bits.buildbytes(addr, 4) l = t.searchMemory(pat) if len(l) == 0: vdb.vprint("0x%.8x may be leaked!" % addr) elif buckets_heap != None: headers = '{0:10} {1:10} {2:10} {3:>8} {4:>8} {5:>8} {6:>8}'.format('Heap', 'SubSeg', 'UserData', 'Index', 'Size', 'Total', 'Free') vdb.vprint(headers) for heap in win32heap.getHeaps(t): if buckets_heap != heap.address and buckets_heap != 'all': continue if heap.isLFH(): lfh = heap.getLFH() for s in lfh.getSubsegments(): row = '{0:<#10x} {1:<#10x} {2:<#10x} {3:>#8x} {4:>#8x} {5:>#8x} {6:>#8x}'.format(heap.address, s.address, s.getUserBlocks(), s.getSizeIndex(), s.getBucketSize(), s.getBlockCount(), s.getFreeBlockCount()) vdb.vprint(row) else: row = '{0:<#10x} {1:<10} {2:^10} {3:>8} {4:>8} {5:>8} {5:>8}'.format(heap.address, 'No LFH', '-', '-', '-', '-') vdb.vprint(row) else: vdb.vprint("Heap\t\tSegment") for heap in win32heap.getHeaps(t): lfh = '' flags = " ".join(heap.getFlagNames()) if heap.isLFH(): lfh = 'LFH' for s in heap.getSegments(): vdb.vprint("0x%.8x\t0x%.8x\t%s\t%s" % (heap.address, s.address, flags, lfh))