-
-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Description/Motivation/Screenshots This PR is the GEF-Extras counter-part of hugsy/gef#1040 Also since `kallsyms` was removed from GEF (in preparation for the kernel module), it was added here with its tests ## How Has This Been Tested ? "Tested" indicates that the PR works *and* the unit test (i.e. `make test`) run passes without issue. * [x] x86-32 * [x] x86-64 * [ ] ARM * [x] AARCH64 * [ ] MIPS * [ ] POWERPC * [ ] SPARC * [ ] RISC-V ## Checklist <!-- N.B.: Your patch won't be reviewed unless fulfilling the following base requirements: --> <!--- Put an `x` in all the boxes that are complete, or that don't apply --> * [x] My code follows the code style of this project. * [x] My change includes a change to the documentation, if required. * [x] If my change adds new code, [adequate tests](https://hugsy.github.io/gef/testing) have been added. * [x] I have read and agree to the [CONTRIBUTING](https://github.com/hugsy/gef/blob/main/.github/CONTRIBUTING.md) document. --------- Co-authored-by: Grazfather <[email protected]>
- Loading branch information
1 parent
4b98e62
commit a669c30
Showing
18 changed files
with
524 additions
and
363 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,15 +2,18 @@ name: Validation | |
|
||
on: | ||
pull_request: | ||
|
||
branches: | ||
- main | ||
|
||
jobs: | ||
pre_commit: | ||
name: Check formatting | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions/setup-python@v3 | ||
- uses: actions/[email protected] | ||
with: | ||
python-version: "3.8" | ||
- uses: pre-commit/[email protected] | ||
|
||
docs_link_check: | ||
|
@@ -20,9 +23,9 @@ jobs: | |
contents: read | ||
steps: | ||
- name: checkout | ||
uses: actions/checkout@v2 | ||
uses: actions/checkout@v4 | ||
- name: Check links | ||
uses: lycheeverse/lychee-action@v1.4.1 | ||
uses: lycheeverse/lychee-action@v1.9.1 | ||
env: | ||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} | ||
with: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
|
||
__AUTHOR__ = "hugsy" | ||
__VERSION__ = 0.2 | ||
__LICENSE__ = "MIT" | ||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
""" | ||
Collection of functions and commands to manipulate kernel symbols | ||
""" | ||
|
||
__AUTHOR__ = "hugsy" | ||
__VERSION__ = 0.1 | ||
__LICENSE__ = "MIT" | ||
|
||
import argparse | ||
from typing import TYPE_CHECKING, Any, List | ||
|
||
if TYPE_CHECKING: | ||
from .. import * # this will allow linting for GEF and GDB | ||
|
||
|
||
@register | ||
class SolveKernelSymbolCommand(GenericCommand): | ||
"""Solve kernel symbols from kallsyms table.""" | ||
|
||
_cmdline_ = "ksymaddr" | ||
_syntax_ = f"{_cmdline_} SymbolToSearch" | ||
_example_ = f"{_cmdline_} prepare_creds" | ||
|
||
@parse_arguments({"symbol": ""}, {}) | ||
def do_invoke(self, _: List[str], **kwargs: Any) -> None: | ||
def hex_to_int(num): | ||
try: | ||
return int(num, 16) | ||
except ValueError: | ||
return 0 | ||
|
||
args: argparse.Namespace = kwargs["arguments"] | ||
if not args.symbol: | ||
self.usage() | ||
return | ||
sym = args.symbol | ||
with open("/proc/kallsyms", "r") as f: | ||
syms = [line.strip().split(" ", 2) for line in f] | ||
matches = [ | ||
(hex_to_int(addr), sym_t, " ".join(name.split())) | ||
for addr, sym_t, name in syms | ||
if sym in name | ||
] | ||
for addr, sym_t, name in matches: | ||
if sym == name.split()[0]: | ||
ok(f"Found matching symbol for '{name}' at {addr:#x} (type={sym_t})") | ||
else: | ||
warn( | ||
f"Found partial match for '{sym}' at {addr:#x} (type={sym_t}): {name}" | ||
) | ||
if not matches: | ||
err(f"No match for '{sym}'") | ||
elif matches[0][0] == 0: | ||
err( | ||
"Check that you have the correct permissions to view kernel symbol addresses" | ||
) | ||
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import os | ||
import pathlib | ||
import random | ||
import subprocess | ||
import tempfile | ||
import time | ||
import unittest | ||
|
||
import rpyc | ||
|
||
from .utils import GEF_EXTRAS_SCRIPTS_PATH, debug_target | ||
|
||
COVERAGE_DIR = os.getenv("COVERAGE_DIR", "") | ||
GEF_PATH = pathlib.Path(os.getenv("GEF_PATH", "../gef/gef.py")).absolute() | ||
RPYC_GEF_PATH = GEF_PATH.parent / "scripts/remote_debug.py" | ||
RPYC_HOST = "localhost" | ||
RPYC_PORT = 18812 | ||
RPYC_SPAWN_TIME = 1.0 | ||
|
||
|
||
class RemoteGefUnitTestGeneric(unittest.TestCase): | ||
""" | ||
The base class for GEF test cases. This will create the `rpyc` environment to programmatically interact with | ||
GDB and GEF in the test. | ||
""" | ||
|
||
def setUp(self) -> None: | ||
self._coverage_file = None | ||
if not hasattr(self, "_target"): | ||
setattr(self, "_target", debug_target("default")) | ||
else: | ||
assert isinstance(self._target, pathlib.Path) # type: ignore pylint: disable=E1101 | ||
assert self._target.exists() # type: ignore pylint: disable=E1101 | ||
self._port = random.randint(1025, 65535) | ||
self._commands = "" | ||
|
||
if COVERAGE_DIR: | ||
self._coverage_file = pathlib.Path(COVERAGE_DIR) / os.getenv( | ||
"PYTEST_XDIST_WORKER", "gw0" | ||
) | ||
self._commands += f""" | ||
pi import coverage | ||
pi cov = coverage.Coverage(data_file="{self._coverage_file}", auto_data=True, branch=True) | ||
pi cov.start() | ||
""" | ||
|
||
self._commands += f""" | ||
source {GEF_PATH} | ||
gef config gef.debug True | ||
gef config gef.propagate_debug_exception True | ||
gef config gef.disable_color True | ||
gef config gef.extra_plugins_dir {GEF_EXTRAS_SCRIPTS_PATH} | ||
source {RPYC_GEF_PATH} | ||
pi start_rpyc_service({self._port}) | ||
""" | ||
|
||
self._initfile = tempfile.NamedTemporaryFile(mode="w", delete=False) | ||
self._initfile.write(self._commands) | ||
self._initfile.flush() | ||
self._command = [ | ||
"gdb", | ||
"-q", | ||
"-nx", | ||
"-ex", | ||
f"source {self._initfile.name}", | ||
"--", | ||
str(self._target.absolute()), # type: ignore pylint: disable=E1101 | ||
] | ||
self._process = subprocess.Popen(self._command) | ||
assert self._process.pid > 0 | ||
time.sleep(RPYC_SPAWN_TIME) | ||
self._conn = rpyc.connect( | ||
RPYC_HOST, | ||
self._port, | ||
) | ||
self._gdb = self._conn.root.gdb | ||
self._gef = self._conn.root.gef | ||
return super().setUp() | ||
|
||
def tearDown(self) -> None: | ||
if COVERAGE_DIR: | ||
self._gdb.execute("pi cov.stop()") | ||
self._gdb.execute("pi cov.save()") | ||
self._conn.close() | ||
self._process.terminate() | ||
return super().tearDown() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
""" | ||
`ksymaddr` command test module | ||
""" | ||
|
||
|
||
from tests.base import RemoteGefUnitTestGeneric | ||
|
||
|
||
class KsymaddrCommand(RemoteGefUnitTestGeneric): | ||
"""`ksymaddr` command test module""" | ||
|
||
cmd = "ksymaddr" | ||
|
||
def test_cmd_ksymaddr(self): | ||
gdb = self._gdb | ||
res = gdb.execute(f"{self.cmd} prepare_kernel_cred", to_string=True) | ||
self.assertIn("Found matching symbol for 'prepare_kernel_cred'", res) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.