repl ¤
The Pwndbg REPL that is the interface to all debugging on LLDB.
Pwndbg has an event system that allows it to react to events in the process being debugged, such as when new executable modules get added to the its address space, when the value of memory and registers change, and pretty much all possible changes to its execution state. We'd like to have the event system work the same way under LLDB as it does under GDB.
Fortunately for us, the events types that are native to LLDB map really well to the event types in GDB and Pwndbg. Very, very unfortunately for us, however, that's basically where our luck ends.
LLDB, as of version 18, only provides two ways to capture events: registering directly with the broadcaster, or registering globally. The former is not available to us in the standard LLDB REPL, as we don't get access to the process object until after it's been launched1. Likewise for the latter, as the interactive debugger will register to receive the global process state change events before everyone else, and LLDB doesn't allow for multiple listeners for the same event bits in the same event class2.
This leaves us with handling process management ourselves as the only option we really have to implement event dispatch in Pwndbg. Easy, right? We can just hijack the commands that deal with target and process creation, and leave everything else untouched. Unfortunately for us, again, shadowing builtin commands is simply not allowed3.
So, really, all that's left for us is either implement our own REPL, or get rid of the event system.
Modules:
-
io
–For our REPL, we need to drive our own I/O with the process being debugged. This
-
proc
– -
readline
–Readline interface for the Pwndbg LLDB REPL.
Classes:
-
EventRelay
–The event system that is sensible for the REPL process driver to use isn't
-
YieldExecDirect
–Execute the given command directly, on behalf of the user.
-
YieldInteractive
–Prompt the user for the next command.
-
PwndbgController
–Class providing interfaces for a client to control the behavior of Pwndbg
Functions:
-
lex_args
–Splits the arguments, respecting quotation marks.
-
show_greeting
–Show the Pwndbg greeting, the same way the GDB version of Pwndbg would. This
-
run
–Runs the Pwndbg CLI through the given asynchronous controller.
-
exec_repl_command
–Parses and runs the given command, returning whether the event loop should continue.
-
parse
–Parses a list of string arguments into an object containing the parsed
-
run_ipython_shell
– -
target_create
–Creates a new target, registers it with the Pwndbg LLDB implementation, and
-
process_launch
–Launches a process with the given arguments.
-
process_attach
–Attaches to a process with the given arguments.
-
attach
–Attaches to a process with the given name or pid based on regex match.
-
process_connect
–Connects to the given remote process.
-
gdb_remote
–Like
process_connect
, but more lenient with the remote URL format. -
continue_process
–Continues the execution of a process.
Attributes:
-
show_tip
– -
LLDB_EXCLUSIVE
– -
target_create_ap
– -
target_create_unsupported
– -
process_launch_ap
– -
process_launch_unsupported
– -
process_attach_ap
– -
process_attach_unsupported
– -
process_connect_ap
– -
gdb_remote_ap
– -
continue_ap
– -
continue_unsupported
–
show_tip module-attribute
¤
LLDB_EXCLUSIVE module-attribute
¤
LLDB_EXCLUSIVE = [
("script", lambda cmd: startswith("sc") and startswith(cmd)),
("expression", lambda cmd: startswith("e") and startswith(cmd)),
]
target_create_unsupported module-attribute
¤
target_create_unsupported = [
"build",
"core",
"no-dependents",
"remote-file",
"symfile",
"version",
]
process_launch_unsupported module-attribute
¤
process_launch_unsupported = [
"disable-aslr",
"script-class",
"environment",
"plugin",
"shell-expand-args",
"arch",
"shell",
"stderr",
"stdin",
"structured-data-key",
"no-stdio",
"stdout",
"tty",
"structured-data-value",
"working-dir",
]
process_attach_unsupported module-attribute
¤
process_attach_unsupported = [
"python-class",
"plugin",
"structured-data-key",
"structured-data-value",
]
EventRelay ¤
EventRelay(dbg: LLDB)
Bases: EventHandler
The event system that is sensible for the REPL process driver to use isn't an exact match with the one used by the rest of Pwndbg. They're close, but there's a bit of work we have to do to properly convey certain events.
Methods:
-
created
– -
suspended
– -
resumed
– -
exited
– -
modules_loaded
–
Attributes:
-
dbg
– -
ignore_resumed
–
YieldExecDirect ¤
Execute the given command directly, on behalf of the user.
YieldInteractive ¤
Prompt the user for the next command.
PwndbgController ¤
Class providing interfaces for a client to control the behavior of Pwndbg asynchronously.
Methods:
-
interactive
–Runs a single interactive round, in which the user is prompted for a
-
execute
–Runs the given command, and displays its output to the user.
-
execute_and_capture
–Runs the given command, and captures its output as a byte string.
interactive ¤
Runs a single interactive round, in which the user is prompted for a command from standard input and readline
, and whatever command they type in is executed.
execute ¤
Runs the given command, and displays its output to the user.
Interactivity¤
Some commands - such as lldb
and ipi
- start interactive prompts when they are run, and issuing them through this command will not change that behavior.
execute_and_capture ¤
Runs the given command, and captures its output as a byte string.
Interactivity¤
Same caveats apply as in execute
.
Reliabily of Capture¤
Some Pwndbg commands currently do not have their outputs captured, even when run through this command. It is expected that this will be improved in the future, but, as as general rule, clients should not rely on the output of the command being available.
show_greeting ¤
Show the Pwndbg greeting, the same way the GDB version of Pwndbg would. This one is considerably simpler than the GDB version, however, as we control the lifetime of the program, we know exactly when the greeting needs to be shown, so we don't bother with any of the lifetime checks.
run ¤
run(
controller: Callable[[PwndbgController], Coroutine[Any, Any, None]],
debug: bool = False,
) -> None
Runs the Pwndbg CLI through the given asynchronous controller.
exec_repl_command ¤
exec_repl_command(
line: str,
lldb_out_target: BinaryIO,
dbg: LLDB,
driver: ProcessDriver,
relay: EventRelay,
) -> bool
Parses and runs the given command, returning whether the event loop should continue.
parse ¤
Parses a list of string arguments into an object containing the parsed data.
target_create ¤
target_create(args: list[str], dbg: LLDB) -> None
Creates a new target, registers it with the Pwndbg LLDB implementation, and sets up listeners for it.
process_launch ¤
process_launch(
driver: ProcessDriver, relay: EventRelay, args: list[str], dbg: LLDB
) -> None
Launches a process with the given arguments.
process_attach ¤
process_attach(
driver: ProcessDriver, relay: EventRelay, args: list[str], dbg: LLDB
) -> None
Attaches to a process with the given arguments.
attach ¤
attach(
driver: ProcessDriver, relay: EventRelay, args: list[str], dbg: LLDB
) -> None
Attaches to a process with the given name or pid based on regex match. Used for _regexp-attach <pid|name>
(alias for attach <pid|name>
) Note: for some reason, attach
does not really take a regex for process name.
process_connect ¤
process_connect(
driver: ProcessDriver, relay: EventRelay, args: list[str], dbg: LLDB
) -> None
Connects to the given remote process.
gdb_remote ¤
gdb_remote(
driver: ProcessDriver, relay: EventRelay, args: list[str], dbg: LLDB
) -> None
Like process_connect
, but more lenient with the remote URL format.
continue_process ¤
continue_process(driver: ProcessDriver, args: list[str], dbg: LLDB) -> None
Continues the execution of a process.