`pwn errno` only ever consulted the host's errno module, so numbers from a
target of a different architecture were reported as unknown (131 is
ECONNRESET on mips but unused here).
Add -c/--context, built on the same context_arg helper as asm, constgrep and
cyclic: number and name lookups now resolve against pwnlib.constants for the
requested os/arch, and --list/--search honour the flag too. --search also
matches errno names, so the flag stays useful on hosts whose strerror cannot
spell out the target's codes.
Covered with three inline doctests, as TESTING.md asks for.
* Test on Python 3.15
* Use `RLIM_INFINITY` instead of `-1` constant for rlimit modification
Python 3.15 warns against using negative values instead of the constant:
DeprecationWarning: Use RLIM_INFINITY instead of negative limit value.
It has been available since Python 2.
* Update CHANGELOG
* docs: fix argument names in regsort, ROP.raw and SSHPath docstrings
regsort documented random instead of randomize, ROP.raw documented data
instead of value, and SSHPath documented name instead of path.
* Add PR number to CHANGELOG entry
* docs: remove changelog entry for docstring fixes
* gdb.corefile: Run gdb directly to prevent detach race
`attach()` waits for the debugger to attach by polling the `TracerPid` regularly. `corefile()` runs `detach` in gdb after dumping the core, so the debugger might attach and detach between two `TracerPid` polls and `wait_for_debugger()` thinks gdb exited before attaching and returns `None` as gdb's pid is no longer valid.
Later `corefile()` ran `psutil.Process(pid).wait()` with `pid = None` which effectively waited on the Python process itself to exit.
This caused a hang in the doctest CI sometimes, which was killed by the watchdog timer eventually.
Run `gdb` directly and just observe the exit code instead of relying on the more advanced `attach` logic for longer running debug sessions.
* Update CHANGELOG
* fix(packing): dd() raises TypeError on a bytearray destination
dd() documents bytearray as a supported destination type, but
dd(bytearray(b'Hello!'), b'?', skip=5) raises
"TypeError: 'bytes' object cannot be interpreted as an integer".
pwnlib/util/packing.py:1108 handled list and bytearray destinations in a
single branch and filled both with list(map(p8, bytearray(src))). p8()
returns a length-1 bytes object, which is what a list destination is
documented to hold (see the existing dd(list('Hello!'), (63,), skip=5)
doctest), but a bytearray slice assignment needs an iterable of int, so
every bytearray destination crashed.
Assign the byte string src directly when the destination is a bytearray.
Every src branch above the destination dispatch (packing.py:1039-1089)
has already reduced src to a byte string, so the slice assignment is
always valid. This also makes a bytearray destination agree with the
bytes and str destinations, which already copy src verbatim.
Add a doctest covering the returned value and the in-place update of the
caller's bytearray.
* Add changelog entry for #2772
---------
Co-authored-by: peace-maker <[email protected]>
* feat(cli): add 'pwn errno --list' / -l + perror-string fallback (#2657)
- '--list / -l': dump every known errno (value, name, strerror message).
- '--search / -s': force perror-substring match (case-insensitive).
- Bare 'pwn errno <text>' falls back to a perror substring search when the
argument is neither an integer nor a known errno macro name. So
'pwn errno "Cannot allocate memory"' now prints ENOMEM directly.
- Positional 'error' arg is now optional so '--list' can be used alone;
argparse explains the requirement when neither is supplied.
Closes#2657
* Update CHANGELOG.md for #2727
* Add type hints to errno commandline tool
---------
Co-authored-by: Chris (ChrisJr404) <[email protected]>
Co-authored-by: Peace-Maker <[email protected]>
* fix: don't truncate the last byte of FileStructure.struntil
* changelog: add entry for #2761
---------
Co-authored-by: peace-maker <[email protected]>
* fix: Fix DeprecationWarning when setting ssl=True in remote()
The current code initializes SSLContext with `ssl.PROTOCOL_TLSv1_2`, which has been deprecated for a while now
This should be the correct fix according to the documentation (https://docs.python.org/3/library/ssl.html#ssl.SSLContext)
* Update CHANGELOG
* Fix the new ssl thing, document a way to disable cert verification
---------
Co-authored-by: peace-maker <[email protected]>
* Disable debuginfod tests in libcdb.unstrip_libc
The external debuginfod servers are really slow or won't respond at all like debuginfod.ubuntu.com.
The caching in CI doesn't help since we only cache it for 3 month and the query fails afterwards most of the time. We cache the negative response too which doesn't help if the service is flakey itself :D
(cherry picked from commit 86cafce196)
* Add changelog entry for #2773
---------
Co-authored-by: Peace-Maker <[email protected]>
* docs: put plain doctest blocks in the default group for Sphinx 9
doctest_test_doctest_blocks is the group name plain >>> blocks are
assigned to. Sphinx < 9 ignored it and always used "default"; Sphinx 9.0
honours it (sphinx-doc/sphinx#13858), so our 'true' moved every plain
block into a group named "true" while `.. doctest:: :hide:` blocks stayed
in "default". The two groups run separately, so hidden context.clear()
calls no longer ran between the examples around them.
Fixes#2711
* Update CHANGELOG for #2784
* feat(libcdb): use local debuginfod client cache before hitting servers (#2623)
If gdb / eu-debuginfod-find / abrt has already downloaded the matching
debuginfo for our libc's build-id (cached at $DEBUGINFOD_CACHE_PATH or
$XDG_CACHE_HOME/debuginfod_client/ or ~/.cache/debuginfod_client/),
unstrip_libc() now reuses it directly instead of doing another network
round-trip via debuginfod servers. Validated by ELF magic so non-ELF
junk in the cache is ignored.
Closes#2623
* Update CHANGELOG.md for #2726
* Check our own cache before looking at debuginfod-client
---------
Co-authored-by: Chris (ChrisJr404) <[email protected]>
Co-authored-by: Peace-Maker <[email protected]>
* Add Type Annotations for parts of pwnlib/util
* fix: use Callable in pwnlib/util/lists.py
* fix: Import Errors
* fix: use getLogger in pwnlib/util/net
* feat: use collections.abc.Buffer where appropriate
* fix: remove collections.abc.Buffer to use Sequence
* add CHANGELOG.md entry
* Improve packing and fiddling types
* Introduce own `BytesLike` type instead of 3.12 Buffer
* Improve web.wget types
* Use TypedDict in util.net
Specify generics properly.
* Improve pwnlib.proc types
* Improve pwnlib.util.lists types
* Fix util.splash types
* Make TypeVars private
* Improve util.hexdump types
* Remove partial types from packing.fit/flat
Those require more work to be useful.
* Fix implicit wget return
* Fix term.text type export
* Fix js_escape return type
* Fix sh_string doctest types
* Fix usage of ssh_channel as ssh_process
We access the pid, so a plain ssh_channel is not enough.
* Improve util.lists types
* Improve packing.dd types
* Fix relying on socket.AddressFamily type at runtime
The type is only in typeshed and not the real socket module. Don't access it at runtime, only at type checking.
* Fix lists.findall with string needle
* Fix dd on two files
* Update mypy-baseline.txt
* Remove testing artifacts from mypy-baseline.txt
---------
Co-authored-by: peace-maker <[email protected]>
* Support paginated libc.rip API requests
libc.rip used to truncate the result set but supports pagination now. Fetch all results reliably now by requesting all pages.
Fixes#2651
* Update CHANGELOG
* docs(args): clarify reserved args map to context, not args.NOASLR
Reserved magic arguments such as DEBUG and NOASLR are consumed as hooks
that adjust context (context.log_level, context.aslr) and are never
stored in the args dict, so args.NOASLR is always the empty string.
The pwnup template comment previously claimed these settings 'show up
in args', which reinforced the wrong mental model and led users to
check args.NOASLR instead of context.aslr. Clarify both the template
comment and the pwnlib.args module docstring.
Fixes#2564
* docs: add changelog entry for args/pwnup.mako docstring clarification
CI requires a CHANGELOG.md entry for changes touching pwnlib/args.py
and pwnlib/data/templates/pwnup.mako.
* Add support for debugging with x64dbg on Windows
Add x64dbg option to `context.debugger` to attach using x64dbg in `windbg.debug()`.
The path to the x96dbg.exe is looked up in the path and through the "Debug with x64dbg" shell extension you can install optionally when first launching the x96dbg.exe launcher.
You can specify the path using `context.x64dbg_binary` too.
* Refactor exclusion of `context.debugger="auto"` while handling `"auto"`
Co-authored-by: Christian Clauss <[email protected]>
* Update CHANGELOG
* Remove absolute path workaround
x64dbg 2026.05.27 fixed passing absolute paths to a script file using -cf.
* Remove bare raise
log.error raises already.
* Fix linting error of winreg import on linux
The module is only available on Windows. So ignore the error when linting on another platform.
---------
Co-authored-by: Christian Clauss <[email protected]>
The external debuginfod servers are really slow or won't respond at all like debuginfod.ubuntu.com.
The caching in CI doesn't help since we only cache it for 3 month and the query fails afterwards most of the time. We cache the negative response too which doesn't help if the service is flakey itself :D
* ROP: Add labels to reference gadgets dynamically
Allow to assign a name to a point in the ROP chain using `ROP.setlabel(name)`
and reference it somewhere else using `ROP.uselabel(name, offset)`.
You have to know the location of your chain in memory to resolve the
right addresses. This allows to specify addresses relative to your ROP chain payload in your chain.
Refs #2583
* Update ret2dlresolve test output
* Update CHANGELOG
* Rename functions to `label` and `ref`
This is less verbose than `setlabel` and `uselabel` but still descriptive enough to be able to guess what they do.
* fix: improve exception handling in process.py and adb.py
- process.py: restore bare except with pylint disable (intentional: catches
non-Exception errors during Python interpreter shutdown)
- adb.py: use specific (OSError, EOFError) instead of broad except Exception
* fix: add missing import for remote in adb.py
The bare except was silently catching NameError from the missing
remote import. Added 'from pwnlib.tubes.remote import remote' to
fix the actual underlying bug.
* docs: add changelog entry for PR #2743
* docs: move changelog reference link near 5.0.0 release section
* fix: catch PwnlibException in emulator AVD name lookup
The bare except was catching PwnlibException raised by remote() when
connection fails. Replacing with except (OSError, EOFError) caused
PwnlibException to propagate, potentially causing retry loops in
Android CI.
Fix by adding PwnlibException to the exception tuple.
* fix: prevent __getattr__ infinite recursion with context.device setter
When context.device setter accesses device.arch, it triggers AdbDevice's
__getattr__ (instead of the arch property). __getattr__ then calls
context.local(device=self), which triggers the setter again, causing
infinite recursion.
Fix: check if the attribute exists on the class via MRO.__dict__
before entering the context.local() path. This lets Python's normal
property resolution handle class-defined attributes.
* revert: remove __getattr__ MRO guard
Peace-maker correctly points out that __getattr__ is only called when
normal attribute lookup fails, so the MRO guard is unnecessary.
The infinite recursion is a pre-existing bug unrelated to this PR.
* Assign to `_avd` instead of `avd`
---------
Co-authored-by: mshzy <[email protected]>
Co-authored-by: peace-maker <[email protected]>
* fix(ssh): use POSIX separator for path detection in ssh.which
On Windows, `os.path.sep` is '\\', which fails to detect POSIX paths.
Hardcoding '/' ensures consistent path detection since the `ssh`
module targets POSIX-compliant systems.
* Update CHANGELOG.md
* feat(context): add path_sep and pathlist_sep to context, make the path seperator dependent on the context.os
* fix(ssh): declare path separator as private member in ssh
* fix(ssh): remote path handling with pathlib
* fix(ssh): replace os.path.basename functions with pathlib for path handling
* fix(ssh): ensure remote paths are decoded to str
* guide users to libc_start_main_return for __libc_start_main_ret
looking up __libc_start_main_ret on ELF(libc).sym just threw a plain
KeyError/AttributeError even though libcdb shows that symbol, which is
confusing (issue 2563). it's not a real symbol so we can't just add it,
and computing it means disassembling __libc_start_main which we don't
want to do for everyone by default.
so for now the symbols dotdict raises a message pointing at the existing
ELF.libc_start_main_return property when you ask for that key. lazy auto
calc can come later. added a doctest covering both sym['...'] and
sym.__libc_start_main_ret access, tests pass.
* use bare super() in symboldict
peace-maker noted new code can use py3 super(), so drop the
redundant (symboldict, self) args.
* add changelog entry for 2746
---------
Co-authored-by: peace-maker <[email protected]>
The nginx docs say that you have to specify the $request_uri manually when a variable is used in the `proxy_pass` value.
Since we just put `/` at the end, all requests were rewritten to `/` instead of the intended e.g. `/api/find` endpoints.
https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
This broke in #2718 but didn't manifest right away since the responses were still cached in CI. Now after the cache expired the fetch failed.
* Fix some global type hint errors
Errors in global scope should be fixed before we're enabling strict mode in mypy and tackle the local problems.
* Remove pwnlib.util.pairwise since it's in itertools now
pairwise was added to itertools itself in 3.10.
https://docs.python.org/3/library/itertools.html#itertools.pairwise
* Fix atexception handlers in term mode
The colored-traceback module registers its own `sys.excepthook` but doesn't call the original handler.
Reorder the includes such that the colored-traceback is setup before and our own hooks afterwards.
We always call the old excepthook and forward the exception to the colored-traceback after firing our own handlers.
It worked before in non-term mode when stderr wasn't a tty and colors were disabled.
* Update CHANGELOG
* Import atexception in doctests
* feat(libcdb): add extra_mirrors arg + PWN_EXTRA_LIBC_MIRRORS env to download_libraries (#2666)
When the libc.rip URL points at a deb.debian.org / archive.ubuntu.com /
security.debian.org URL whose package has been pulled (e.g. older
vulnerable libc versions like 'GLIBC 2.36-9+deb12u6'), download_libraries
now also tries the same /pool/... path against any user-supplied mirror
prefix(es). Mirrors can be passed via the new keyword argument
extra_mirrors=... (str or list) or the comma/whitespace-separated
PWN_EXTRA_LIBC_MIRRORS environment variable.
Closes#2666
* Update CHANGELOG.md for #2725
* Rename environment variable to `PWNLIB_EXTRA_LIBC_MIRRORS`
All our other user-facing environment variables are `PWNLIB_` instead of `PWN_`.
* Move `import re` to toplevel
* Add type hints to touched functions
* Add example usage for download_libraries with extra_mirrors parameter
* Fix envvar in CHANGELOG
---------
Co-authored-by: Chris (ChrisJr404) <[email protected]>
Co-authored-by: Peace-Maker <[email protected]>
* Add typehints to timeout module
Co-authored-by: Copilot <[email protected]>
* Add typehints to device class
* Add typehints to PwnlibException
* Add general typehints for term.text module
Since the available module attributes are handled dynamically like `text.green()` or `text.green_on_white()` or `text.underline_red()`, it's not feasible to type out all possible combinations.
Just tell the type checker that all module attibutes have the same type and thus avoid the `error: Module has no attribute "bold_blue" [attr-defined]` errors.
* Add typehints for config module
* Add typehints for hashes module
The guaranteed algorithms in hashlib are pretty stable and we can generate the list out proper type checking and auto complete.
Still add a check in CI that notifies us if there are changes in the future.
* Add atexception and atexit types
atexception.unregister was not documented correctly since the function expects an identifier returned by `atexception.register` instead of the handler function.
* Fix toplevel type hints in shellcraft.internal
* Fix toplevel type hints in term.key
---------
Co-authored-by: Copilot <[email protected]>
* add ":" to Distro string
* Update cache file path to include username
Include username in cache file path for better uniqueness.
* Added public_key+fingerprint for ssh class & Modified ssh checksec_cache path to be more unique & checksec is per ssh server and not attached to a user
* Fix typeo
* Revert indentation to 10 chars
* ssh: Fix downloading data to tmp on Windows
Allows the checksec output of the target server to be generated.
Filenames cannot contain a colon ":".
* Update CHANGELOG
---------
Co-authored-by: Peace-Maker <[email protected]>
* refactor: optimize completion script
And deprecate an interface
* chore: update changelog
* refactor: full patch of zsh comp script
* fix: add missing message in output
* fix: a typo and a missing help
* feat: allow -l to match multiple arguments
* feat: optimize completion logic
1. move all complicated functions in front of pwn()
2. add file completion for libcdb subcommands
3. add completion for pwn errno