Add command to display information about kernel syscalls (#3103)

* merge conflicts

* Fix lint errors

* ksyscalls

* Update pwndbg/commands/ksyscalls.py

* Requested changes

* docs

* merge fix

* Minor change

* Minor change in test

* Check sys_call_table symbol

---------

Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>
pull/3206/head
Allen Chang 4 months ago committed by GitHub
parent 335cc887c6
commit 26db4533aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -86,6 +86,7 @@
- [knft-list-rules](kernel/knft-list-rules.md) - Dump netfilter rules form a specific chain - [knft-list-rules](kernel/knft-list-rules.md) - Dump netfilter rules form a specific chain
- [knft-list-sets](kernel/knft-list-sets.md) - Dump netfilter sets from a specific table - [knft-list-sets](kernel/knft-list-sets.md) - Dump netfilter sets from a specific table
- [knft-list-tables](kernel/knft-list-tables.md) - Dump netfliter tables from a specific network namespace - [knft-list-tables](kernel/knft-list-tables.md) - Dump netfliter tables from a specific network namespace
- [ksyscalls](kernel/ksyscalls.md) - Displays Linux syscall table, including names and addresses of syscalls.
- [ktask](kernel/ktask.md) - Displays information about kernel tasks. - [ktask](kernel/ktask.md) - Displays information about kernel tasks.
- [kversion](kernel/kversion.md) - Outputs the kernel version (/proc/version). - [kversion](kernel/kversion.md) - Outputs the kernel version (/proc/version).
- [msr](kernel/msr.md) - Read or write to Model Specific Register (MSR) - [msr](kernel/msr.md) - Read or write to Model Specific Register (MSR)

@ -0,0 +1,23 @@
<!-- THIS PART OF THIS FILE IS AUTOGENERATED. DO NOT MODIFY IT. See scripts/generate-docs.sh -->
# ksyscalls
```text
usage: ksyscalls [-h] [syscall_name]
```
Displays Linux syscall table, including names and addresses of syscalls.
### Positional arguments
|Positional Argument|Help|
| :--- | :--- |
|syscall_name|A syscall name to search for|
### Optional arguments
|Short|Long|Help|
| :--- | :--- | :--- |
|-h|--help|show this help message and exit|
<!-- END OF AUTOGENERATED PART. Do not modify this line or the line below, they mark the end of the auto-generated part of the file. If you want to extend the documentation in a way which cannot easily be done by adding to the command help description, write below the following line. -->
<!-- ------------\>8---- ----\>8---- ----\>8------------ -->

@ -925,6 +925,7 @@ def load_commands() -> None:
import pwndbg.commands.klookup import pwndbg.commands.klookup
import pwndbg.commands.kmod import pwndbg.commands.kmod
import pwndbg.commands.knft import pwndbg.commands.knft
import pwndbg.commands.ksyscalls
import pwndbg.commands.ktask import pwndbg.commands.ktask
import pwndbg.commands.kversion import pwndbg.commands.kversion
import pwndbg.commands.leakfind import pwndbg.commands.leakfind

@ -1 +1,68 @@
"""
Displays the syscall table for kernel debugging.
"""
from __future__ import annotations from __future__ import annotations
import argparse
import pwndbg.color.message as message
import pwndbg.commands
parser = argparse.ArgumentParser(
description="Displays Linux syscall table, including names and addresses of syscalls."
)
parser.add_argument("syscall_name", nargs="?", type=str, help="A syscall name to search for")
@pwndbg.commands.Command(parser, category=pwndbg.commands.CommandCategory.KERNEL)
@pwndbg.commands.OnlyWhenQemuKernel
@pwndbg.commands.OnlyWhenPagingEnabled
@pwndbg.commands.OnlyWithKernelDebugSymbols
def ksyscalls(syscall_name=None) -> None:
# Look up the address of the sys_call_table symbol.
table_addr = pwndbg.aglib.symbol.lookup_symbol_addr("sys_call_table")
if table_addr is None:
print(
"The sys_call_table symbol was not found. This may indicate that the symbol is not available in the current build."
)
return
try:
# Compute number of syscalls in the table.
sc_count = int(
pwndbg.dbg.selected_frame().evaluate_expression(
"sizeof(sys_call_table) / sizeof(void *)"
)
)
except pwndbg.dbg_mod.Error:
print(
"The sys_call_table symbol was not found. This may indicate that the symbol is not available in the current build."
)
return
try:
print(f"Syscall table address with {sc_count} entries found at {table_addr:#x}.\n")
size_ptr = pwndbg.aglib.arch.ptrsize
print(f"{'':>4} {'Address':>18} {'Symbol'}")
# Iterate through the syscall table entries.
for i in range(sc_count):
sc_addr = pwndbg.aglib.memory.read_pointer_width(table_addr + i * size_ptr)
symbol = pwndbg.aglib.symbol.resolve_addr(sc_addr)
if syscall_name is not None:
if symbol is None or syscall_name not in symbol:
continue
print_entry = lambda: print(f"{i:>4} {hex(sc_addr):>18} {symbol or '<unknown>'}")
print_entry()
except pwndbg.dbg_mod.Error as e:
print(message.error(f"ERROR: {e}"))
return

@ -58,6 +58,16 @@ def test_command_kmod():
assert "Kernel modules address found at" in res or "The modules symbol was not found." in res assert "Kernel modules address found at" in res or "The modules symbol was not found." in res
def test_command_ksyscalls():
if not pwndbg.aglib.kernel.has_debug_symbols():
res = gdb.execute("ksyscalls", to_string=True)
assert "may only be run when debugging a Linux kernel with debug" in res
return
res = gdb.execute("ksyscalls", to_string=True)
assert "entries found at" in res or "sys_call_table symbol was not found" in res
def test_command_ktask(): def test_command_ktask():
if not pwndbg.aglib.kernel.has_debug_info(): if not pwndbg.aglib.kernel.has_debug_info():
res = gdb.execute("ktask", to_string=True) res = gdb.execute("ktask", to_string=True)

Loading…
Cancel
Save