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
Szymon Borecki 3 years ago committed by GitHub
parent 3fa4ddab73
commit 3b56329acc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -460,6 +460,7 @@ def load_commands():
import pwndbg.commands.config import pwndbg.commands.config
import pwndbg.commands.context import pwndbg.commands.context
import pwndbg.commands.cpsr import pwndbg.commands.cpsr
import pwndbg.commands.cyclic
import pwndbg.commands.cymbol import pwndbg.commands.cymbol
import pwndbg.commands.dt import pwndbg.commands.dt
import pwndbg.commands.dumpargs import pwndbg.commands.dumpargs

@ -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())

@ -7,7 +7,7 @@ import os
import pwndbg.commands import pwndbg.commands
import pwndbg.lib.which import pwndbg.lib.which
pwncmds = ["asm", "constgrep", "cyclic", "disasm", "pwn", "unhex"] pwncmds = ["asm", "constgrep", "disasm", "pwn", "unhex"]
shellcmd_names = [ shellcmd_names = [
"awk", "awk",
"bash", "bash",

@ -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…
Cancel
Save