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-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
- [ksyscalls](kernel/ksyscalls.md) - Displays Linux syscall table, including names and addresses of syscalls.
- [ktask](kernel/ktask.md) - Displays information about kernel tasks.
- [kversion](kernel/kversion.md) - Outputs the kernel version (/proc/version).
- [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.kmod
import pwndbg.commands.knft
import pwndbg.commands.ksyscalls
import pwndbg.commands.ktask
import pwndbg.commands.kversion
import pwndbg.commands.leakfind

@ -1 +1,68 @@
"""
Displays the syscall table for kernel debugging.
"""
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
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():
if not pwndbg.aglib.kernel.has_debug_info():
res = gdb.execute("ktask", to_string=True)

Loading…
Cancel
Save