Esempio n. 1
0
def help():
    """Details about the commands provided by shadow"""

    print("\n[shadow] De Mysteriis Dom Firefox")
    print("[shadow] shadow %s" % (VERSION))
    print("[shadow] Firefox v%s (%s)\n" % (xul_version, dbg.get_arch()))
    print("[shadow] jemalloc-specific commands:")
    print("[shadow]   jechunks                : dump info on all available chunks")
    print("[shadow]   jearenas                : dump info on jemalloc arenas")
    print("[shadow]   jerun <address>         : dump info on a single run")
    print("[shadow]   jeruns [-cs]            : dump info on jemalloc runs")
    print("[shadow]                                 -c : current runs only")
    print("[shadow]                    -s <size class> : runs for the given size class only")
    print("[shadow]   jebins                  : dump info on jemalloc bins")
    print("[shadow]   jeregions <size class>  : dump all current regions of the given size class")
    print("[shadow]   jesearch [-cfqs] <hex>  : search the heap for the given hex dword")
    print("[shadow]                                 -c : current runs only")
    print("[shadow]                                 -q : quick search (less details)")
    print("[shadow]                    -s <size class> : regions of the given size only")
    print("[shadow]                                 -f : search for filled region holes")
    print("[shadow]   jeinfo <address>        : display all available details for an address")
    print("[shadow]   jedump [filename]       : dump all available jemalloc info to screen (default) or file")
    print("[shadow]   jeparse                 : parse jemalloc structures from memory")
    print("[shadow] Firefox-specific commands:")
    print("[shadow]   nursery                 : display info on the SpiderMonkey GC nursery")
    print("[shadow]   symbol [-vjdx] <size>   : display all Firefox symbols of the given size")
    print("[shadow]                                 -v : only class symbols with vtable")
    print("[shadow]                                 -j : only symbols from SpiderMonkey")
    print("[shadow]                                 -d : only DOM symbols")
    print("[shadow]                                 -x : only non-SpiderMonkey symbols")
    print("[shadow]   pa <address> [<length>] : modify the ArrayObject's length (default new length 0x666)")
    print("[shadow] Generic commands:")
    print("[shadow]   version                 : output version number")
    print("[shadow]   help                    : this help message")
Esempio n. 2
0
def help():
    '''Details about the commands provided by shadow'''

    print('\n[shadow] De Mysteriis Dom jemalloc')
    print('[shadow] shadow %s' % (VERSION))
    print('[shadow] Firefox v%s (%s)\n' % (xul_version, dbg.get_arch()))
    print('[shadow] jemalloc-specific commands:')
    print('[shadow]   jechunks                : dump info on all available chunks')
    print('[shadow]   jearenas                : dump info on jemalloc arenas')
    print('[shadow]   jerun <address>         : dump info on a single run')
    print('[shadow]   jeruns [-cs]            : dump info on jemalloc runs')
    print('[shadow]                                 -c : current runs only')
    print('[shadow]                    -s <size class> : runs for the given size class only')
    print('[shadow]   jebins                  : dump info on jemalloc bins')
    print('[shadow]   jeregions <size class>  : dump all current regions of the given size class')
    print('[shadow]   jesearch [-cfqs] <hex>  : search the heap for the given hex dword')
    print('[shadow]                                 -c : current runs only')
    print('[shadow]                                 -q : quick search (less details)')
    print('[shadow]                    -s <size class> : regions of the given size only')
    print('[shadow]                                 -f : search for filled region holes')
    print('[shadow]   jeinfo <address>        : display all available details for an address')
    print('[shadow]   jedump [filename]       : dump all available jemalloc info to screen (default) or file')
    print('[shadow]   jeparse                 : parse jemalloc structures from memory')
    print('[shadow] Firefox-specific commands:')
    print('[shadow]   nursery                 : display info on the SpiderMonkey GC nursery')
    print('[shadow]   symbol [-vjdx] <size>   : display all Firefox symbols of the given size')
    print('[shadow]                                 -v : only class symbols with vtable')
    print('[shadow]                                 -j : only symbols from SpiderMonkey')
    print('[shadow]                                 -d : only DOM symbols')
    print('[shadow]                                 -x : only non-SpiderMonkey symbols')
    print('[shadow]   pa <address> [<length>] : modify the ArrayObject\'s length (default new length 0x666)')
    print('[shadow] Generic commands:')
    print('[shadow]   version                 : output version number')
    print('[shadow]   help                    : this help message')
Esempio n. 3
0
def firefox_version():
    """Output Firefox's version we are attached to"""

    global xul_version
    print("[shadow] Firefox v%s (%s)" % (xul_version, dbg.get_arch()))
Esempio n. 4
0
def parse_chunks():
    global jeheap
    global dbg_engine

    # delete the chunks' list
    jeheap.chunks[:] = []

    try:
        root = dbg.to_int(dbg.eval_expr(dbg.chunk_rtree_root_expr))
        height = dbg.to_int(dbg.eval_expr(dbg.chunk_rtree_height_expr))

        level2bits = []

        for i in range(0, height):
            expr = dbg.chunk_rtree_level2bits_expr % (i)
            level2bits.append(dbg.to_int(dbg.eval_expr(expr)))
    except:
        print("[shadow] error: cannot parse chunk radix tree")
        sys.exit()

    # XXX: check if we're running on x86_64,
    #      not required for windbg/pykd (see the dp command)
    if jeheap.DWORD_SIZE == 8:
        if dbg_engine == "gdb":
            dw_fmt = "g"
        else:  # lldb
            dw_fmt = "XXX"
    else:
        if dbg_engine == "gdb":
            dw_fmt = "w"
        else:  # lldb
            dw_fmt = "XXX"

    # parse the radix tree using a stack
    stack = [(root, 0)]
    while len(stack):
        (node, node_height) = stack.pop()
        child_cnt = 1 << level2bits[node_height]

        if dbg_engine == "gdb":
            expr = dbg.chunk_radix_expr % (child_cnt, dw_fmt, node)
        elif dbg_engine == "pykd":
            if dbg.get_arch() == "x86":
                child_cnt = child_cnt / 6

            expr = dbg.chunk_radix_expr % (node, child_cnt)
        else:  # lldb
            expr = ""

        dump = dbg.execute(expr)

        for line in dump.split("\n"):

            line = line[line.find(dbg.address_separator) + len(dbg.address_separator) :]

            for address in line.split():
                try:
                    address = int(address, 16)
                except:
                    address = 0

                if address != 0:
                    # leaf nodes hold pointers to actual values
                    if node_height == height - 1:
                        expr = dbg.chunk_arena_expr % address

                        try:
                            arena_addr = dbg.to_int(dbg.eval_expr(expr))
                        except:
                            arena_addr = 0

                        exists = false

                        if arena_addr in [i.addr for i in jeheap.arenas]:
                            exists = true

                        if exists:
                            jeheap.chunks.append(jemalloc.arena_chunk(address, arena_addr))
                        else:
                            jeheap.chunks.append(jemalloc.arena_chunk(address))

                    # non-leaf nodes are inserted in the stack
                    else:
                        stack.append((address, node_height + 1))
Esempio n. 5
0
def firefox_version():
    '''Output Firefox's version we are attached to'''

    global xul_version
    print('[shadow] Firefox v%s (%s)' % (xul_version, dbg.get_arch()))
Esempio n. 6
0
def parse_chunks():
    global jeheap
    global dbg_engine

    # delete the chunks' list
    jeheap.chunks[:] = []

    try:
        root = dbg.to_int(dbg.eval_expr(dbg.chunk_rtree_root_expr))
        height = dbg.to_int(dbg.eval_expr(dbg.chunk_rtree_height_expr))

        level2bits = []

        for i in range(0, height):
            expr = dbg.chunk_rtree_level2bits_expr % (i)
            level2bits.append(dbg.to_int(dbg.eval_expr(expr)))
    except:
        print('[shadow] error: cannot parse chunk radix tree')
        sys.exit()

    # XXX: check if we're running on x86_64,
    #      not required for windbg/pykd (see the dp command)
    if jeheap.DWORD_SIZE == 8:
        if dbg_engine == 'gdb':
            dw_fmt = 'g'
        else: # lldb
            dw_fmt = 'XXX'
    else:
        if dbg_engine == 'gdb':
            dw_fmt = 'w'
        else: # lldb
            dw_fmt = 'XXX'

    # parse the radix tree using a stack
    stack = [(root, 0)]
    while len(stack):
        (node, node_height) = stack.pop()
        child_cnt = 1 << level2bits[node_height]
        
        if dbg_engine == 'gdb':
            expr = dbg.chunk_radix_expr % (child_cnt, dw_fmt, node)
        elif dbg_engine == 'pykd':
            if dbg.get_arch() == 'x86':
                child_cnt = child_cnt / 6

            expr = dbg.chunk_radix_expr % (node, child_cnt)
        else: # lldb
            expr = ''

        dump = dbg.execute(expr)

        for line in dump.split('\n'):
            
            line = line[line.find(dbg.address_separator) + \
                    len(dbg.address_separator):]

            for address in line.split():
                try:
                    address = int(address, 16)
                except:
                    address = 0

                if address != 0:
                    # leaf nodes hold pointers to actual values
                    if node_height == height - 1:
                        expr = dbg.chunk_arena_expr % address
                        
                        try:
                            arena_addr = dbg.to_int(dbg.eval_expr(expr))
                        except:
                            arena_addr = 0
 
                        exists = false

                        if arena_addr in [i.addr for i in jeheap.arenas]:
                            exists = true

                        if exists:
                            jeheap.chunks.append(jemalloc.arena_chunk(address, arena_addr))
                        else:
                            jeheap.chunks.append(jemalloc.arena_chunk(address))

                    # non-leaf nodes are inserted in the stack
                    else:
                        stack.append((address, node_height + 1))