From 466e40aa0867318410dd05da45d032dc8f05293b Mon Sep 17 00:00:00 2001 From: Grazfather Date: Sat, 16 Dec 2023 18:44:24 +0000 Subject: [PATCH] Add memory manager map parsing tests --- gef.py | 5 ++-- tests/api/misc.py | 56 +++++++++++++++++++++++++++++++++--- tests/commands/gef_remote.py | 30 ++++++++++--------- 3 files changed, 72 insertions(+), 19 deletions(-) diff --git a/gef.py b/gef.py index 8d0de9f82..80350a5bd 100644 --- a/gef.py +++ b/gef.py @@ -10393,10 +10393,11 @@ def read_ascii_string(self, address: int) -> Optional[str]: @property def maps(self) -> List[Section]: if not self.__maps: - self.__maps = self.__parse_maps() + self.__maps = self._parse_maps() return self.__maps - def __parse_maps(self) -> List[Section]: + @staticmethod + def _parse_maps() -> List[Section]: """Return the mapped memory sections. If the current arch has its maps method defined, then defer to that to generated maps, otherwise, try to figure it out from procfs, then info sections, then monitor info diff --git a/tests/api/misc.py b/tests/api/misc.py index 51b4a4383..132e6b821 100644 --- a/tests/api/misc.py +++ b/tests/api/misc.py @@ -12,7 +12,12 @@ _target, gdb_start_silent_cmd, gdb_test_python_method, + gdb_run_cmd, + gdbserver_session, + qemuuser_session, GefUnitTestGeneric, + GDBSERVER_DEFAULT_HOST, + GDBSERVER_DEFAULT_PORT, ) @@ -26,7 +31,6 @@ def test_func_which(self): res = gdb_test_python_method("which('__IDontExist__')") self.assertIn("Missing file `__IDontExist__`", res) - def test_func_gef_convenience(self): func = "gef_convenience('meh')" res = gdb_test_python_method(func, target=_target("default")) @@ -41,18 +45,62 @@ def test_func_parse_address(self): res = gdb_test_python_method(func) self.assertException(res) + def test_func_parse_permissions(self): + func = "Permission.from_info_sections('ALLOC LOAD READONLY CODE HAS_CONTENTS')" + res = gdb_test_python_method(func) + self.assertNoException(res) + + func = "Permission.from_process_maps('r--')" + res = gdb_test_python_method(func) + self.assertNoException(res) + + func = "Permission.from_monitor_info_mem('-r-')" + res = gdb_test_python_method(func) + self.assertNoException(res) + + func = "Permission.from_info_mem('rw')" + res = gdb_test_python_method(func) + self.assertNoException(res) + def test_func_parse_maps(self): - func = "Permission.from_info_sections(' [10] 0x555555574000->0x55555557401b at 0x00020000: .init ALLOC LOAD READONLY CODE HAS_CONTENTS')" + func = "list(GefMemoryManager.parse_procfs_maps())" res = gdb_test_python_method(func) self.assertNoException(res) + assert "Section" in res - func = "Permission.from_process_maps('0x0000555555554000 0x0000555555574000 0x0000000000000000 r-- /usr/bin/bash')" + func = "list(GefMemoryManager.parse_gdb_info_sections())" res = gdb_test_python_method(func) self.assertNoException(res) + assert "Section" in res + + # When in a gef-remote session `parse_gdb_info_sections` should work to + # query the memory maps + port = GDBSERVER_DEFAULT_PORT + 1 + before = [f"gef-remote {GDBSERVER_DEFAULT_HOST} {port}"] + with gdbserver_session(port=port) as _: + func = "list(GefMemoryManager.parse_gdb_info_sections())" + res = gdb_test_python_method(func) + self.assertNoException(res) + assert "Section" in res - func = "Permission.from_info_mem('ffffff2a65e0b000-ffffff2a65e0c000 0000000000001000 -r-')" + # When in a gef-remote qemu-user session `parse_gdb_info_sections` + # should work to query the memory maps + port = GDBSERVER_DEFAULT_PORT + 2 + target = _target("default") + before = [ + f"gef-remote --qemu-user --qemu-binary {target} {GDBSERVER_DEFAULT_HOST} {port}"] + with qemuuser_session(port=port) as _: + func = "list(GefMemoryManager.parse_gdb_info_sections())" + res = gdb_test_python_method(func) + self.assertNoException(res) + assert "Section" in res + + # Running the _parse_maps method should just find the correct one + func = "list(GefMemoryManager._parse_maps())" res = gdb_test_python_method(func) self.assertNoException(res) + assert "Section" in res + @pytest.mark.slow @pytest.mark.online diff --git a/tests/commands/gef_remote.py b/tests/commands/gef_remote.py index 7c628cccc..56429745d 100644 --- a/tests/commands/gef_remote.py +++ b/tests/commands/gef_remote.py @@ -3,45 +3,49 @@ """ -from tests.utils import (GefUnitTestGeneric, _target, gdb_run_cmd, - gdbserver_session, qemuuser_session) - -GDBSERVER_PREFERED_HOST = "localhost" -GDBSERVER_PREFERED_PORT = 1234 +from tests.utils import ( + GefUnitTestGeneric, + _target, + gdb_run_cmd, + gdbserver_session, + qemuuser_session, + GDBSERVER_DEFAULT_HOST, + GDBSERVER_DEFAULT_PORT, +) class GefRemoteCommand(GefUnitTestGeneric): """`gef_remote` command test module""" def test_cmd_gef_remote(self): - port = GDBSERVER_PREFERED_PORT + 1 - before = [f"gef-remote {GDBSERVER_PREFERED_HOST} {port}"] + port = GDBSERVER_DEFAULT_PORT + 1 + before = [f"gef-remote {GDBSERVER_DEFAULT_HOST} {port}"] with gdbserver_session(port=port) as _: res = gdb_run_cmd( "pi print(gef.session.remote)", before=before) self.assertNoException(res) self.assertIn( - f"RemoteSession(target='{GDBSERVER_PREFERED_HOST}:{port}', local='/tmp/", res) + f"RemoteSession(target='{GDBSERVER_DEFAULT_HOST}:{port}', local='/tmp/", res) self.assertIn(", qemu_user=False)", res) def test_cmd_gef_remote_qemu_user(self): - port = GDBSERVER_PREFERED_PORT + 2 + port = GDBSERVER_DEFAULT_PORT + 2 target = _target("default") before = [ - f"gef-remote --qemu-user --qemu-binary {target} {GDBSERVER_PREFERED_HOST} {port}"] + f"gef-remote --qemu-user --qemu-binary {target} {GDBSERVER_DEFAULT_HOST} {port}"] with qemuuser_session(port=port) as _: res = gdb_run_cmd( "pi print(gef.session.remote)", before=before) self.assertNoException(res) self.assertIn( - f"RemoteSession(target='{GDBSERVER_PREFERED_HOST}:{port}', local='/tmp/", res) + f"RemoteSession(target='{GDBSERVER_DEFAULT_HOST}:{port}', local='/tmp/", res) self.assertIn(", qemu_user=True)", res) def test_cmd_target_remote(self): - port = GDBSERVER_PREFERED_PORT + 3 - before = [f"target remote {GDBSERVER_PREFERED_HOST}:{port}"] + port = GDBSERVER_DEFAULT_PORT + 3 + before = [f"target remote {GDBSERVER_DEFAULT_HOST}:{port}"] with gdbserver_session(port=port) as _: res = gdb_run_cmd( "pi print(gef.session.remote)", before=before)