Skip to content

Commit

Permalink
[cmd] Add support for flags specifying filters type in vmmap, and all…
Browse files Browse the repository at this point in the history
…ow multiple filters (#1120)

Parse args:
 - `-a` / `--addr`:
- filter by address -> parses the next arg as an int or asks gdb the
value
 - `-n` / `--name`:
   - filter based on section name
- If nothing is specified, print a warning and guess the type (previous
behavior)

---------

Co-authored-by: Grazfather <[email protected]>
  • Loading branch information
ValekoZ and Grazfather authored Oct 24, 2024
1 parent f9f8045 commit ba70548
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 19 deletions.
20 changes: 15 additions & 5 deletions docs/commands/vmmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,23 @@ differs from one architecture to another (this is one of the main reasons I star
place). For example, you can learn that ELF running on SPARC architectures always have their `.data`
and `heap` sections set as Read/Write/Execute.

`vmmap` accepts one argument, either a pattern to match again mapping names, or an address to
determine which section it belongs to.
`vmmap` can accept multiple arguments, either patterns to match again mapping names, or addresses
to determine which section it belongs to:

![vmmap-grep](https://i.imgur.com/ZFF4QVf.png)
1. `-a` / `--addr`:
- filter by address -> parses the next argument as an integer or asks gdb to interpret the value
2. `-n` / `--name`:
- filter based on section name
3. If nothing is specified, it prints a warning and guesses the type

![vmmap-address](https://i.imgur.com/hfcs1jH.png)
![vmmap-grep](https://github.com/hugsy/gef/assets/11377623/a3dbaa3e-88b0-407f-a0dd-07e65c4a3f73)

![vmmap-address](https://github.com/hugsy/gef/assets/11377623/4dffe491-f927-4f03-b842-4d941140e66c)

The address can be also be given in the form of a register or variable.

![vmmap-register](https://i.imgur.com/RlZA6NU.png)
![vmmap-register](https://github.com/hugsy/gef/assets/11377623/aed7ecdc-7ad9-4ba5-ae03-329e66432731)

And you can do all of them in one command 🙂

![vmmap-all-in-one](https://github.com/hugsy/gef/assets/11377623/b043f61b-48b3-4316-9f84-eb83822149ac)
55 changes: 43 additions & 12 deletions gef.py
Original file line number Diff line number Diff line change
Expand Up @@ -8898,12 +8898,35 @@ class VMMapCommand(GenericCommand):
_example_ = f"{_cmdline_} libc"

@only_if_gdb_running
def do_invoke(self, argv: List[str]) -> None:
@parse_arguments({"unknown_types": [""]}, {("--addr", "-a"): [""], ("--name", "-n"): [""]})
def do_invoke(self, _: List[str], **kwargs: Any) -> None:
args : argparse.Namespace = kwargs["arguments"]
vmmap = gef.memory.maps
if not vmmap:
err("No address mapping information found")
return

addrs: Dict[str, int] = {x: parse_address(x) for x in args.addr}
names: List[str] = [x for x in args.name]

for arg in args.unknown_types:
if not arg:
continue

if self.is_integer(arg):
addr = int(arg, 0)
else:
addr = safe_parse_and_eval(arg)

if addr is None:
names.append(arg)
warn(f"`{arg}` has no type specified. We guessed it was a name filter.")
else:
addrs[arg] = int(addr)
warn(f"`{arg}` has no type specified. We guessed it was an address filter.")
warn("You can use --name or --addr before the filter value for specifying its type manually.")
gef_print()

if not gef.config["gef.disable_color"]:
self.show_legend()

Expand All @@ -8912,22 +8935,30 @@ def do_invoke(self, argv: List[str]) -> None:
headers = ["Start", "End", "Offset", "Perm", "Path"]
gef_print(Color.colorify("{:<{w}s}{:<{w}s}{:<{w}s}{:<4s} {:s}".format(*headers, w=gef.arch.ptrsize*2+3), color))

last_printed_filter = None

for entry in vmmap:
if not argv:
names_filter = [f"name = '{x}'" for x in names if x in entry.path]
addrs_filter = [f"addr = {self.format_addr_filter(arg, addr)}" for arg, addr in addrs.items()
if entry.page_start <= addr < entry.page_end]
filter_content = f"[{' & '.join([*names_filter, *addrs_filter])}]"

if not names and not addrs:
self.print_entry(entry)
continue
if argv[0] in entry.path:

elif names_filter or addrs_filter:
if filter_content != last_printed_filter:
gef_print() # skip a line between different filters
gef_print(Color.greenify(filter_content))
last_printed_filter = filter_content
self.print_entry(entry)
elif self.is_integer(argv[0]):
addr = int(argv[0], 0)
if addr >= entry.page_start and addr < entry.page_end:
self.print_entry(entry)
else:
addr = safe_parse_and_eval(argv[0])
if addr is not None and addr >= entry.page_start and addr < entry.page_end:
self.print_entry(entry)

gef_print()
return

def format_addr_filter(self, arg: str, addr: int):
return f"`{arg}`" if self.is_integer(arg) else f"`{arg}` ({addr:#x})"

def print_entry(self, entry: Section) -> None:
line_color = ""
if entry.path == "[stack]":
Expand Down
28 changes: 26 additions & 2 deletions tests/commands/vmmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,31 @@ def test_cmd_vmmap(self):
self.assertGreater(len(res.splitlines()), 1)

res = gdb.execute("vmmap stack", to_string=True)
self.assertGreater(len(res.splitlines()), 1)
assert "`stack` has no type specified. We guessed it was a name filter." in res
self.assertEqual(len(res.splitlines()), 9)

res = gdb.execute("vmmap $pc", to_string=True)
self.assertEqual(len(res.splitlines()), 2)
assert "`$pc` has no type specified. We guessed it was an address filter." in res
self.assertEqual(len(res.splitlines()), 8)

def test_cmd_vmmap_addr(self):
gef, gdb = self._gef, self._gdb
gdb.execute("start")

pc = gef.arch.register("pc")

res = gdb.execute(f"vmmap -a {pc:#x}", to_string=True)
self.assertEqual(len(res.splitlines()), 5)

res = gdb.execute("vmmap --addr $pc", to_string=True)
self.assertEqual(len(res.splitlines()), 5)

def test_cmd_vmmap_name(self):
gdb = self._gdb
gdb.execute("start")

res = gdb.execute("vmmap -n stack", to_string=True)
self.assertEqual(len(res.splitlines()), 5)

res = gdb.execute("vmmap --name stack", to_string=True)
self.assertEqual(len(res.splitlines()), 5)

0 comments on commit ba70548

Please sign in to comment.