Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions docs/commands/vmmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,28 @@ place). For example, you can learn that ELF running on SPARC architectures alway
and `heap` sections set as Read/Write/Execute.

`vmmap` can accept multiple arguments, either patterns to match again mapping names, or addresses
to determine which section it belongs to:
to determine which section it belongs to, or the permissions of the sections to match:
Comment thread
ValekoZ marked this conversation as resolved.

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
3. `-p` / `--perms`:
- filter based on section permissions
4. If nothing is specified, it prints a warning and guesses the type

![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.
The address can be also be given in the form of a register or variable:

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

Using perms:
Comment thread
ValekoZ marked this conversation as resolved.
Outdated

![vmmap-perms](https://github.com/user-attachments/assets/c34822d3-2369-464f-aafa-87113b293174)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can add this as an asset? Can we count on these sticking around forever?

Copy link
Copy Markdown
Owner

@hugsy hugsy May 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👆
Those don't render.

image


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)
39 changes: 34 additions & 5 deletions gef.py
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,21 @@ def from_info_mem(cls, perm_str: str) -> "Permission":
if "x" in perm_str: perm |= Permission.EXECUTE
return perm

@classmethod
def from_filter_repr(cls, filter_str: str) -> list["Permission"]:
perms = [cls(0)]
Comment thread
ValekoZ marked this conversation as resolved.
Outdated

for k in range(3):
for i in range(len(perms)):
p = cls(1 << (2-k))
if filter_str[k] == "rwx"[k]:
perms[i] |= p
elif filter_str[k] == "?":
perms.append(perms[i] | p)

return perms



class Section:
"""GEF representation of process memory sections."""
Expand Down Expand Up @@ -8910,7 +8925,9 @@ class VMMapCommand(GenericCommand):
_example_ = f"{_cmdline_} libc"

@only_if_gdb_running
@parse_arguments({"unknown_types": [""]}, {("--addr", "-a"): [""], ("--name", "-n"): [""]})
@parse_arguments({"unknown_types": [""]}, {("--addr", "-a"): [""],
("--name", "-n"): [""],
("--perms", "-p"): [""]})
def do_invoke(self, _: list[str], **kwargs: Any) -> None:
args : argparse.Namespace = kwargs["arguments"]
vmmap = gef.memory.maps
Expand All @@ -8920,6 +8937,10 @@ def do_invoke(self, _: list[str], **kwargs: Any) -> None:

addrs: dict[str, int] = {x: parse_address(x) for x in args.addr}
names: list[str] = [x for x in args.name]
perms: set[Permission] = set()

for x in args.perms:
Comment thread
ValekoZ marked this conversation as resolved.
Outdated
perms = perms.union(Permission.from_filter_repr(x))

for arg in args.unknown_types:
if not arg:
Expand All @@ -8931,12 +8952,19 @@ def do_invoke(self, _: list[str], **kwargs: Any) -> None:
addr = safe_parse_and_eval(arg)

if addr is None:
if arg[0] in 'r-?' and \
arg[1] in 'w-?' and \
arg[2] in 'x-?':
Comment thread
ValekoZ marked this conversation as resolved.
Outdated
perms = perms.union(Permission.from_filter_repr(arg))
warn(f"`{arg}` has no type specified. We guessed it was a perm filter.")
continue

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.")
warn("You can use --name, --addr or --perms before the filter value for specifying its type manually.")
gef_print()

if not gef.config["gef.disable_color"]:
Expand All @@ -8953,12 +8981,13 @@ def do_invoke(self, _: list[str], **kwargs: Any) -> None:
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])}]"
perms_filter = [f"perms = {x}" for x in perms if entry.permission == x]
filter_content = f"[{' & '.join([*names_filter, *addrs_filter, *perms_filter])}]"

if not names and not addrs:
if not names and not addrs and not perms:
self.print_entry(entry)

elif names_filter or addrs_filter:
elif names_filter or addrs_filter or perms_filter:
if filter_content != last_printed_filter:
gef_print() # skip a line between different filters
gef_print(Color.greenify(filter_content))
Expand Down
20 changes: 20 additions & 0 deletions tests/api/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,23 @@ def test_func_process_lookup_path(self):
assert "libc" in pathlib.Path(libc.path).name

assert root.eval("process_lookup_path('stack')") is not None

def test_func_from_filter_repr(self):
root = self._conn.root
Permission = root.eval("Permission")

none = Permission.from_filter_repr('---')
Comment thread
ValekoZ marked this conversation as resolved.
Outdated
assert len(none) == 1
assert none[0] == Permission.NONE

all_readable_perms = Permission.from_filter_repr("r??")
assert all(x & Permission.READ for x in all_readable_perms)
assert len(all_readable_perms) == 4

all_writable_perms = Permission.from_filter_repr("?w?")
assert all(x & Permission.WRITE for x in all_writable_perms)
assert len(all_writable_perms) == 4

all_executable_perms = Permission.from_filter_repr("??x")
assert all(x & Permission.EXECUTE for x in all_executable_perms)
assert len(all_executable_perms) == 4
28 changes: 28 additions & 0 deletions tests/commands/vmmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ def test_cmd_vmmap(self):
assert "`$pc` has no type specified. We guessed it was an address filter." in res
self.assertEqual(len(res.splitlines()), 8)

res = gdb.execute("vmmap r-?", to_string=True)
assert "`r-?` has no type specified. We guessed it was a perm filter." in res
self.assertGreater(len(res.splitlines()), 3)

def test_cmd_vmmap_addr(self):
gef, gdb = self._gef, self._gdb
gdb.execute("start")
Expand All @@ -48,3 +52,27 @@ def test_cmd_vmmap_name(self):

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

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

res1 = gdb.execute("vmmap -p r?-", to_string=True)
lines1 = res1.splitlines()
self.assertGreater(len(lines1), 5)
for line in lines1:
if line[:2] != "0x":
continue
perm_str = line.split()[3]
assert perm_str[0] == 'r'
Comment thread
ValekoZ marked this conversation as resolved.
Outdated
assert perm_str[1] in ('w', '-')
assert perm_str[2] == '-'

res2 = gdb.execute("vmmap --perms r?-", to_string=True)
assert res1 == res2

res = gdb.execute("vmmap -p rw-", to_string=True)
self.assertGreater(len(res.splitlines()), 5)

res = gdb.execute("vmmap --perms rw-", to_string=True)
self.assertGreater(len(res.splitlines()), 5)