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")
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')
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()))
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))
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()))
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))