Skip to content

Commit

Permalink
- switched emulate to use the new argparser
Browse files Browse the repository at this point in the history
  • Loading branch information
hugsy committed Jun 10, 2021
1 parent 6482690 commit 2892d15
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 62 deletions.
11 changes: 11 additions & 0 deletions docs/api.md
Expand Up @@ -212,6 +212,17 @@ gef_on_exit_unhook
> GDB are only present in the very latest version of GDB.

```
@parse_arguments( {"required_argument_1": DefaultValue1, ...}, {"--optional-argument-1": DefaultValue1, ...} )
```
> This decorator aims to facilitate the argument passing to a command. If added, it will use
> the `argparse` module to parse arguments, and will store them in the `kwargs["arguments"]` of
> the calling function (therefore the function **must** have `*args, **kwargs` added to its
> signature). Argument type is inferred directly from the default value **except** for boolean,
> where a value of `True` corresponds to `argparse`'s `store_true` action. For more details on
> `argparse`, refer to its Python doc.

### Classes ###

For exhaustive documentation, run
Expand Down
101 changes: 44 additions & 57 deletions gef.py
Expand Up @@ -2621,7 +2621,7 @@ def wrapper(*args, **kwargs):
parser.add_argument(argname, type=argtype, required=True, default=argvalue)
else:
# positional args
parser.add_argument(argname, type=argtype, default=argvalue, nargs='?')
parser.add_argument(argname, type=argtype, default=argvalue, nargs='*')

for argname in optional_arguments:
if not argname.startswith("-"):
Expand Down Expand Up @@ -3181,10 +3181,7 @@ def get_generic_arch(module, prefix, arch, mode, big_endian, to_string=False):

else:
arch = getattr(module, "{:s}_ARCH_{:s}".format(prefix, arch))
if prefix == "KS" and mode == "ARM":
# this workaround is because keystone.KS_MODE_ARM doesn't exist, must use 0
mode = 0
elif mode:
if mode:
mode = getattr(module, "{:s}_MODE_{:s}".format(prefix, mode))
else:
mode = 0
Expand Down Expand Up @@ -4359,7 +4356,7 @@ def do_invoke(self, argv, *args, **kwargs):
err("Language must be in: {}".format(str(self.valid_formats)))
return

start_addr = int(gdb.parse_and_eval(args.location))
start_addr = int(gdb.parse_and_eval(args.location[0]))
size = int(args.bitlen / 8)
end_addr = start_addr + args.length * size
fmt = self.format_matrix[args.bitlen][0]
Expand Down Expand Up @@ -5871,7 +5868,7 @@ def pre_load(self):
def do_invoke(self, argv, *args, **kwargs):
args = kwargs["arguments"]
start_address = args.start or current_arch.pc
end_address = args.until or self.get_unicorn_end_addr(start_address, args.nb)
end_address = args.until or self.get_unicorn_end_addr(start_address, args.nb[0])
self.run_unicorn(start_address, end_address, skip_emulation=args.skip_emulation, to_file=args.output_file)
return

Expand Down Expand Up @@ -6388,7 +6385,7 @@ def __init__(self):
@parse_arguments({"address": ""}, {"--retval": 0})
def do_invoke(self, argv, *args, **kwargs):
args = kwargs["arguments"]
loc = args.address if args.address else "*{:#x}".format(current_arch.pc)
loc = args.address[0] if args.address else "*{:#x}".format(current_arch.pc)
StubBreakpoint(loc, args.retval)
return

Expand Down Expand Up @@ -7275,16 +7272,14 @@ def do_invoke(self, argv):

@register_command
class AssembleCommand(GenericCommand):
"""Inline code assemble. Architecture can be set in GEF runtime config (default x86-32). """
"""Inline code assemble. Architecture can be set in GEF runtime config. """

_cmdline_ = "assemble"
_syntax_ = "{:s} [-a ARCH] [-m MODE] [-e] [-s] [-l LOCATION] instruction;[instruction;...instruction;])".format(_cmdline_)
_aliases_ = ["asm",]
_example_ = "\n{0:s} -a x86 -m 32 nop ; nop ; inc eax ; int3\n{0:s} -a arm -m arm add r0, r0, 1".format(_cmdline_)

def __init__(self, *args, **kwargs):
super().__init__(complete=gdb.COMPLETE_LOCATION)
self.valid_arch_modes = {
valid_arch_modes = {
"ARM": ["ARM", "THUMB"],
"ARM64": ["ARM", "THUMB", "V5", "V8", ],
"MIPS": ["MICRO", "MIPS3", "MIPS32", "MIPS32R6", "MIPS64",],
Expand All @@ -7293,6 +7288,13 @@ def __init__(self, *args, **kwargs):
"SYSTEMZ": ["32",],
"X86": ["16", "32", "64"],
}
valid_archs = valid_arch_modes.keys()
valid_modes = [_ for sublist in valid_arch_modes.values() for _ in sublist]

def __init__(self):
super().__init__()
self.add_setting("default_architecture", "X86", "Specify the default architecture to use when assembling")
self.add_setting("default_mode", "64", "Specify the default architecture to use when assembling")
return

def pre_load(self):
Expand All @@ -7312,52 +7314,37 @@ def usage(self):
gef_print(" * {}".format(" / ".join(self.valid_arch_modes[arch])))
return

def do_invoke(self, argv):
arch_s, mode_s, big_endian, as_shellcode, write_to_location = None, None, False, False, None
opts, args = getopt.getopt(argv, "a:m:l:esh")
for o, a in opts:
if o == "-a": arch_s = a.upper()
if o == "-m": mode_s = a.upper()
if o == "-e": big_endian = True
if o == "-s": as_shellcode = True
if o == "-l": write_to_location = int(gdb.parse_and_eval(a))
if o == "-h":
self.usage()
return
@parse_arguments({"instructions": ""}, {"--mode": "", "--arch": "", "--overwrite-location": 0, "--big-endian": True, "--as-shellcode": True, })
def do_invoke(self, argv, *args, **kwargs):
arch_s, mode_s, endian_s = self.get_setting("default_architecture"), self.get_setting("default_mode"), ""

if not args:
args = kwargs["arguments"]
if not args.instructions:
err("No instruction given.")
return

if (arch_s, mode_s) == (None, None):
if is_alive():
arch_s, mode_s = current_arch.arch, current_arch.mode
endian_s = "big" if is_big_endian() else "little"
arch, mode = get_keystone_arch(arch=arch_s, mode=mode_s, endian=is_big_endian())
else:
# if not alive, defaults to x86-32
arch_s = "X86"
mode_s = "32"
endian_s = "little"
arch, mode = get_keystone_arch(arch=arch_s, mode=mode_s, endian=False)
elif not arch_s:
err("An architecture (-a) must be provided")
return
elif not mode_s:
err("A mode (-m) must be provided")
return
else:
arch, mode = get_keystone_arch(arch=arch_s, mode=mode_s, endian=big_endian)
endian_s = "big" if big_endian else "little"
if is_alive():
arch_s, mode_s = current_arch.arch, current_arch.mode
endian_s = "big" if is_big_endian() else ""

if args.arch:
arch_s = args.arch

if args.mode:
mode_s = args.mode

if args.big_endian:
endian_s = "big"

insns = " ".join(args)
insns = [x.strip() for x in insns.split(";") if x is not None]
if arch_s.upper() not in self.valid_archs or mode_s.upper() not in self.valid_modes:
raise AttributeError("invalid arch/mode")

info("Assembling {} instruction{} for {} ({} endian)".format(len(insns),
"s" if len(insns)>1 else "",
":".join([arch_s, mode_s]),
endian_s))
# this is fire a ValueError if the arch/mode/endianess are invalid
arch, mode = get_keystone_arch(arch=arch_s.upper(), mode=mode_s.upper(), endian=endian_s.upper())
insns = [x.strip() for x in " ".join(args.instructions).split(";") if x]
info("Assembling {} instruction(s) for {}:{}".format(len(insns),arch_s, mode_s))

if as_shellcode:
if args.as_shellcode:
gef_print("""sc="" """)

raw = b""
Expand All @@ -7367,23 +7354,23 @@ def do_invoke(self, argv):
gef_print("(Invalid)")
continue

if write_to_location:
if args.overwrite_location:
raw += res
continue

s = binascii.hexlify(res)
res = b"\\x" + b"\\x".join([s[i:i + 2] for i in range(0, len(s), 2)])
res = res.decode("utf-8")

if as_shellcode:
if args.as_shellcode:
res = """sc+="{0:s}" """.format(res)

gef_print("{0:60s} # {1}".format(res, insn))

if write_to_location:
if args.overwrite_location:
l = len(raw)
info("Overwriting {:d} bytes at {:s}".format(l, format_address(write_to_location)))
write_memory(write_to_location, raw, l)
info("Overwriting {:d} bytes at {:s}".format(l, format_address(args.overwrite_location)))
write_memory(args.overwrite_location, raw, l)
return


Expand Down
10 changes: 5 additions & 5 deletions tests/runtests.py
Expand Up @@ -249,11 +249,11 @@ def test_cmd_hexdump(self):

def test_cmd_keystone_assemble(self):
valid_cmds = [
"assemble nop; xor eax, eax; int 0x80",
"assemble -a arm -m arm add r0, r1, r2",
"assemble -a mips -m mips32 add $v0, 1",
"assemble -a sparc -m sparc32 set 0, %o0",
"assemble -a arm64 -m little_endian add x29, sp, 0; mov w0, 0; ret"
"assemble nop; xor eax, eax; syscall",
"assemble --arch arm --mode arm add r0, r1, r2",
"assemble --arch mips --mode mips32 add $v0, 1",
"assemble --arch sparc --mode sparc32 set 0, %o0",
"assemble --arch arm64 --mode arm add x29, sp, 0; mov w0, 0; ret"
]
for cmd in valid_cmds:
res = gdb_start_silent_cmd(cmd)
Expand Down

0 comments on commit 2892d15

Please sign in to comment.