diff --git a/docs/commands/heap.md b/docs/commands/heap.md index 835312656..0dc63129a 100644 --- a/docs/commands/heap.md +++ b/docs/commands/heap.md @@ -30,6 +30,14 @@ gef➤ gef config gef.bruteforce_main_arena True Note that this might take a few seconds to complete. If GEF does find the symbol you can then calculate the offset to the libc base address and save it in the config. +Sometimes, the dump might not contain proper info to help GEF find the libc version, which results in +failure to parse the arena information. In this case, you can try to provide GEF a specific libc +version to use with the following command: + +```text +gef➤ gef config gef.libc_version 2.31 +``` + ### `heap chunks` command Displays all the chunks from the `heap` section of the current arena. diff --git a/gef.py b/gef.py index 8e9e4d2f3..9b80293b9 100644 --- a/gef.py +++ b/gef.py @@ -9587,6 +9587,7 @@ def __init__(self) -> None: gef.config["gef.show_deprecation_warnings"] = GefSetting(True, bool, "Toggle the display of the `deprecated` warnings") gef.config["gef.buffer"] = GefSetting(True, bool, "Internally buffer command output until completion") gef.config["gef.bruteforce_main_arena"] = GefSetting(False, bool, "Allow bruteforcing main_arena symbol if everything else fails") + gef.config["gef.libc_version"] = GefSetting("", str, "Specify libc version when auto-detection fails") gef.config["gef.main_arena_offset"] = GefSetting("", str, "Offset from libc base address to main_arena symbol (int or hex). Set to empty string to disable.") self.commands : Dict[str, GenericCommand] = collections.OrderedDict() @@ -11166,8 +11167,14 @@ def __str__(self) -> str: def version(self) -> Optional[Tuple[int, int]]: if not is_alive(): return None + if not self._version: self._version = GefLibcManager.find_libc_version() + + # Whenever auto-detection fails, we use the user-provided version. + if self._version == (0, 0) and gef.config["gef.libc_version"] != "": + return tuple([int(v) for v in gef.config["gef.libc_version"].split(".")]) + return self._version @staticmethod diff --git a/tests/config/__init__.py b/tests/config/__init__.py index 1d35df3ec..d2f59d67f 100644 --- a/tests/config/__init__.py +++ b/tests/config/__init__.py @@ -2,7 +2,7 @@ Test GEF configuration parameters. """ -from tests.utils import gdb_run_cmd +from tests.utils import gdb_run_cmd, gdb_start_silent_cmd from tests.utils import GefUnitTestGeneric @@ -49,3 +49,23 @@ def test_config_type_validator(self): res = gdb_run_cmd("gef config gef.debug 0") self.assertNoException(res) self.assertNotIn("[!]", res) + + def test_config_libc_version(self): + """Check setting libc version.""" + res = gdb_run_cmd("gef config gef.libc_version") + self.assertNoException(res) + self.assertNotIn("[!]", res) + + res = gdb_run_cmd("gef config gef.libc_version", before=["gef config gef.libc_version 2.31"]) + self.assertNoException(res) + self.assertNotIn("[!]", res) + self.assertIn('gef.libc_version (str) = "2.31"', res) + + res = gdb_run_cmd("gef config gef.libc_version", before=["gef config gef.libc_version 2.31", "gef config gef.libc_version ''"]) + self.assertNoException(res) + self.assertNotIn("[!]", res) + self.assertIn('gef.libc_version (str) = ""', res) + + res = gdb_start_silent_cmd("python print(gef.libc.version)", before=["gef config gef.libc_version 2.31"]) + self.assertNoException(res) + self.assertNotIn("[!]", res)