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

Add an "--all" option to the got command #1101

Merged
merged 2 commits into from
Jun 1, 2024
Merged
Changes from all 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
13 changes: 12 additions & 1 deletion docs/commands/got.md
Original file line number Diff line number Diff line change
@@ -6,9 +6,11 @@ The `got` command optionally takes function names and filters the output display
matching functions.

```text
gef➤ got
gef➤ got [--all] [filters]
```

`--all` Print the GOT for all shared objects in addition to the executable file

![gef-got](https://i.imgur.com/554ebM3.png)

The applied filter partially matches the name of the functions, so you can do something like this.
Grazfather marked this conversation as resolved.
Show resolved Hide resolved
@@ -28,3 +30,12 @@ gef➤ got str get
```

![gef-got-multi-filter](https://i.imgur.com/7L2uLt8.png)

```text
gef➤ got --all str get
```

Print relocatable symbols matching "str" or "get" in the executable and all shared object files.

**Note**: Because gdbserver does not canonicalize paths, the --all option does not work correctly
for remote debugging. See gdb bug [23764](https://sourceware.org/bugzilla/show_bug.cgi?id=23764)
21 changes: 17 additions & 4 deletions gef.py
Original file line number Diff line number Diff line change
@@ -9269,11 +9269,24 @@ def build_line(self, name: str, color: str, address_val: int, got_address: int)
return line

@only_if_gdb_running
def do_invoke(self, argv: List[str]) -> None:
@parse_arguments({"symbols": [""]}, {"--all": False})
def do_invoke(self, _: List[str], **kwargs: Any) -> None:
args : argparse.Namespace = kwargs["arguments"]
if args.all:
vmmap = gef.memory.maps
mapfiles = set(mapfile.path for mapfile in vmmap if
pathlib.Path(mapfile.realpath).is_file() and
mapfile.permission & Permission.EXECUTE)
for mapfile in mapfiles:
self.print_got_for(mapfile, args.symbols)
hugsy marked this conversation as resolved.
Show resolved Hide resolved
else:
self.print_got_for(str(gef.session.file), args.symbols)

def print_got_for(self, file: str, argv: List[str]) -> None:
readelf = gef.session.constants["readelf"]

elf_file = str(gef.session.file)
elf_virtual_path = str(gef.session.file)
elf_file = file
elf_virtual_path = file

func_names_filter = argv if argv else []
vmmap = gef.memory.maps
@@ -9297,7 +9310,7 @@ def do_invoke(self, argv: List[str]) -> None:
lines = gef_execute_external([readelf, "--wide", "--relocs", elf_file], as_list=True)
jmpslots = [line for line in lines if "JUMP" in line]

gef_print(f"\nGOT protection: {relro_status} | GOT functions: {len(jmpslots)}\n ")
gef_print(f"{titlify(file)}\n\nGOT protection: {relro_status} | GOT functions: {len(jmpslots)}\n ")

for line in jmpslots:
address, _, _, _, name = line.split()[:5]
33 changes: 33 additions & 0 deletions tests/commands/got.py
Original file line number Diff line number Diff line change
@@ -35,3 +35,36 @@ def test_cmd_got(self):
res = gdb.execute("got printf", to_string=True)
self.assertIn("printf", res)
self.assertNotIn("strcpy", res)
self.assertNotIn("/libc", res)

def checksyms(lines):
if not lines:
return None
if "format-string-helper.out" in lines[0]:
res = ''.join(lines)
self.assertIn(" printf", res)
self.assertNotIn(" strcpy", res)
return "format-string-helper.out"
if "/libc" in lines[0]:
res = ''.join(lines)
self.assertNotIn(" printf", res)
self.assertNotIn(" strcpy", res)
return "libc"
return None

res = gdb.execute("got --all printf", to_string=True)
# Keep a list of output blocks describing files mapped in the process
checked_sections = []
# Iterate over lines of output and assemble blocks. When a new block
# is found, or when the end of output is reached, check the output
# block for symbols expected in that block.
lines = []
for line in res.splitlines():
Grazfather marked this conversation as resolved.
Show resolved Hide resolved
if line.startswith("─"):
checked_sections.append(checksyms(lines))
lines = []
lines.append(line)
checked_sections.append(checksyms(lines))
# Make sure that both the executable and libc sections were found.
self.assertIn("format-string-helper.out", checked_sections)
self.assertIn("libc", checked_sections)