mirror of https://github.com/pwndbg/pwndbg.git
Port pwntools cyclic into pwndbg (#1337)
* Port pwntools' cyclic into pwndbg * Update pwndbg/commands/cyclic.py Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com> * Update pwndbg/commands/cyclic.py Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>pull/1353/head
parent
3fa4ddab73
commit
3b56329acc
@ -0,0 +1,86 @@
|
||||
import argparse
|
||||
import string
|
||||
|
||||
import gdb
|
||||
from pwnlib.util.cyclic import cyclic
|
||||
from pwnlib.util.cyclic import cyclic_find
|
||||
|
||||
import pwndbg.commands
|
||||
import pwndbg.gdblib.arch
|
||||
from pwndbg.color import message
|
||||
|
||||
parser = argparse.ArgumentParser(description="Cyclic pattern creator/finder")
|
||||
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--alphabet",
|
||||
metavar="charset",
|
||||
default=string.ascii_lowercase,
|
||||
type=str.encode,
|
||||
help="The alphabet to use in the cyclic pattern",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--length",
|
||||
metavar="length",
|
||||
type=int,
|
||||
help="Size of the unique subsequences (defaults to the pointer size for the current arch)",
|
||||
)
|
||||
|
||||
group = parser.add_mutually_exclusive_group(required=False)
|
||||
group.add_argument(
|
||||
"-l",
|
||||
"-o",
|
||||
"--offset",
|
||||
"--lookup",
|
||||
dest="lookup",
|
||||
metavar="lookup_value",
|
||||
type=str,
|
||||
help="Do a lookup instead of printing the sequence (accepts constant values as well as expressions)",
|
||||
)
|
||||
|
||||
group.add_argument(
|
||||
"count",
|
||||
type=int,
|
||||
nargs="?",
|
||||
default=None,
|
||||
help="Number of characters to print from the sequence (default: print the entire sequence)",
|
||||
)
|
||||
|
||||
|
||||
@pwndbg.commands.ArgparsedCommand(parser, command_name="cyclic")
|
||||
def cyclic_cmd(alphabet, length, lookup, count):
|
||||
if length:
|
||||
# Convert from gdb.Value
|
||||
length = int(length)
|
||||
else:
|
||||
length = pwndbg.gdblib.arch.ptrsize
|
||||
|
||||
if lookup:
|
||||
lookup = pwndbg.commands.fix(lookup, sloppy=True)
|
||||
|
||||
if type(lookup) in [gdb.Value, int]:
|
||||
lookup = int(lookup).to_bytes(length, pwndbg.gdblib.arch.endian)
|
||||
elif type(lookup) is str:
|
||||
lookup = bytes(lookup, "utf-8")
|
||||
|
||||
if len(lookup) != length:
|
||||
print(message.error(f"Lookup pattern must be {length} bytes"))
|
||||
return
|
||||
|
||||
print(message.notice(f"Lookup value: {str(lookup)}"))
|
||||
|
||||
if any(c not in alphabet for c in lookup):
|
||||
print(message.error("Pattern contains characters not present in the alphabet"))
|
||||
return
|
||||
|
||||
offset = cyclic_find(lookup, alphabet, length)
|
||||
|
||||
if offset == -1:
|
||||
print(message.error("Given lookup pattern does not exist in the sequence"))
|
||||
else:
|
||||
print(message.success(offset))
|
||||
else:
|
||||
sequence = cyclic(count, alphabet, length)
|
||||
print(sequence.decode())
|
||||
@ -0,0 +1,57 @@
|
||||
import gdb
|
||||
from pwnlib.util.cyclic import cyclic
|
||||
|
||||
import pwndbg.gdblib.arch
|
||||
import pwndbg.gdblib.memory
|
||||
import pwndbg.gdblib.regs
|
||||
import tests
|
||||
|
||||
REFERENCE_BINARY = tests.binaries.get("reference-binary.out")
|
||||
|
||||
|
||||
def test_command_cyclic_value(start_binary):
|
||||
"""
|
||||
Tests lookup on a constant value
|
||||
"""
|
||||
start_binary(REFERENCE_BINARY)
|
||||
|
||||
ptr_size = pwndbg.gdblib.arch.ptrsize
|
||||
test_offset = 37
|
||||
pattern = cyclic(length=80, n=ptr_size)
|
||||
val = int.from_bytes(pattern[test_offset : test_offset + ptr_size], pwndbg.gdblib.arch.endian)
|
||||
out = gdb.execute(f"cyclic -l {hex(val)}", to_string=True)
|
||||
|
||||
assert int(out.split("\n")[1]) == test_offset
|
||||
|
||||
|
||||
def test_command_cyclic_register(start_binary):
|
||||
"""
|
||||
Tests lookup on a register
|
||||
"""
|
||||
start_binary(REFERENCE_BINARY)
|
||||
|
||||
ptr_size = pwndbg.gdblib.arch.ptrsize
|
||||
test_offset = 45
|
||||
pattern = cyclic(length=80, n=ptr_size)
|
||||
pwndbg.gdblib.regs.rdi = int.from_bytes(
|
||||
pattern[test_offset : test_offset + ptr_size], pwndbg.gdblib.arch.endian
|
||||
)
|
||||
out = gdb.execute("cyclic -l $rdi", to_string=True)
|
||||
|
||||
assert int(out.split("\n")[1]) == test_offset
|
||||
|
||||
|
||||
def test_command_cyclic_address(start_binary):
|
||||
"""
|
||||
Tests lookup on a memory address
|
||||
"""
|
||||
start_binary(REFERENCE_BINARY)
|
||||
|
||||
addr = pwndbg.gdblib.regs.rsp
|
||||
ptr_size = pwndbg.gdblib.arch.ptrsize
|
||||
test_offset = 48
|
||||
pattern = cyclic(length=80, n=ptr_size)
|
||||
pwndbg.gdblib.memory.write(addr, pattern)
|
||||
out = gdb.execute(f"cyclic -l '{{unsigned long}}{hex(addr + test_offset)}'", to_string=True)
|
||||
|
||||
assert int(out.split("\n")[1]) == test_offset
|
||||
Loading…
Reference in new issue