Beispiel #1
0
def validate_heaps(db):
    """
    A simple routine that works like the built in windows
    heap checkers to show where blocks and/or freelist
    is potentially dorked.
    """
    trace = db.getTrace()
    db.vprint("Validating:")
    for heap in win32heap.getHeaps(trace):
        db.vprint("%s: 0x%.8x" % ("heap".rjust(9), heap.address))

        try:
            f = heap.getFreeLists()
        except Exception as e:
            db.vprint("%s: %s" % (e.__class__.__name__, e))

        for seg in heap.getSegments():
            db.vprint("%s: 0x%.8x" % ("segment".rjust(9), seg.address))
            try:
                blist = seg.getChunks()
                for i, chunk in enumerate(blist):
                    if i == 0:
                        continue
                    if heap._win7_heap:
                        continue
                    pchunk = blist[i - 1]
                    if chunk.chunk.PreviousSize != pchunk.chunk.Size:
                        db.vprint(
                            'Corruption! (block at 0x%.8x (size: %d) block at 0x%.8x (prevsize: %d)'
                            % (pchunk.address, pchunk.chunk.Size,
                               chunk.address, chunk.chunk.PreviousSize))
                        break

            except Exception as e:
                db.vprint("%s: %s" % (e.__class__.__name__, e))
Beispiel #2
0
def validate_heaps(db):
    """
    A simple routine that works like the built in windows
    heap checkers to show where blocks and/or freelist
    is potentially dorked.
    """
    trace = db.getTrace()
    db.vprint("Validating:")
    for heap in win32heap.getHeaps(trace):
        db.vprint("%s: 0x%.8x" % ("heap".rjust(9), heap.address))

        try:
            f = heap.getFreeLists()
        except Exception, e:
            #import traceback
            #traceback.print_exc()
            db.vprint("%s: %s" % (e.__class__.__name__,e))

        for seg in heap.getSegments():
            db.vprint("%s: 0x%.8x" % ("segment".rjust(9),seg.address))
            try:
                blist = seg.getChunks()
                for i,chunk in enumerate(blist):
                    if i == 0:
                        continue
                    if heap._win7_heap:
                        continue
                    pchunk = blist[i-1]
                    if chunk.chunk.PreviousSize != pchunk.chunk.Size:
                        db.vprint('Corruption! (block at 0x%.8x (size: %d) block at 0x%.8x (prevsize: %d)' % 
                                  (pchunk.address, pchunk.chunk.Size, chunk.address, chunk.chunk.PreviousSize))
                        break

            except Exception, e:
                db.vprint("%s: %s" % (e.__class__.__name__,e))
Beispiel #3
0
    def updateHeapTree(self, tree=None):
        if tree == None:
            tree = self.getWidget("Win32HeapTree")
        t = self.vdb.getTrace()
        model = tree.get_model()
        model.clear()
        if not t.isAttached():
            return

        # Populate the heap list
        for h in win32heap.getHeaps(t):
            #i = model.append(None, (h,"0x%.8x" % h.address,"0x%.8x" % int(h.heap.Flags),""))
            for s in h.getSegments():
                i = model.append(None, (s, "0x%.8x" % h.address,"0x%.8x" % s.address))
                model.append(i, (None, repr(h.heap), repr(s.seg)))
Beispiel #4
0
    def updateHeapTree(self, tree=None):
        if tree == None:
            tree = self.getWidget("Win32HeapTree")
        t = self.vdb.getTrace()
        model = tree.get_model()
        model.clear()
        if not t.isAttached():
            return

        # Populate the heap list
        for h in win32heap.getHeaps(t):
            #i = model.append(None, (h,"0x%.8x" % h.address,"0x%.8x" % int(h.heap.Flags),""))
            for s in h.getSegments():
                i = model.append(
                    None, (s, "0x%.8x" % h.address, "0x%.8x" % s.address))
                model.append(i, (None, repr(h.heap), repr(s.seg)))
Beispiel #5
0
def validate_heaps(db):
    """
    A simple routine that works like the built in windows
    heap checkers to show where blocks and/or freelist
    is potentially dorked.
    """
    trace = db.getTrace()
    db.vprint("Validating:")
    for heap in win32heap.getHeaps(trace):
        db.vprint("%s: 0x%.8x" % ("heap".rjust(9), heap.address))

        try:
            f = heap.getFreeLists()
        except Exception, e:
            db.vprint("%s: %s" % (e.__class__.__name__, e))

        for seg in heap.getSegments():
            db.vprint("%s: 0x%.8x" % ("segment".rjust(9), seg.address))
            try:
                blist = seg.getChunks()
            except Exception, e:
                db.vprint("%s: %s" % (e.__class__.__name__, e))
Beispiel #6
0
def validate_heaps(db):
    """
    A simple routine that works like the built in windows
    heap checkers to show where blocks and/or freelist
    is potentially dorked.
    """
    trace = db.getTrace()
    db.vprint("Validating:")
    for heap in win32heap.getHeaps(trace):
        db.vprint("%s: 0x%.8x" % ("heap".rjust(9), heap.address))

        try:
            f = heap.getFreeLists()
        except Exception, e:
            db.vprint("%s: %s" % (e.__class__.__name__,e))

        for seg in heap.getSegments():
            db.vprint("%s: 0x%.8x" % ("segment".rjust(9),seg.address))
            try:
                blist = seg.getChunks()
            except Exception, e:
                db.vprint("%s: %s" % (e.__class__.__name__,e))
Beispiel #7
0
            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)

    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:
Beispiel #8
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))
Beispiel #9
0
            chunklist_seg = t.parseExpression(optarg)

    if freelist_heap != None:
        print "NOT YET"

    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)

    else:
Beispiel #10
0
    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)

    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)
        for i, l in enumerate(heap.getLookAsideLists()):
            if len(l):
                vdb.vprint("Lookaside Index: %d" % i)
                for c in l:
                    vdb.vprint("    %s" % (repr(c)))

    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)
Beispiel #11
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))
Beispiel #12
0
        elif opt == "-L":
            chunklist_seg = t.parseExpression(optarg)

    if freelist_heap != None:
        print "NOT YET"

    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)

    else:
        vdb.vprint("Heap\t\tSegment")
        for heap in win32heap.getHeaps(t):