Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move syscall-args and is-syscall to gef-extras #861

Merged
merged 3 commits into from
Jul 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 0 additions & 18 deletions docs/commands/is-syscall.md

This file was deleted.

49 changes: 0 additions & 49 deletions docs/commands/syscall-args.md

This file was deleted.

2 changes: 2 additions & 0 deletions docs/deprecated.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ This page aims to track those changes.
| `ida-interact` | Moved | 2022.06 | [Link](https://github.com/hugsy/gef-extras/blob/dev/scripts/ida_interact.py) | Depends on `rpyc` |
| `exploit-template` | Moved | [c402900](https://github.com/hugsy/gef-extras/commit/c4029007994d5e508cb3df900b60821b0b61e0e5) | [Link](https://github.com/hugsy/gef-extras/blob/dev/scripts/skel.py) | |
| `windbg` | Moved | [a933a5a](https://github.com/hugsy/gef-extras/commit/a933a5ac43933742d91f4e299eadf05e3e0670be) | [Link](https://github.com/hugsy/gef-extras/blob/dev/scripts/windbg.py) | |
| `is-syscall` | Moved | [3f79fb38](https://github.com/hugsy/gef-extras/commit/3f79fb382aa9052d073698d40237f98982c5d2de) | [Link](https://github.com/hugsy/gef-extras/blob/dev/scripts/syscall_args) | |
| `syscall-args` | Moved | [3f79fb38](https://github.com/hugsy/gef-extras/commit/3f79fb382aa9052d073698d40237f98982c5d2de) | [Link](https://github.com/hugsy/gef-extras/blob/dev/scripts/syscall_args) | |
121 changes: 23 additions & 98 deletions gef.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ def update_gef(argv: List[str]) -> int:
GEF_EXTRAS_DEFAULT_BRANCH = "main"

gef : "Gef"
__registered_commands__ : List[Type["GenericCommand"]] = []
__registered_functions__ : List[Type["GenericFunction"]] = []
__registered_commands__ : Set[Type["GenericCommand"]] = set()
__registered_functions__ : Set[Type["GenericFunction"]] = set()
__registered_architectures__ : Dict[Union["Elf.Abi", str], Type["Architecture"]] = {}
__registered_file_formats__ : Set[ Type["FileFormat"] ] = set()

Expand Down Expand Up @@ -4416,17 +4416,20 @@ def register_priority_command(cls: Type["GenericCommand"]) -> Type["GenericComma
return cls


def register(cls: Type["GenericCommand"]) -> Type["GenericCommand"]:
def register(cls: Union[Type["GenericCommand"], Type["GenericFunction"]]) -> Union[Type["GenericCommand"], Type["GenericFunction"]]:
global __registered_commands__, __registered_functions__
if issubclass(cls, GenericCommand):
assert( hasattr(cls, "_cmdline_"))
assert( hasattr(cls, "do_invoke"))
__registered_commands__.append(cls)
assert( all(map(lambda x: x._cmdline_ != cls._cmdline_, __registered_commands__)))
__registered_commands__.add(cls)
return cls

if issubclass(cls, GenericFunction):
assert( hasattr(cls, "_function_"))
assert( hasattr(cls, "invoke"))
__registered_functions__.append(cls)
assert( all(map(lambda x: x._function_ != cls._function_, __registered_functions__)))
__registered_functions__.add(cls)
return cls

raise TypeError(f"`{cls.__class__}` is an illegal class for `register`")
Expand Down Expand Up @@ -7120,6 +7123,9 @@ def do_invoke(self, argv: List[str]) -> None:
except gdb.MemoryError as e:
# a MemoryError will happen when $pc is corrupted (invalid address)
err(str(e))
except IndexError:
# the `section` is not present, just skip
pass

self.context_title("")

Expand Down Expand Up @@ -9110,93 +9116,6 @@ def clean(self, _: "gdb.Event") -> None:
return


@register
class IsSyscallCommand(GenericCommand):
"""Tells whether the next instruction is a system call."""
_cmdline_ = "is-syscall"
_syntax_ = _cmdline_

@only_if_gdb_running
def do_invoke(self, _: List[str]) -> None:
ok(f"Current instruction is{' ' if is_syscall(gef.arch.pc) else ' not '}a syscall")
return


@register
class SyscallArgsCommand(GenericCommand):
"""Gets the syscall name and arguments based on the register values in the current state."""
_cmdline_ = "syscall-args"
_syntax_ = _cmdline_

def __init__(self) -> None:
super().__init__()
path = pathlib.Path(gef.config["gef.tempdir"]) / "syscall-tables"
self["path"] = (str(path.absolute()), "Path to store/load the syscall tables files")
return

@only_if_gdb_running
def do_invoke(self, _: List[str]) -> None:
if not self["path"]:
err(f"Cannot open '{self['path']}': check directory and/or "
"`gef config syscall-args.path` setting.")
return

color = gef.config["theme.table_heading"]
arch = gef.arch.__class__.__name__
syscall_table = self.__get_syscall_table(arch)

if is_syscall(gef.arch.pc):
# if $pc is before the `syscall` instruction is executed:
reg_value = gef.arch.register(gef.arch.syscall_register)
else:
# otherwise, try the previous instruction (case of using `catch syscall`)
previous_insn_addr = gdb_get_nth_previous_instruction_address(gef.arch.pc, 1)
if not is_syscall(previous_insn_addr):
err("No syscall found")
return
reg_value = gef.arch.register(f"$orig_{gef.arch.syscall_register.lstrip('$')}")

if reg_value not in syscall_table:
warn(f"There is no system call for {reg_value:#x}")
return
syscall_entry = syscall_table[reg_value]

values = [gef.arch.register(param.reg) for param in syscall_entry.params]
parameters = [s.param for s in syscall_entry.params]
registers = [s.reg for s in syscall_entry.params]

info(f"Detected syscall {Color.colorify(syscall_entry.name, color)}")
gef_print(f" {syscall_entry.name}({', '.join(parameters)})")

headers = ["Parameter", "Register", "Value"]
param_names = [re.split(r" |\*", p)[-1] for p in parameters]
info(Color.colorify("{:<20} {:<20} {}".format(*headers), color))
for name, register, value in zip(param_names, registers, values):
line = f" {name:<20} {register:<20} {value:#x}"
addrs = dereference_from(value)
if len(addrs) > 1:
line += RIGHT_ARROW + RIGHT_ARROW.join(addrs[1:])
gef_print(line)
return

def __get_syscall_table(self, modname: str) -> Dict[str, Any]:
def get_filepath(x: str) -> Optional[pathlib.Path]:
path = pathlib.Path(self["path"]).expanduser()
if not path.is_dir():
return None
return path / f"{x}.py"

def load_module(modname: str) -> Any:
_fpath = get_filepath(modname)
if not _fpath:
raise FileNotFoundError
_fullname = str(_fpath.absolute())
return importlib.machinery.SourceFileLoader(modname, _fullname).load_module(None)

_mod = load_module(modname)
return getattr(_mod, "syscall_table")


#
# GDB Function declaration
#
Expand Down Expand Up @@ -9429,6 +9348,7 @@ def setup(self) -> None:
def load_extra_plugins(self) -> int:
def load_plugin(fpath: pathlib.Path) -> bool:
try:
dbg(f"Loading '{fpath}'")
gdb.execute(f"source {fpath}")
except Exception as e:
warn(f"Exception while loading {fpath}: {str(e)}")
Expand Down Expand Up @@ -9458,10 +9378,15 @@ def load_plugin(fpath: pathlib.Path) -> bool:
nb_added = len(__registered_commands__) - nb_inital
if nb_added > 0:
self.load()
nb_failed = len(__registered_commands__) - len(self.commands)
end_time = time.perf_counter()
load_time = end_time - start_time
ok(f"{Color.colorify(str(nb_added), 'bold green')} extra commands added from "
f"'{Color.colorify(', '.join(directories), 'bold blue')}' in {load_time:.2f} seconds")
if nb_failed != 0:
warn(f"{Color.colorify(str(nb_failed), 'bold light_gray')} extra commands/functions failed to be added. "
"Check `gef missing` to know why")

except gdb.error as e:
err(f"failed: {e}")
return nb_added
Expand Down Expand Up @@ -9504,17 +9429,17 @@ def load(self) -> None:

# load all new functions
for name in sorted(new_functions):
for function_class in __registered_functions__:
if function_class._function_ == name:
self.functions[name] = function_class()
for function_cls in __registered_functions__:
if function_cls._function_ == name:
self.functions[name] = function_cls()
break

# load all new commands
for name in sorted(new_commands):
try:
for function_class in __registered_commands__:
if function_class._cmdline_ == name:
command_instance = function_class()
for command_cls in __registered_commands__:
if command_cls._cmdline_ == name:
command_instance = command_cls()

# create the aliases if any
if hasattr(command_instance, "_aliases_"):
Expand Down
2 changes: 0 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ nav:
- hexdump: commands/hexdump.md
- highlight: commands/highlight.md
- hijack-fd: commands/hijack-fd.md
- is-syscall: commands/is-syscall.md
- ksymaddr: commands/ksymaddr.md
- memory: commands/memory.md
- name-break: commands/name-break.md
Expand All @@ -62,7 +61,6 @@ nav:
- search-pattern: commands/search-pattern.md
- shellcode: commands/shellcode.md
- stub: commands/stub.md
- syscall-args: commands/syscall-args.md
- theme: commands/theme.md
- tmux-setup: commands/tmux-setup.md
- trace-run: commands/trace-run.md
Expand Down
34 changes: 34 additions & 0 deletions tests/binaries/mmap-known-address.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* -*- mode: c -*-
* -*- coding: utf-8 -*-
*
* mmap-known-address.c : only mmap() at 0x1337000 and DebugBreak
*
* @author: @_hugsy_
* @licence: WTFPL v.2
*/

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>

#include "utils.h"

int main(int argc, char **argv, char **envp)
{
void *p = mmap((void *)0x1337000,
getpagesize(),
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,
-1,
0);

if (p == (void *)-1)
return EXIT_FAILURE;

DebugBreak();

return EXIT_SUCCESS;
}
34 changes: 0 additions & 34 deletions tests/binaries/set-permission.c

This file was deleted.

50 changes: 0 additions & 50 deletions tests/binaries/syscall-args.c

This file was deleted.