def telescope(address=None, count=telescope_lines, to_string=False): """ Recursively dereferences pointers starting at the specified address ($sp by default) """ address = int(address if address else pwndbg.regs.sp) & pwndbg.arch.ptrmask count = int(count) & pwndbg.arch.ptrmask delimiter = T.delimiter(offset_delimiter) separator = T.separator(offset_separator) # Allow invocation of "hexdump 20" to dump 20 bytes at the stack pointer if address < pwndbg.memory.MMAP_MIN_ADDR and not pwndbg.memory.peek(address): count = address address = pwndbg.regs.sp # Allow invocation of "hexdump a b" to dump all bytes from A to B if int(address) < int(count): count -= address reg_values = collections.defaultdict(lambda: []) for reg in pwndbg.regs.common: reg_values[pwndbg.regs[reg]].append(reg) # address = pwndbg.memory.poi(pwndbg.typeinfo.ppvoid, address) ptrsize = pwndbg.typeinfo.ptrsize start = address stop = address + (count*ptrsize) step = ptrsize # Find all registers which show up in the trace regs = {} for i in range(start, stop, step): values = list(reg_values[i]) for width in range(1, pwndbg.arch.ptrsize): values.extend('%s-%i' % (r,width) for r in reg_values[i+width]) regs[i] = ' '.join(values) # Find the longest set of register information if regs: longest_regs = max(map(len, regs.values())) + 1 else: longest_regs = 0 # Print everything out result = [] last = None skip = False for i,addr in enumerate(range(start, stop, step)): if not pwndbg.memory.peek(addr): result.append("<Could not read memory at %#x>" % addr) break # Collapse repeating values. value = pwndbg.memory.pvoid(addr) if last == value: if not skip: result.append(T.repeating_marker('%s' % repeating_maker)) skip = True continue last = value skip = False line = ' '.join((T.offset("%02x%s%04x%s" % (i, delimiter, addr-start, separator)), T.register(regs[addr].ljust(longest_regs)), pwndbg.chain.format(addr))) result.append(line) if not to_string: print('\n'.join(result)) return result
def telescope(address=None, count=telescope_lines, to_string=False): """ Recursively dereferences pointers starting at the specified address ($sp by default) """ address = int(address if address else pwndbg.regs.sp) & pwndbg.arch.ptrmask count = int(count) & pwndbg.arch.ptrmask delimiter = T.delimiter(offset_delimiter) separator = T.separator(offset_separator) # Allow invocation of "hexdump 20" to dump 20 bytes at the stack pointer if address < pwndbg.memory.MMAP_MIN_ADDR and not pwndbg.memory.peek( address): count = address address = pwndbg.regs.sp # Allow invocation of "hexdump a b" to dump all bytes from A to B if int(address) < int(count): count -= address reg_values = collections.defaultdict(lambda: []) for reg in pwndbg.regs.common: reg_values[pwndbg.regs[reg]].append(reg) # address = pwndbg.memory.poi(pwndbg.typeinfo.ppvoid, address) ptrsize = pwndbg.typeinfo.ptrsize start = address stop = address + (count * ptrsize) step = ptrsize # Find all registers which show up in the trace regs = {} for i in range(start, stop, step): values = list(reg_values[i]) for width in range(1, pwndbg.arch.ptrsize): values.extend('%s-%i' % (r, width) for r in reg_values[i + width]) regs[i] = ' '.join(values) # Find the longest set of register information if regs: longest_regs = max(map(len, regs.values())) + 1 else: longest_regs = 0 # Print everything out result = [] last = None skip = False for i, addr in enumerate(range(start, stop, step)): if not pwndbg.memory.peek(addr): result.append("<Could not read memory at %#x>" % addr) break # Collapse repeating values. value = pwndbg.memory.pvoid(addr) if last == value: if not skip: result.append(T.repeating_marker('%s' % repeating_maker)) skip = True continue last = value skip = False line = ' '.join((T.offset("%02x%s%04x%s" % (i, delimiter, addr - start, separator)), T.register(regs[addr].ljust(longest_regs)), pwndbg.chain.format(addr))) result.append(line) if not to_string: print('\n'.join(result)) return result
def telescope(address=None, count=telescope_lines, to_string=False, reverse=False): """ Recursively dereferences pointers starting at the specified address ($sp by default) """ ptrsize = pwndbg.typeinfo.ptrsize if telescope.repeat: address = telescope.last_address + ptrsize telescope.offset += 1 else: telescope.offset = 0 address = int(address if address else pwndbg.regs.sp) & pwndbg.arch.ptrmask count = max(int(count), 1) & pwndbg.arch.ptrmask delimiter = T.delimiter(offset_delimiter) separator = T.separator(offset_separator) # Allow invocation of telescope -r to dump previous addresses if reverse: address -= (count - 1) * ptrsize # Allow invocation of "telescope 20" to dump 20 bytes at the stack pointer if address < pwndbg.memory.MMAP_MIN_ADDR and not pwndbg.memory.peek( address): count = address address = pwndbg.regs.sp # Allow invocation of "telescope a b" to dump all bytes from A to B if int(address) <= int(count): # adjust count if it is an address. use ceil division as count is number of # ptrsize values and we don't want to strip out a value if dest is unaligned count -= address count = max(math.ceil(count / ptrsize), 1) reg_values = collections.defaultdict(lambda: []) for reg in pwndbg.regs.common: reg_values[pwndbg.regs[reg]].append(reg) # address = pwndbg.memory.poi(pwndbg.typeinfo.ppvoid, address) start = address stop = address + (count * ptrsize) step = ptrsize # Find all registers which show up in the trace regs = {} for i in range(start, stop, step): values = list(reg_values[i]) for width in range(1, pwndbg.arch.ptrsize): values.extend("%s-%i" % (r, width) for r in reg_values[i + width]) regs[i] = " ".join(values) # Find the longest set of register information if regs: longest_regs = max(map(len, regs.values())) else: longest_regs = 0 # Print everything out result = [] last = None collapse_buffer = [] skipped_padding = (2 + len(offset_delimiter) + 4 + len(offset_separator) + 1 + longest_regs + 1 - len(repeating_marker)) # Collapse repeating values exceeding minimum delta. def collapse_repeating_values(): # The first line was already printed, hence increment by 1 if collapse_buffer and len( collapse_buffer) + 1 >= skip_repeating_values_minimum: result.append( T.repeating_marker("%s%s%i skipped" % (repeating_marker, " " * skipped_padding, len(collapse_buffer)))) else: result.extend(collapse_buffer) collapse_buffer.clear() for i, addr in enumerate(range(start, stop, step)): if not pwndbg.memory.peek(addr): collapse_repeating_values() result.append("<Could not read memory at %#x>" % addr) break line = " ".join(( T.offset("%02x%s%04x%s" % ( i + telescope.offset, delimiter, addr - start + (telescope.offset * ptrsize), separator, )), T.register(regs[addr].ljust(longest_regs)), pwndbg.chain.format(addr), )) # Buffer repeating values. if skip_repeating_values: value = pwndbg.memory.pvoid(addr) if last == value: collapse_buffer.append(line) continue collapse_repeating_values() last = value result.append(line) collapse_repeating_values() telescope.offset += i telescope.last_address = addr if not to_string: print("\n".join(result)) return result