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