You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pwndbg/pwndbg/commands/misc.py

146 lines
4.6 KiB
Python

import argparse
import errno
import gdb
import pwndbg.auxv
import pwndbg.commands
import pwndbg.gdblib.regs
import pwndbg.gdblib.symbol
errno.errorcode[0] = "OK" # type: ignore # manually add error code 0 for "OK"
parser = argparse.ArgumentParser(
description="""
Converts errno (or argument) to its string representation.
"""
)
parser.add_argument(
"err",
type=int,
nargs="?",
default=None,
help="Errno; if not passed, it is retrieved from __errno_location",
)
@pwndbg.commands.ArgparsedCommand(parser, command_name="errno")
@pwndbg.commands.OnlyWhenRunning
def errno_(err):
if err is None:
# Try to get the `errno` variable value
# if it does not exist, get the errno variable from its location
try:
err = int(gdb.parse_and_eval("errno"))
except gdb.error:
try:
# We can't simply call __errno_location because its .plt.got entry may be uninitialized
# (e.g. if the binary was just started with `starti` command)
# So we have to check the got.plt entry first before calling it
errno_loc_gotplt = pwndbg.gdblib.symbol.address("__errno_location@got.plt")
# If the got.plt entry is not there (is None), it means the symbol is not used by the binary
if errno_loc_gotplt is None or pwndbg.gdblib.vmmap.find(
pwndbg.gdblib.memory.pvoid(errno_loc_gotplt)
):
err = int(gdb.parse_and_eval("*((int *(*) (void)) __errno_location) ()"))
else:
print(
"Could not determine error code automatically: the __errno_location@got.plt has no valid address yet (perhaps libc.so hasn't been loaded yet?)"
)
return
except gdb.error:
print(
"Could not determine error code automatically: neither `errno` nor `__errno_location` symbols were provided (perhaps libc.so hasn't been not loaded yet?)"
)
return
msg = errno.errorcode.get(int(err), "Unknown error code")
print("Errno %s: %s" % (err, msg))
parser = argparse.ArgumentParser(
description="""
Prints out a list of all pwndbg commands. The list can be optionally filtered if filter_pattern is passed.
"""
)
group = parser.add_mutually_exclusive_group()
group.add_argument("--shell", action="store_true", help="Only display shell commands")
group.add_argument("--all", dest="all_", action="store_true", help="Only display shell commands")
parser.add_argument(
"filter_pattern",
type=str,
nargs="?",
default=None,
help="Filter to apply to commands names/docs",
)
@pwndbg.commands.ArgparsedCommand(parser, command_name="pwndbg")
def pwndbg_(filter_pattern, shell, all_):
if all_:
shell_cmds = True
pwndbg_cmds = True
elif shell:
shell_cmds = True
pwndbg_cmds = False
else:
shell_cmds = False
pwndbg_cmds = True
for name, docs in list_and_filter_commands(filter_pattern, pwndbg_cmds, shell_cmds):
print("%-20s %s" % (name, docs))
parser = argparse.ArgumentParser(description="""Print the distance between the two arguments.""")
parser.add_argument("a", type=int, help="The first address.")
parser.add_argument("b", type=int, help="The second address.")
@pwndbg.commands.ArgparsedCommand(parser)
def distance(a, b):
"""Print the distance between the two arguments"""
a = int(a) & pwndbg.gdblib.arch.ptrmask
b = int(b) & pwndbg.gdblib.arch.ptrmask
distance = b - a
print(
"%#x->%#x is %#x bytes (%#x words)"
% (a, b, distance, distance // pwndbg.gdblib.arch.ptrsize)
)
def list_and_filter_commands(filter_str, pwndbg_cmds=True, shell_cmds=False):
sorted_commands = list(pwndbg.commands.commands)
sorted_commands.sort(key=lambda x: x.__name__)
if filter_str:
filter_str = filter_str.lower()
results = []
for c in sorted_commands:
# If this is a shell command and we didn't ask for shell commands, skip it
if c.shell and not shell_cmds:
continue
# If this is a normal command and we didn't ask for normal commands, skip it
if not c.shell and not pwndbg_cmds:
continue
name = c.__name__
docs = c.__doc__
if docs:
docs = docs.strip()
if docs:
docs = docs.splitlines()[0]
if not filter_str or filter_str in name.lower() or (docs and filter_str in docs.lower()):
results.append((name, docs))
return results