Example #1
0
    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)
Example #2
0
    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
Example #4
0
    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
Example #5
0
    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
Example #6
0
    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)
Example #7
0
    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)
Example #8
0
    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
Example #9
0
 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)
Example #10
0
 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)
Example #11
0
        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()
Example #12
0
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))
Example #13
0
    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))
Example #14
0
        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
Example #15
0
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))