Compare commits

...
179 Commits
Author SHA1 Message Date
peace-maker 8bc6f6cd2b Merge pull request #2796 from peace-maker/stable_backports
Backport bugfixes from 5.0 to stable
2026-11-08 08:49:07 +01:00
peace-maker 455c8c02c3 Backport: Test on Python 3.15 (#2792)
* 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
2026-10-30 20:49:30 +01:00
Carlos Luna-Pena dbc618de0d Backport: fix #2737: pwnlib.shellcraft submodule imports on python 3.12+ (#2739)
* shellcraft: migrate lazy importer to find_spec for py3.12+

* shellcraft: changelog entry + mypy baseline sync for #2739
2026-10-30 20:49:06 +01:00
peace-maker 34b8345d1d Backport: Support paginated libc.rip API requests (#2767)
* 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
2026-10-30 20:49:05 +01:00
Peace-Maker 771c7f81ac Backport: Skip ssh.ibt doctest since some runners appear to support it now 2026-10-30 20:49:05 +01:00
Taran 8d69dc6142 Backport: fix(srop): correct amd64 SigreturnFrame uc_sigmask offset (#2762)
* fix(srop): correct amd64 SigreturnFrame uc_sigmask offset

* changelog: add entry for #2762
2026-10-30 20:49:05 +01:00
peace-maker 3911a6a12e Backport: Fix libcdb CI cache not forwarding URI path (#2749)
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.
2026-10-30 20:49:05 +01:00
ChrisJr404andChris a5f3873194 Backport: safeeval: allow LIST_APPEND and SET_ADD opcodes (Python 3.14) (#2722)
* safeeval: allow LIST_APPEND and SET_ADD opcodes (Python 3.14)

* changelog: add entry for #2722 (safeeval Python 3.14 opcodes)

* ci: retrigger after transient libcdb network failure

---------

Co-authored-by: Chris (ChrisJr404) <[email protected]>
2026-10-30 20:49:05 +01:00
peace-maker 481704bfd8 Backport: ssh: Discard stderr of lsb_release for Distro lookup (#2704)
* ssh: Discard stderr of `lsb_release`

The "No LSB modules are available." spam interferes with parsing the output for the initial checksec distro parsing when connecting to a new host.

* Update CHANGELOG
2026-10-30 20:49:05 +01:00
zackary 5196a1a0f0 Backport: fix: delay upstream DNS resolution to prevent startup failures (#2718)
Use nginx variable pattern (set $upstream + proxy_pass https://$upstream)
to defer DNS resolution until first request instead of at config parse time.

This fixes the occasional 'host not found in upstream' error in CI when
nginx container starts before Docker DNS is fully available.

Fixes #2712
2026-10-30 20:49:05 +01:00
Peace-Maker be705326a7 Backport: libcdb CI cache: Resolve upstream hostnames on request
Instead of trying to resolve all of them when nginx starts and exit
if any of them fail to resolve.

[emerg] 1#1: host not found in upstream "debuginfod.elfutils.org" in /etc/nginx/nginx.conf:23
2026-10-30 20:49:05 +01:00
Peace-Maker c7e6ef37c8 Backport: Cache gitlab.com libcdb responses in CI
The reponses set a cloudflare `_cfuvid` cookie and had a cache time of 60 seconds.
nginx doesn't cache responses with a `Set-Cookie` header by default,
so ignore the cookie and override the cache time to 12 weeks.

Fixes #2494
2026-10-30 20:49:05 +01:00
Arusekk 210faac75b Backport: no atexit, OS will suffice 2026-10-30 20:49:05 +01:00
peace-maker 8e0e4c6c90 Backport: Close SSH client connection when authentication failed (#2688)
* Close SSH client when authentication failed

The TCP connection stayed open after an exception was thrown
during authentication, even when a `with`-statement guarding the call.
Close the connection before re-raising the exception.

Fixes #2678

* Update CHANGELOG
2026-10-30 20:49:05 +01:00
peace-maker bbac6660b2 Backport: Fix tty and raw arguments in ssh.process (#2699)
* Fix `tty` and `raw` arguments in ssh.process

The arguments were unused and not passed through to the underlying `ssh_process` class.

Fixes #2038

* Add tty tests

* Update CHANGELOG

* Fix buffered process environment output without tty
2026-10-30 20:49:05 +01:00
Rin 2a986f12c1 Backport: refactor: replace unsafe eval with ast.literal_eval in ROP cache loading (#2677)
* refactor: replace unsafe eval with ast.literal_eval in ROP cache loading

* docs: add PR link to CHANGELOG reference section

* docs: restore full CHANGELOG and correctly add PR #2677 reference
2026-10-30 20:49:05 +01:00
peace-maker b60ed9928d Backport: Fix typo causing doctests not getting skipped (#2681)
Downloading all those libcs slowed down the CI a lot.
2026-10-30 20:49:05 +01:00
peace-maker b1391984d1 Backport: asm: try native binutils before fallback architectures (#2669)
* asm: try native binutils before fallback architectures

Some binutils builds support multiple architectures,
like the x86_64 assembler supports i386 too in most
package builds and vice versa. We support this by trying
the other binutils as well when looking for the right tool.
That support is optional though and there are packages
that don't include the "cross" compilation.

When assembling for the host's native architecture, we
still prefer the explicitly named `x86_64-linux-gnu-as`
instead of the native `as` binary. That native binary is
tried as a last resort after looking for any other explictly
named binary. If the fallback package is installed but
compiled without the cross-compiler support, we'd still
find the `i386-as` binary while looking for `x86_64-as`
before trying the native `as` binary.
That would fail to assemble.

This patch moves the native `as` binary forward in the list
to try it before checking the other fallback architecture ones.

Fixes #2509

* Update CHANGELOG
2026-10-30 20:49:05 +01:00
Th3S dd747e1062 Backport: fix(libcdb-cli): return early if no matched libc found (#2646)
* Fix: return early if no matched libc found

* Update CHANGELOG
2026-10-30 20:49:05 +01:00
peace-maker 78fccc055f Backport: Remove "pip" as explicit dependency (#2642)
It looks like this was done to work around a bug in an old pip version years ago.
It caused problems when freezing dependencies which unnecessarily forced pip to the version used at freeze time when installing again.

Fixes #2625
2026-10-30 20:49:05 +01:00
OBarronCS 4f50b45586 Backport: Add aarch64_be qemu mapping (#2653) 2026-10-30 20:49:05 +01:00
a1c7d07db8 Backport: GitHub Actions: Test on Python 3.14 (#2627)
* GitHub Actions: Test on Python 3.14

Python v3.14 -- October 7th
* https://www.python.org/download/pre-releases
* https://www.python.org/downloads/release/python-3140rc3
* https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md#allow-pre-releases

* Allow new LOAD_SMALL_INT opcode in safeeval

* Support lambdas in mbruteforce

* Drop pwnlib.util.iters.lookahead

---------

Co-authored-by: Peace-Maker <[email protected]>
Co-authored-by: Arusekk <[email protected]>
2026-10-30 20:49:05 +01:00
Arusekk 6691e8476a Backport: template: error message and fallback on no docker 2026-10-30 20:49:05 +01:00
peace-maker a8bcdf6f8d Backport: Fix log.progress ignoring context.log_console (#2610)
* Fix `log.progress` ignoring `context.log_console`

When setting `context.log_console` to something other than stdout, spinners while using `log.progress` would still be printed to stdout.
Redirect them to the stream specified by `context.log_console` and don't animate if it's not a tty.

Fixes #1702

* Update CHANGELOG
2026-10-30 20:49:05 +01:00
k4lizen bf5e4df220 Backport: Fix aarch64 ABI (#2598)
* upd aarch64 abi

* changelog
2026-10-30 20:49:05 +01:00
Shordenandpeace-maker 68b5bbf16b Backport: Support context.timeout in ~/.pwn.conf (#2592)
* Add float to supported config types

This change functionally just allows setting `context.timeout` in
~/.pwn.conf.

* update changelog

---------

Co-authored-by: peace-maker <[email protected]>
2026-10-30 20:49:05 +01:00
Arusekk 9a7e197754 Backport: Fix double exception on gaierror
Closes #2581
2026-10-30 20:49:05 +01:00
Zach Hanson 96c3ede156 Backport: Fix a bug that incorrectly reports GNU_STACK missing when its not. (#2493) 2026-10-30 20:49:05 +01:00
RocketDev f2eba7c8fd Backport: ROP: fix ROP(ELF(exe)).leave is None in some ELF (#2506)
* ROP: fix `self.leave is None` in some libc

When `pop rbp; pop rsp; ret;` exists in libc, it is chosen instead of
`leave`. Add a specific `order` to filter out the former one.

* add changelog for #2506

* ROP: add sp_move when `pop rsp`

* CHANGELOG: mv #2506 to `5.0.0`
2026-10-30 20:49:05 +01:00
peace-maker 1c7d917432 Backport: CI: Test on Python 3.13 (#2534) 2026-10-30 20:49:05 +01:00
tesujiandpeace-maker 1553670f9d Backport: checksec: Do NOT error when passing directory arguments to commandline tool (#2530)
I often use `checksec *` to lazily avoid typing filenames in a directory.
If the directory contains any other sub-dirs, the command fails.
With this patch, checksec will silently skip dir paths. There's still
TOCTOU issue but I don't think checksec do anything important enough
to explicitly use try/catch to account for that.

Co-authored-by: peace-maker <[email protected]>
2026-10-30 20:49:05 +01:00
peace-maker 8f67b7b7b5 Backport: Raise EOFError during process.recv when stdout closes on Windows (#2524)
* Windows: Raise EOFError during process.recv when stdout closes

If the receiving thread terminates while we're waiting for data to arrive we'd be waiting endlessly. Raise EOFError when .recv()ing on a process with stdout closed and no more data queued up from the receiver thread.

* Update CHANGELOG
2026-10-30 20:49:05 +01:00
Rahulandrahul05ranjan 459dfd7e35 fix(regsort): drop self-assignments through register aliases (#2795)
* fix(regsort): drop self-assignments through register aliases

The self-assignment drop compared register names only (k != v), so an
assignment through an alias (e.g. {'ax': 'eax'} with registers.native32)
was not recognized as a no-op.  It then surfaced as a spurious
1-register dependency cycle, which either raised PwnlibException with
xchg=False or emitted a useless 'mov' of a register into its own alias.

With xchg=False and other registers present, the bogus cycle also
forced the temporary-register code path, reordering unrelated moves and
silently leaving registers with wrong values (see the linked issue).

Compare the mapped names instead, like the rest of the function.

Fixes #2794

Co-authored-by: rahul05ranjan <[email protected]>

* docs(changelog): add regsort register-alias self-assignment fix entry

---------

Co-authored-by: Rahul Ranjan <[email protected]>
2026-10-30 16:20:25 +01:00
peace-maker d8d47977ac gdb.corefile: Run gdb directly to prevent detach race (#2787)
* 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
2026-10-26 06:15:28 +00:00
Max Freedom Pollardandpeace-maker 3daf28b6be fix(packing): dd() raises TypeError on a bytearray destination (#2772)
* 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]>
2026-10-24 12:15:03 +02:00
h4kk4p4kk4andpeace-maker f4b3e6e1c4 fix(elf): prevent elf.libc returning the executable when its name starts with libc[.-] (#2781)
Co-authored-by: peace-maker <[email protected]>
2026-10-24 12:12:47 +02:00
Max Freedom PollardandPeace-Maker 2b39684912 Disable debuginfod doctests in libcdb.unstrip_libc on stable (#2773)
* 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]>
2026-10-21 20:04:53 +02:00
peace-maker 7e5e79d00f Allow running with Unicorn 2.1.[34] but throw when emulating MIPS (#2721)
* Allow running with Unicorn 2.1.[34] but throw when emulating MIPS

Unicorn 2.1.5 wasn't released for a while and 2.1.2 doesn't have binary wheels for Python 3.14.
This made installing pwntools on newer Python versions more annoying since you had to build Unicorn yourself.

The only problem with the blocked versions is MIPS emulation, so only avoid that while allowing to use Unicorn 2.1.3 or 2.1.4 for other architectures.

Refs #2621

* Update CHANGELOG
2026-04-27 18:23:01 +02:00
0xDanielandpeace-maker e551b4ae56 fix: apply force_to_bytes to readline result in non-term_mode path (#2707)
Co-authored-by: peace-maker <[email protected]>
2026-04-07 11:28:48 +02:00
43ef1b494c Fix _build_date() crash on non-standard locale date strings (#2701)
* Fix _build_date() crash on non-standard locale date strings (#2513)

Some Android devices return locale-dependent strings in ro.build.date
(e.g. '2017年 11月 14日 星期二 09:55:07 CST' for Chinese locale) that
dateutil.parser.parse() cannot handle, causing wait_for_device() to
crash with a ParserError.

Fix: prefer ro.build.date.utc (integer epoch timestamp) which is
locale-independent and available on all Android devices. Fall back
to ro.build.date with error handling if the UTC property is missing.

* Add CHANGELOG entry for #2513 fix

* Simplify _build_date(): prefer ro.build.date.utc, keep minimal fallback

Address review: ro.build.date.utc is set by the AOSP build system
and available on all standard Android devices. Simplified comments
to reflect this is the primary path, with ro.build.date kept only
as a fallback for non-standard builds.

* Move CHANGELOG entry

* Fix Python 2.7 compatibility

* Disable intro doctest connecting to `ftp.ubuntu.com`

The FTP server is throttled in CI or just really slow. We already test the basic tcp tubes in the `remote` tests.

---------

Co-authored-by: coder999999999 <[email protected]>
Co-authored-by: peace-maker <[email protected]>
2026-04-07 11:09:01 +02:00
be92aa1b4c fix: pad bytes fields to correct field size in FileStructure (#2694)
* fix: pad bytes fields to correct field size in FileStructure

When setting bytes fields (e.g. _IO_save_base) on FileStructure, the
value was padded to context.bytes instead of the actual field size from
self.length[val]. This caused struct.pack errors for fields whose size
differs from the pointer size.

Fixes #2693

* Cleanup test and add CHANGELOG

---------

Co-authored-by: nightcityblade <[email protected]>
Co-authored-by: Peace-Maker <[email protected]>
2026-04-05 20:37:31 +00:00
Peace-Maker 07f3caadc4 Stay with pylint < 4.0 until recursion errors are fixed
https://github.com/pylint-dev/pylint/issues/9190
2025-10-16 16:17:08 +02:00
Peace-Maker 3ad86ec5ad Release 4.15.0 2025-10-12 16:48:05 +02:00
Arusekk b5076d9262 Merge branch 'stable' into beta 2025-09-26 09:54:54 +02:00
ArusekkandHackrrr 77b4f06b07 docs: warn that .libs/.libc/.maps are dangerous (#2626)
Co-authored-by: Hackrrr <[email protected]>
2025-09-26 07:36:34 +00:00
Arusekk 4968499d11 ffix: ugly ELF docs (whitespace only) 2025-09-26 09:20:53 +02:00
Peace-Maker f38991bc02 Merge branch 'stable' into beta 2025-09-16 21:41:00 +02:00
peace-maker d0e6ee4b37 Fix regression: gdbserver can't handle command-line argument containing whitespace (#2624)
* Fix regression: gdbserver can't handle command-line argument containing whitespace

The `--no-startup-with-shell` argument was passed in an attempt to
fix gdbserver startup with `SHELL=/bin/fish`. (#2377) It caused a regression
which disallowed passing arguments containing whitespace to the debuggee in `gdb.debug`.

gdbserver would exit with a message:
"can't handle command-line argument containing whitespace"

There is a 3 second timeout waiting for gdbserver to startup and
printing a message with a workaround already suggesting to set
`SHELL=/bin/bash` to allow gdbserver to launch. This has to be
our best effort to guide users of such shells until we find time
to investigate a better solution.

Fixes #2550

* Update CHANGELOG
2025-09-16 21:06:29 +02:00
peace-makerandArusekk 48ea09b27f Fix lookup of binutils for mipsel architecture (#2612)
* Fix lookup of binutils for `mipsel` architecture

The endianness is encoded in the architecture name for mips targets which wasn't respected while looking for the correct binutils binary.

Sync the CI and Dockerfile binutils packages while we're at it.

Fixes #2591

* Update CHANGELOG

* still fall back to the other endianness

---------

Co-authored-by: Arusekk <[email protected]>
2025-09-11 13:09:28 +00:00
Arusekk 9f22a2f202 Merge branch 'stable' into beta 2025-09-11 14:55:56 +02:00
Arusekk 7413a3da31 Exclude Unicorn versions segfaulting on MIPS PLT (#2621)
Fixes #2619
2025-09-11 12:55:51 +00:00
Peace-Maker 95aac6e367 Merge branch 'stable' into beta 2025-09-05 13:59:45 +02:00
Peace-Maker 9ed93a5281 Fix race condition in process mapping tests
We could try to lookup the mapped libraries before they are actually loaded in the process.
Wait until the program is up and running before trying to fetch the memory maps.
2025-09-05 13:14:57 +02:00
peace-maker 3579fb1384 Fix log level of child remotes of server tube (#2609)
* Fix log level of child remotes of `server` tube

The log level of the `server` tube wasn't passed
on to the `remote` wrappers created upon receiving
a new child connection. This caused the connection
closed message to be logged even when the server
object was created with `level='error'`.

* Update CHANGELOG
2025-09-05 12:25:49 +02:00
Peace-Maker 485bf0a0b7 Merge branch 'stable' into beta 2025-08-28 14:36:00 +02:00
William Tan b133b76b4e Allow setting debugger path via context.gdb_binary (#2602)
* Allow setting debugger path via context

* Update changelog
2025-08-19 10:30:05 +02:00
ffc46d277a Fix poll error in process.libs() and clean up maps parsing (#2579)
Co-authored-by: Raccoon <raccoon@42>
Co-authored-by: peace-maker <[email protected]>
2025-08-09 14:47:57 +00:00
Peace-Maker dd3a5f6974 libcdb: Fix cache handling of debuginfo
When trying multiple debuginfod servers, the first one to fail would save the failed attempt and block the remaining servers to be tried.

Only save that we couldn't find the debuginfo if we tried all the configured servers.
2025-08-06 14:32:08 +02:00
Peace-Maker 9a275b2db0 Fix libcdb cache in CI
Requests to debuginfod.elfutils.org had the wrong SNI in their request.

Cache requests to debuginfod.ubuntu.com too.
2025-08-06 12:16:10 +02:00
Peace-Maker 1c28222fe6 Merge remote-tracking branch 'stable' into beta-staging 2025-08-05 21:47:13 +02:00
peace-maker b93c5ace10 Ignore colored_traceback error when TERM is unset (#2596)
* Ignore colored_traceback error when TERM is unset

Fixes using pwntools in non-interactive sage scripts with newer colored_traceback versions.

Fixes #2594

* Update CHANGELOG
2025-08-05 21:25:21 +02:00
peace-maker da9797c1c2 Support longer function names in Windows getexport shellcode (#2587)
* Support longer function names in Windows getexport shellcode

Previously, an arbitrary name length limit of 8 characters was in place due to the lack of a proper strcmp loop. Implement a cheap strcmp for longer function names.
This trashes a bunch of registers and we might be able to optimize it further to reduce the damage.

Use a unique label too to avoid redefinition when using the shellcraft template twice in the same shellcode. Use the mov shellcraft template for the destination register to avoid an instruction if the result is already in the desired register.

* Update CHANGELOG
2025-08-05 14:55:35 +00:00
Shordenandpeace-maker 6dfe8b6f72 Use unicorn on macOS w/ SIP enabled (#2593)
* __ensure_memory_to_run_unicorn: don't request wx memory

macOS systems with SIP enabled prohibit mmaping WX memory.
unicorn doesn't run into this issue because it uses the MAP_JIT
protection flag.

See also:
https://github.com/unicorn-engine/unicorn/blob/803fe5a47770360d1942de72600d3b295b521e31/qemu/accel/tcg/translate-all.c#L1021-L1032
https://github.com/pwndbg/pwndbg/blob/2f6b5bbaea484391f55850a09a16efda161498f2/pwndbg/aglib/disasm/__init__.py#L305-L316

* update changelog

---------

Co-authored-by: peace-maker <[email protected]>
2025-08-05 11:39:28 +00:00
peace-maker 425221fb30 Add Ubuntu and Debian debuginfod servers (#2595)
* Add Ubuntu and Debian debuginfod servers

Most CTF challenges are hosted on Ubuntu or Debian [citation needed], so check their debuginfod servers before trying the federating one as a fallback.

This is required since the elfutils.org server seems down for maintenance occasionally.

* Update CHANGELOG
2025-08-05 13:02:00 +02:00
Chaitanya RahalkarandPeace-Maker 004a6dab88 Add automatic detection of statically linked binaries in detect_missing_binaries function. (#2570)
* Add automatic detection of statically linked binaries in `detect_missing_binaries` function.

* Add entry for PR #2570 to CHANGELOG.md: fix `pwn template` for statically linked binaries.

* Remove partial test implementation

The commands should be tested end-to-end instead of using doctests (later).

---------

Co-authored-by: Peace-Maker <[email protected]>
2025-07-11 13:10:40 +02:00
Arusekk 6098f28bfa Merge branch 'stable' into beta 2025-04-02 18:00:52 +02:00
Arusekk 1205b1aaa3 regsort: respect register aliases (#2576)
Closes #2481
2025-04-02 15:57:59 +00:00
tesujiandArusekk ce6d2ca847 Fix invalid parsing of loader error message in elf.libc (#2567)
For example, on my machine:

  > ./main_no_flag
  ./main_no_flag: /lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.32' not found (required by ./main_no_flag)

Co-authored-by: Arusekk <[email protected]>
2025-04-02 14:17:30 +02:00
Peace-Maker 9e0ca3a415 Move changelog entry to stable log 2025-03-30 12:21:08 +02:00
Daniel Kilimnik b60b2e897f SSH: fix download/upload with -1 exit status (#2545)
* SSH: fix download/upload with -1 exit status

* Add Changelog
2025-03-30 10:19:42 +00:00
Arusekk 2c3e783f96 Release 4.15.0beta1 2025-03-24 13:21:16 +01:00
Arusekk 15bdd4a766 Release 4.14.1 2025-03-24 13:01:50 +01:00
Arusekk 7c95e838f4 Merge branch 'stable' into beta 2025-03-24 12:15:36 +01:00
Maxime Meignan 92aa64ce01 Fixed bound on memcpy loop in thumb,arm,aarch64 (#2552) 2025-03-24 10:30:14 +00:00
peace-maker ae4bb08c3e Fix syntax highlighting of multiline comments in ASM (#2562)
Enable DOT_ALL next to the default MULTILINE regex flags to match newlines too with the `.*?`.
```
/* this works */
/*
this is not highlighted as a comment
*/
```
2025-03-21 20:55:23 +00:00
6739525ebe Show ELF symbols defined to value 0 (#2451)
Lets say we have an ELF with the following symbols

```
Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000035     0 NOTYPE  LOCAL  DEFAULT    2 aaaa
     2: 0000000000000022     0 NOTYPE  LOCAL  DEFAULT    2 bbbb
     3: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    2 cccc
     4: 0000000000000054     0 NOTYPE  GLOBAL DEFAULT    2 dddd
```

Then pwnlib's ELF(binary).symbols will be `{'aaaa': 53, 'bbbb': 34, 'dddd': 84}`.
This is missing the symbol `cccc`, because its value is 0.

This change checks the name instead of the value, because the value can
be 0 if the symbol points to the beginning.

The new and correct value of pwnlib's ELF(binary).symbols will be
`{'aaaa': 53, 'cccc': 0, 'bbbb': 34, 'dddd': 84}`.

* Do not unresolve zeros
* Do not add undefined symbols

Co-authored-by: peace-maker <[email protected]>
Co-authored-by: Arusekk <[email protected]>
2025-03-21 11:34:33 +01:00
Arusekk d10b7aee4c Exclude broken Unicorn version (#2565)
Closes #2560
2025-03-19 08:47:55 +00:00
Arusekk aeb4c26bf0 Fix parsing corefile with missing auxv (#2559)
Closes #2543
2025-03-03 16:01:05 +00:00
Peace-Maker ec6b8cd87c Merge branch 'stable' into beta 2025-01-26 23:47:08 +01:00
Meetesh SainiandPeace-Maker b2345f214e fix: update apport coredump path handling for CorefileFinder (#2518)
* fix: update apport coredump path handling for CorefileFinder

* chore: update comment on Apport core path handling

* Update CHANGELOG

---------

Co-authored-by: Peace-Maker <[email protected]>
2025-01-26 22:28:14 +00:00
peace-maker e9d9bd9ddb Fix installation on Python 3.5 and lower on stable (#2533)
* Fix installation on Python 3.5 and lower on stable

The unix-ar package requires Python 3.6. Only install it on Python 3.6 then and use the Python 2 fallback for Python <= 3.5 too.

* Update CHANGELOG
2025-01-26 23:18:16 +01:00
Peace-Maker d7a7376eca Merge branch 'stable' into beta 2025-01-15 20:34:56 +01:00
Peace-Maker 9472ec1e93 Fix building docs on stable
Pin to Python 3.12.
2025-01-15 16:49:27 +01:00
peace-maker e4b939dc1a Poll before reading /proc/maps in process.libs() (#2516)
Try to avoid race condition of reading memory maps before libraries are loaded.
2025-01-15 16:49:02 +01:00
Peace-Maker c02190b5d4 Release 4.15.0beta0 2025-01-15 08:48:06 +01:00
Peace-Maker e341e238ca Release 4.14.0 2025-01-15 08:46:49 +01:00
Luca Bancale 7741a187ea Ignore a warning with unused args in asm on NIX (#2508)
* Ignore a warning when compiling with asm

* Add pr to changelog
2025-01-14 22:50:23 +01:00
Findus 4ef3c16d09 ssh: replaced nonexistent key with str(e) in error handling (#2512) 2025-01-06 22:43:21 +01:00
fb2ee19b90 Deprecate direct commandline scripts invocation and exclude nonsense ones (#2364)
* deprecate direct commandline scripts invocation and exclude nonsense ones

* Don't deprecate all commandline tools

---------

Co-authored-by: Arusekk <[email protected]>
Co-authored-by: Peace-Maker <[email protected]>
2024-12-10 22:47:47 +01:00
Jakub Nowakandpeace-maker 74a300db6c Deprecate 'keepends' argument in favor of 'drop' (#2476)
* Replace 'keepends' with 'drop'

Add 'drop' argument in place of 'keepends' for tubes. 'keepends' still
works but raises depreciation warning.

* changelog

* Ignore line numbers in PyLint check

---------

Co-authored-by: peace-maker <[email protected]>
2024-12-10 22:31:29 +01:00
peace-maker 57b9eb9107 Fix loading ELF files without valid .dynamic section (#2502)
* Fix loading ELF files without valid .dynamic section

This allows to load separate debuginfo files and access their symbols.

* Update CHANGELOG
2024-12-10 21:36:33 +01:00
Peace-Maker b2d56fa37c Merge branch 'beta' into dev 2024-12-10 21:17:16 +01:00
Peace-Maker a0ddbf5e16 Tests: Revert timeout changes from gdb tests
There were additional `timeout=X` additions in #2382 which caused tests to fail randomly when a timeout was reached. The tests run through occationally, so it's not an infinite loop. But flakey tests are annoying and I don't see a reason for the timeout additions to the doctests for the core patch of that PR other than failing early during manual tests of new functionality. CI running smoothly is more important than fast failing during development on the gdb module imo.
2024-12-10 20:34:39 +01:00
Peace-Maker 1be8ad7770 Merge branch 'stable' into beta 2024-12-10 20:34:14 +01:00
Peace-Maker 24d217cfbd Docs: Fix link to source for class properties
The property has setters and getters. Link to the getter if it's available. This adds line numbers to the source link for properties.

Fixes #2401
2024-12-09 13:09:10 +01:00
peace-maker ec262d8d01 Update sphinx for Python 3.13 support (#2503)
* Fix sphinx warnings in docstrings

* Update sphinx for Python 3.13 support

Could not import extension sphinx.builders.epub3 (exception: No module named 'imghdr')

`imghdr` was removed in Python 3.13.
2024-12-08 21:16:39 +01:00
Justin ApplegateandPeace-Maker 55ac6e11fc Update documentation for format strings (#2501)
* Update fmtstr.py documentation

Clarified that the `value` in the `writes` dict (for `fmtstr_payload()`) should be a bytestring if the value to be written is shorter than a long

* Update fmtstr.py documentation for FmtStr class

Updated example and definition for `write()` function in `FmtStr` class to include bytes as the value.

* Fix code formatting

---------

Co-authored-by: Peace-Maker <[email protected]>
2024-12-08 19:33:32 +01:00
Leopold 96d98cf192 fix fromsocket to deal with ipv6 socket (#2497)
* fix fromsocket to deal with ipv6 socket

* add remote.fromsocket ipv6 test and update CHANGELOG.md

* skip fromsocket ipv6 test
2024-11-01 13:36:30 +00:00
peace-maker 6f0793eebc Add tube.upload_manually to upload files in chunks (#2410)
* Add `tube.upload_manually`

Upload data in chunks when having a tube connected to a shell.
This is useful when doing kernel or qemu challenges where you can't use the ssh tube's file upload features.

* Add tests and fix corner cases

* Update CHANGELOG

* Fix character escaping in tests

* Fix gzip compression on Python 2
2024-10-28 21:11:36 +01:00
ckxckxandPeace-Maker 51cbdb465d Fix attaching to a gdbserver with tuple gdb.attach(('0.0.0.0',12345)) (#2291)
* Patch for #issues/2290

* Return listening process on `pidof(("0.0.0.0", 1234))`

Instead of returning the process which is connected to port 1234,
return the process which is listening on that port.

* Update CHANGELOG

---------

Co-authored-by: Peace-Maker <[email protected]>
2024-10-28 21:06:56 +01:00
Peace-Maker 61804b169b Merge branch 'beta' into dev 2024-10-24 23:28:53 +02:00
Peace-Maker 04e90bc754 Merge branch 'stable' into beta 2024-10-24 23:28:20 +02:00
Peace-Maker 8926a3a2bc Fix checksec commandline output after Python 3.12 fixes
This reverts #2346 which apparently didn't do what was expected. The logger has to be initialized for the checksec output to show up, so some other file imported * from pwn before too.
With the double registration of subparsers removed in f28d3ebb6c this didn't happen anymore making checksec print nothing.
2024-10-24 23:24:43 +02:00
peace-maker bb7a85c8df Allow to disable caching (#2484)
* Allow to disable caching

By setting `context.cache_dir = None`. Generate default cache dir again by setting `context.cache_dir = True`.

* Disable cache in `asm` caching test

* Update CHANGELOG

* Fix asm cache test
2024-10-24 17:04:50 +02:00
Peace-Maker 3303ea949d Merge branch 'beta' into dev 2024-10-24 16:44:19 +02:00
Peace-Maker cef48f4085 Merge branch 'stable' into beta 2024-10-24 16:32:29 +02:00
Peace-Maker 2ce27dab0d CI: Install coveralls without --break-system-packages
ubuntu-latest doesn't seem to point to Ubuntu 24.04 anymore? Allow this to work on Ubuntu 22.04 too.
2024-10-24 16:20:50 +02:00
Th3Sandpeace-maker fa14663243 libcdb-cli: add --offline-only, refactor unstrip and add fetch parser for download libc-database (#2478)
* Add `return_raw` for `search_by_symbol_offsets`

* Add `--offline-only` and unstrip libc as default behavior

* Add short arg name for `--download-libc`

* Fix bugs

* Add fetch parser

* Fix bugs

* file parse not unstrip default

* Update function docs

* Update CHANGELOG

* Edit dest of `--no-strip`

* Update CHANGELOG

* Unstrip before `return cache`

* Revert `--unstrip` help

* Improve `libcdb fetch` default behavior

* Perf fetch command

* Fix fetch command `-u`

---------

Co-authored-by: peace-maker <[email protected]>
2024-10-24 16:11:07 +02:00
peace-maker d2253110bd Add caching proxy for libcdb debuginfod files to CI (#2487) 2024-10-24 15:59:24 +02:00
peace-maker a3b22b748d Throw error when using sni and setting server_hostname manually in remote (#2482)
* Throw error when using `sni` and setting `server_hostname` manually in `remote`

Prevents silently replacing the `server_hostname` that was provided in `ssl_args`.

Fixes #2425

* Update CHANGELOG
2024-10-24 15:56:47 +02:00
peace-maker 584eccaa33 Only print checksec output of ELF.libc when it was printed for the ELF already (#2483)
* Only print `checksec` output of `ELF.libc` when it was printed for the `ELF` already

* Update CHANGELOG
2024-10-24 15:55:37 +02:00
robbert1978 7dceeddca8 Stop using cmd.exe to keep current directory (#2488)
* Stop using cmd.exe to keep current directory

* Update misc.py

* Update misc.py, deal with cmd.exe

* Update misc.py
2024-10-24 15:51:07 +02:00
Peace-Maker 34da249779 Bump Ubuntu versions in README and bug report template 2024-10-12 18:04:01 +02:00
Peace-Maker c68c00c316 Merge branch 'beta' into dev 2024-10-12 18:01:08 +02:00
Peace-Maker 2e86d8afe2 Merge branch 'stable' into beta 2024-10-12 17:48:59 +02:00
peace-maker f28d3ebb6c Test Python version >= 3.10 in CI and fix tests on Python 3.12 (#2486)
* Bump tested python version to >= 3.10

Some workflows were using 3.8 still. Start testing on 3.12 too.

* Fix installing rpyc in CI on ubuntu 24.04

`ubuntu-latest` now points to 24.04 which requires the --break-system-packages dance.

* Test Python 2 on Ubuntu 22.04

Ubuntu 24.04 dropped the python2.7 packages.

* Test on android-34

* Fix ARM binutils disassembly output test expectation

It used to print "; 0x4" but changed to "@ 0x4" in some version.

* Skip QEMU LD_PREFIX path test

Ubuntu 24.04 seemed to have switched the qemu-user --help output to show `/usr/gnemul/qemu-$ARCH` instead of `/etc/qemu-binfmt`. Ignore the actual path in the test.

* Fix x86 ascii shellcode encoder test

The alphabet was using `\` escape sequences badly.

<stdin>:1: SyntaxWarning: invalid escape sequence '\]'

* Fix mips xor encoder unaligned memory access

qemu throws a SIGBUS error when the shellcode tries to access unaligned memory since some version. Align the "stack" properly.

* Fix util.lists.partition test output on Python 3.12

The __repr__ output of OrderedDict was changed to look like ordinary {} dicts.

* Fix safeeval test on Python 3.12

There is a 151 RESUME opcode in Python 3.12 now.

* Fix registering commandline subparsers multiple times for Python 3.11

Python 3.11 added a sanity check to argparse to prevent registering the same subparser multiple times.

argparse.ArgumentError: argument command: conflicting subparser: cyclic

Avoid importing the command twice.
`python -m pwnlib.commandline.cyclic` failed on Python 3.11 triggered in CI when running the commandline tools while collecting coverage.

* Fix pip cache in CI
2024-10-12 17:48:12 +02:00
Lorenzo Cian cfc021d88e Extract libraries from Docker image (#2479)
* feat: extract libraries from Docker image

* docs: update CHANGELOG.md

* fix: python2.7 compatibility

* address comments

* address linter
2024-10-07 11:46:05 +02:00
Peace-Maker 9f92ed04fc Fix docs of ELF.{libs,maps}
Fixes #2400
2024-10-03 12:17:06 +02:00
k4lizen b08f4b7bc8 redirect kitty kill command stderr to /dev/null (#2472) 2024-10-01 19:37:52 +02:00
Peace-Maker d664bb49d4 Merge branch 'beta' into dev 2024-09-30 00:45:22 +02:00
Peace-Maker c0d6e07f1c Release 4.14.0beta1 2024-09-30 00:34:36 +02:00
peace-maker fa5a288a69 Fix waiting for gdb under WSL2 (#2470)
* Fix returning wrong pid in WSL for run_in_new_terminal

We run cmd.exe which and other Windows processes before going back into WSL. The returned pid would be the one for the ephemeral cmd.exe process instead of the real command we wanted to launch.

I don't know how to properly trace the execution and get the command pid, so scan for newer pids matching the command for a while instead as a workaround.

We wrap the command in a script so psutil.Process.exe() returns the path to the shell instead of the real command. Look at psutil.Process.cmdline() too which contains the real program running right now.

* Make `proc.wait_for_debugger` return the debugger pid

If we fail to get the pid when launching gdb, grab it after tracing the debugger at least. gdb won't be closed when the exploit exits but at least we have the correct pid.

* Fix working directory of run_in_new_terminal in WSL

The process' cwd would be %WINDIR% due to cmd.exe not supporting WSL paths.

* Update CHANGELOG
2024-09-30 00:27:40 +02:00
peace-maker 69ab2054e8 Fix collecting coverage in CI (#2477)
The upload-artifact action v4.4.0 excluded hidden files from uploads by default. We want to upload only hidden `.coverage*` files though. Enable hidden files again using the `include-hidden-files` input.

https://github.com/actions/upload-artifact/releases/tag/v4.4.0
2024-09-30 00:20:59 +02:00
Peace-Maker 907e921043 Merge branch 'beta' into dev 2024-09-30 00:08:31 +02:00
Peace-Maker a3f14df14d Merge branch 'stable' into beta 2024-09-29 23:56:06 +02:00
Peace-Maker 78dd777735 Release 4.13.1 2024-09-29 23:41:04 +02:00
Th3Sandpeace-maker ee63072930 libcdb: improve the search speed of search_by_symbol_offsets (#2413)
* Add `hash_type` for `search_by_symbol_offsets`

* Add docs

* Update CHANGELOG

* Allow search `id` in search_by_hash

* Fix py2.7 test

* Rename `hash_type` to `search_type`

* Rename `TYPES['id']` to `TYPES['libs_id']`

* Rename part `hex_encoded_id` to `search_target`

* Turbofast extract build id

* Fix docs

* Add a map for types key

* Extract proper buildid

* Fix docs

* Fix E0606

* Simplify get `mapped_type`

* Add `search_by_libs_id` to `__all__`

* Modify docs

* Fix py2.7

* Fix reference

---------

Co-authored-by: peace-maker <[email protected]>
2024-09-29 01:53:06 +02:00
Arusekk 824d67d8f4 gdb: fix pid attach (#2474) 2024-09-28 07:32:15 +00:00
k4lizen 785ed9fdda Properly close spawned kitty window (#2471)
* properly close spawned kitty window

* python2 support

* changelog
2024-09-27 09:23:06 +02:00
Jordan ERNST 5c1fb1d11b Fix: GDB 15.1 rpyc detection (#2469)
* Fix: GDB 15 rpyc detection

* Update CHANGELOG.md

* Changelog on the right version

* Remove extra newline in CHANGELOG.md
2024-09-26 22:25:04 +02:00
peace-maker cdfd64f6de Install pwntools on Windows and import it once (#2450)
This is just a basic smoke test for now.
2024-09-26 13:44:52 +02:00
peace-maker 3727c93859 Add ELF.close() to release resources (#2444)
* Add ELF.close() to release resources

`ELFFile.close()` just closes the mmap'd file, but our own wrapper keeps the file handle open.

This is annoying when using a temporary file on Windows since they can't be deleted if there is
a dangling handle. This can be used together with the inherited context manager from ELFFile.

* Update CHANGELOG
2024-09-26 13:41:18 +02:00
Peace-Maker bc453b46c3 Merge branch 'beta' into dev 2024-09-26 01:57:52 +02:00
Peace-Maker f47e417e4e Merge branch 'stable' into beta 2024-09-26 01:29:24 +02:00
peace-maker 7c79c73a5f Backport: Fix typo for fallback to default number of console colors on windows (#2467)
* Fix typo for fallback to default number of console colors on windows

* Update CHANGELOG
2024-09-25 23:20:04 +00:00
peace-maker 3e9849f0ca Fix PLT emulation with Unicorn 2.1.0 (#2466)
* Fix PLT emulation with Unicorn 2.1.0

You cannot add multiple hooks at once anymore, so add them individually - still to the same callback.

https://github.com/unicorn-engine/unicorn/blob/f164769a9a973a3e981f279ed7aa90459ae68545/bindings/python/unicorn/unicorn_py3/unicorn.py#L970-L976

* Update CHANGELOG

* Switch to PyPi Simple API for update checks

Fault: <Fault -32500: 'RuntimeError: PyPI no longer supports the XMLRPC package_releases method. Use JSON or Simple API instead. See https://github.com/pypi/warehouse/issues/16642 and https://warehouse.pypa.io/api-reference/xml-rpc.html#deprecated-methods for more information.'>

* Update CHANGELOG

* Disable ssh.user_shstk test

Github Actions Runners have userland shadow stack enabled now apparently.
Don't test for this system state.
2024-09-25 23:01:08 +00:00
peace-maker 149ebe0c47 Fix parsing the PLT on Windows (#2445)
* Fix parsing the PLT on Windows

The Unicorn Engine 1GB workaround doesn't work since `mmap` has different semantics on Windows.

* Update CHANGELOG

* Catch ImportError instead

* Remove unused sys import
2024-09-25 23:14:58 +02:00
tesuji d7817a7eac Nicely handle non ELF files in checksec (#2457) 2024-09-11 11:22:13 +02:00
patryk4815 df620d7449 darwin: generate syscalls sdk 15.1 (#2448) 2024-08-25 12:59:14 +02:00
peace-maker 67678c2e1c Cache output of asm() (#2358)
* Cache output of `asm()`

To speed up repeated runs of an exploit, cache the assembled output.

Use a sha1 hash of the shellcode as well as relevant context values
like `context.arch` and `context.bits` to see if the exact same
shellcode was assembled for the same context before.

Fixes #2312

* Return path to cache file if `not extract`

* Update CHANGELOG

* Create temporary copy of cached file

* Add debug log about using the cache

* Include full assembler and linker commandlines in hash

This should catch any changes across pwntools updates and system environment changes.

* Include pwntools version in hash
2024-08-12 20:59:22 +02:00
Peace-Maker 734cb3bf82 Begin working on 4.15.0 2024-08-12 19:45:10 +02:00
Peace-Maker adaa6abc08 Release 4.14.0beta0 2024-08-12 19:27:23 +02:00
Peace-Maker 3e21808da9 Cleanup CHANGELOG order 2024-08-12 18:13:05 +02:00
k4lizen 405357c075 Add resolution_addr parameter to Ret2dlresolvePayload (#2436)
* add documentation for data_addr and resolution_addr

* add resolution_addr

* changelog

* changelog^2
2024-08-09 12:33:38 +02:00
peace-maker 248f4510c6 Support asm/disasm on Windows (#2437)
* Support asm/disasm on Windows

Find binutils toolchains like https://gnutoolchains.com/ if they exist in the PATH.

* Update CHANGELOG

* Update binutils install docs

* cpp reads from stdin when no infile is given

No need for a tempfile here.
2024-08-08 14:13:37 +02:00
Peace-Maker de67c86432 Fix tty_escape on Python 2 2024-08-07 23:52:33 +02:00
Peace-Maker 101f9bc76b Add documentation for tty_escape 2024-08-07 23:27:05 +02:00
Peace-Maker 4879590a37 Fix typo for fallback to default number of console colors on windows 2024-08-07 00:14:54 +02:00
dependabot[bot] 7194ced044 Bump docker/build-push-action from 5 to 6 (#2420) 2024-08-06 14:17:36 +00:00
k4lizenandpeace-maker 6a9deffbfb Add functions for retrieving process mappings (#2371)
* add to process mapping function, and stack, heap, vdso, vvar, libc _mapping properties

* better libc string mapping detection #2370

* return all mappings instead of just the first one

* add single/multiple option to every _mapping function

* undo @property tags

* added function doc comments

* added elf_mapping

* add get_mapping and refactor helpers to use it

* better doc

* add _location functions

* _location_from_mappings for libc and musl locations

* _location_from_mappings doc

* change comment

* fix executable -> path

* change comment

* python2.7 support

* changelog

* add address_mapping()

* get_mapping comment typo

* mention the path is an exact match

* add references to wrapped functions

* add missing 'the's, make sentences one line, fix 'exact' path description in get_mapping_location

* add private and shared fields to permissions object

* maps doctest

* get_mapping doctest

* stack_mapping doctest

* heap_mapping doctest

* improve stack_mapping and heap_mapping with address example

* vvar and vdso _mapping doctest

* libc_mapping doctest

* elf_mapping doctest

* _location_from_mappings doctest

* get_mapping_location doctest

* heap and stack _location doctest

* vdso vvar _location doctest

* improved vdso and vvar doctest

* elf_location doctest

* libc_location doctest

* address_mapping bugfix

* address_mapping doctest

* fix meow check

* fix len(mappings) check

* actually fix meow check

* why dont docs support format string?

* removed _location functions

* removed the rest of the _location related functions

* added lib_size()

* add lib_size() example

* replace f'' with correct syntax

* remove _location() from other doctests

* cleanup == in doctest

* change " to ' in doctests

---------

Co-authored-by: peace-maker <[email protected]>
2024-08-06 11:10:10 +02:00
mephi42 26e72f2b3e gdb.debug: avoid 2s timeout if possible (#2435)
On Ubuntu 22.04 gdb.debug() takes at least 2 seconds. This is because
it prints only "Remote debugging from host 127.0.0.1, port 33398", but
the code expects 2 lines.

It's very unclear what the second line is supposed to be; the only lead
is "* Handle extra newline printed by gdb" in commit 338fbeba ("Improve
pwnup template, gdbserver detection (#1148)"), but I could not trace it
back to the GDB source code, both historic and modern. Perhaps, there
is a non-upstreamed patch in some distro that introduces it.

It should still be safe to skip waiting for the second line if the
first one already starts with "Remote debugging ...", so do it.
2024-08-05 13:05:25 +02:00
00663aa1bf Add port, gdb_args, and gdbserver_args to gdb.debug() (#2382)
* added two arguments to gdb.debug:
+ port: specifies the port that should be used by the gdbserver (this is useful for alpine)
+ gdb_args: allows forwarding arguments to the gdb binary spawned by gdb.attach() (just a passthrough)

aslo downgraded "GDB Python API is supported only for local processes" to a warning, because it seems to work on some systems.

* added changelog entry and fixed python2.7 compatibility

* also added optional gdbserver_args parameter to gdb.debug()

* implemented requested fixes for #2382:
+ gdb.debug port is now also used for qemu
+ GDB Python API is now tested for tubes.process.process a warning for ssh.process and an error for everything else
+ updated docs to use mention that gdbserver ports are randomized by default
+ now using gdbserver_port to check if the correct port was set
+ fixed CHANGELOG.md structure

* implemented requested fixes for #2382:
+ gdb.debug port is now also used for qemu
+ GDB Python API is now tested for tubes.process.process a warning for ssh.process and an error for everything else
+ updated docs to use mention that gdbserver ports are randomized by default
+ now using gdbserver_port to check if the correct port was set
+ fixed CHANGELOG.md structure
+ added timeouts for recvline() gdb tests
+ also run gdb api tests for ssh runner

---------

Co-authored-by: gfelber <@users.noreply.github.com>
Co-authored-by: peace-maker <[email protected]>
2024-07-23 13:53:35 +02:00
Peace-Maker 18c8bfba3d Pin colored_traceback < 0.4 for Python 2 2024-07-23 13:37:26 +02:00
Jakub Nowak 4284c3fcdf Improve remote() documentation (#2427)
* Improve remote() documentation

* changelog
2024-07-09 09:23:46 +02:00
Arusekk a366e91038 Add TTY escape function for file transfer (#2422) 2024-07-02 07:04:14 +02:00
CocoaandArusekk 736cf9d112 feat: multi shellcraft cmd (#2398)
* added support for multiple shellcraft commands

* updated CHANGELOG.md

* fix `pwn shellcraft -l shellcode`

* fix `get_template`

* strip strings after spliting by the delimiter

* fix `pwn shellcraft --show shellcode`

* added some tests in ci

* better handling for splitting by delimiter

---------

Co-authored-by: Arusekk <[email protected]>
2024-06-23 16:51:23 +02:00
peace-maker 4dc8d60b9e Add "none" ssh authentication method (#2405)
* Add "none" ssh authentication method

Allow to "disable" ssh authentication if the remote server has it enabled.

Fixes #2380

* Add CHANGELOG
2024-06-17 10:03:55 +02:00
Dvorhack d5fffb6769 Shellcode socket IPV6 (#2415) 2024-06-15 18:56:45 +02:00
Th3Sandpeace-maker 51e8eb09ee libcdb: add offline_only to search_by_symbol_offsets (#2388)
* Add `offline_only` for `search_by_symbol_offsets`

* Fix bug

* Update CHANGELOG

* Remove redundant code

* Update

---------

Co-authored-by: peace-maker <[email protected]>
2024-05-23 16:57:19 +02:00
Sanjit Kumarandpeace-maker e92a30bbf7 Convert bytes-like object to string in apport_corefile() method (#2387)
* converting bytes-like object to string

* updated changelog

---------

Co-authored-by: peace-maker <[email protected]>
2024-05-12 13:26:08 +02:00
peace-maker fcec11784a Fix access of undefined ssh._tried_sftp in raw mode (#2396)
* Fix access of undefined `ssh._tried_sftp` in `raw` mode

The attribute was never set when setting `ssh(raw=True)` which caused the code to run `ssh.__getattr__` which raised an AttributeError due to `_tried_sftp` starting with an `_` on Python 3.12.

* Document all `ssh` attributes
2024-05-12 11:31:46 +02:00
qux-bbb fe560c9835 Add sudo for apt-get (#2395) 2024-04-24 12:46:07 +02:00
Peace-Maker 27366fdeb8 Merge branch 'beta' into dev 2024-04-22 00:05:28 +02:00
peace-maker f2f55f3e1c Return buffered data on first EOF in tube.readline() (#2376)
* Return buffered data on first EOF in tube.readline()

When there is still data available in the tube buffer when an EOFError occurs in
`tube.recvline()`, return that data even though it doesn't contain a newline.
The next time `tube.recvline()` is called afterwards will raise EOFError normally.

This behavior is in line with the GNU readline implementation and avoids
loss of data. It allows `tube.stream()` to print everything that's received before
the receiving end terminates.

A new warning is logged when data is returned due to an EOF informing
about the lack of the trailing newline character.

Fixes #2366

* Update CHANGELOG

* Add context.throw_eof_on_incomplete_line

Allow to control the behavior of `tube.recvline` and
be able to suppress the new warning.

* Cleanup docs
2024-04-21 22:37:46 +02:00
7ac5a34a59 Change from pop to keys for reporting proper error message (#2391)
* Change from pop to keys for reporting proper error message

* update changelog

* add doctest for xor

* Add newline to run xor doctests

* Switch to `dict.popitem()`

---------

Co-authored-by: marinelay <[email protected]>
Co-authored-by: Peace-Maker <[email protected]>
2024-04-21 22:22:46 +02:00
eec3321ae9 Fix passing bytes to context.log_file and crc.BitPolynom (#2389)
* Fix incosistent usage of bytes/str

* update changelog

* Update CHANGELOG

---------

Co-authored-by: marinelay <[email protected]>
Co-authored-by: Peace-Maker <[email protected]>
2024-04-21 22:18:28 +02:00
Lewis Watson d2a02a7b37 Updated Mac OS Install Documentation (#2392)
* Added Missing MacOS Requirements

* Updated Binutils Install Docs

Due to security reasons Homebrew has removed direct formula references, this is the workaround.

* Updated changelog for #2392

* reverting changelog
2024-04-21 22:14:55 +02:00
peace-maker c1ce1897df Fix duplicate definition of ssh.sftp (#2394) 2024-04-21 22:13:56 +02:00
peace-maker 5981c7290d Change newline when setting context.os to "windows" (#2330)
* Change newline when setting `context.os`

Windows uses `b'\r\n'` for newlines while unix uses `b'\n'`. Change the expected newline to `b'\r\n'` when setting `context.os = "windows"` automatically for convenience.

* Update CHANGELOG

* Fix other tests setting os
2024-03-29 17:52:34 +01:00
peace-makerandLevitatingLion cb540857cc Add basic RISCV64 shellcraft support (#2322)
* Add basic RISCV64 shellcraft support

The `mov` template isn't 100% null-byte and newline free
for all inputs. Certain larger values are just emitted using
the `li` pseudo-instruction by the assembler which might
contain null-bytes.

Co-authored-by: LevitatingLion <[email protected]>

* Generate RISCV syscall constants from musl-libc

diet-libc doesn't support RISCV, so borrow from musl.
Need to consider their license.

* Update CHANGELOG

* Fix CHANGELOG

---------

Co-authored-by: LevitatingLion <[email protected]>
2024-03-29 17:28:50 +01:00
peace-maker 8ba1bdf0b6 Add basic support to debug processes on Windows (#2327)
* Add basic support to debug processes on Windows

Currently only `windbg.debug()` and `windbg.attach()` are implemented,
which open a WinDbg instance and attach to the process.

* Update CHANGELOG

* Cleanup CheckRemoteDebuggerPresent call

Only require PROCESS_QUERY_INFORMATION access and check for errors when opening the process.

* process.close: Move closing of std fds after kill

Windows processes would block on fd.close() when the main thread is suspended.
2024-03-29 16:04:56 +01:00
Th3S 4ac98cd11a Add offline parameter for libcdb.search_by_hash series function (#2360)
* Add offline parameter

* Add CHANGELOG

* Rename `offline` to `offline_only`
2024-03-29 15:27:38 +01:00
Swastik Sarkar 75cc3c3d5c libcdb.unstrip_libc: debug symbols are fetched only if not present (#2374)
* libcdb.unstrip_libc: debug symbols are fetched only if not present

* Usage of `ELF.debuginfo` to check if debug symbols exist

closes #2324

---------

Signed-off-by: sswastik02 <[email protected]>

* Add CHANGELOG

Signed-off-by: sswastik02 <[email protected]>

---------

Signed-off-by: sswastik02 <[email protected]>
2024-03-24 13:19:31 +01:00
Peace-Maker a2acdf9bd9 Pin pyelftools<0.30 for Python 2 in docs/requirements.txt
Docs only installs fail under python2 due to trying to install pyelftools>=0.30 which dropped py2 support.

Fixes #2372
2024-03-22 20:32:57 +01:00
Pratik Raj 14c0d73f89 feat : use --no-cache-dir flag to pip in dockerfiles to save space (#2357)
using the "--no-cache-dir" flag in pip install, make sure downloaded packages by pip don't cache on the system. This is a best practice that makes sure to fetch from a repo instead of using a local cached one. Further, in the case of Docker Containers, by restricting caching, we can reduce image size. In terms of stats, it depends upon the number of python packages multiplied by their respective size. e.g for heavy packages with a lot of dependencies it reduces a lot by don't cache pip packages.

Further, more detailed information can be found at

https://medium.com/sciforce/strategies-of-docker-images-optimization-2ca9cc5719b6

Signed-off-by: Pratik Raj <[email protected]>
2024-03-07 13:38:36 +01:00
Th3S 3b4b261b5a Add local libc database provider for libcdb (#2356)
* Add local libc database provider for libcdb

* Remove unnecessary assert

* Add docstring for local_libcdb

* Suppress warning output while `context.libdb` sets default

* Testing the local system's libc first

* Set falsely `context.lcoal_libcdb` to turn off local libc-database integration

* Fix docstring

* Make path check in validator

* Fix doctests

* Add CHANGELOG
2024-03-01 13:01:09 +01:00
Peace-Maker 000c31c155 ci: Install rpyc from pip instead of apt
The apt package appears outdated and incompatible with the latest version on pypi.

>>> ValueError: invalid message type: 18
2024-02-25 14:39:51 +01:00
Peace-Maker 197f00806e Merge branch 'beta' into dev 2024-02-22 23:08:02 +01:00
Peace-Maker e1770a3045 Begin working on 4.14.0 2024-02-22 22:49:41 +01:00
141 changed files with 8551 additions and 936 deletions

No files matched your search

+1 -1
View File
@@ -39,7 +39,7 @@ You should see `[DEBUG]` statements that show what's happening behind the scenes
## Verify on Ubuntu
If possible, please verify that your issue occurs on 64-bit Ubuntu 18.04. We provide a Dockerfile based on Ubuntu 18.04 via `docker.io` to make this super simple, no VM required!
If possible, please verify that your issue occurs on 64-bit Ubuntu 22.04. We provide a Dockerfile based on Ubuntu 22.04 via `docker.io` to make this super simple, no VM required!
```sh
# Download the Docker image
+18 -8
View File
@@ -6,24 +6,21 @@ jobs:
android-test:
strategy:
matrix:
python-version: [3.8]
python-version: ['3.10']
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Cache for pip
uses: actions/cache@v4
id: cache-pip
with:
path: ~/.cache/pip
key: ${{ matrix.os }}-cache-pip
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: |
**/pyproject.toml
**/requirements*.txt
- name: Install Linux dependencies
run: |
@@ -35,6 +32,19 @@ jobs:
binutils-arm-linux-gnueabihf \
libc6-dbg
- name: Cache for avd
uses: actions/cache@v4
id: cache-avd
with:
path: |
~/.android
/usr/local/lib/android/sdk/emulator
/usr/local/lib/android/sdk/platform-tools
/usr/local/lib/android/sdk/system-images
key: ${{ matrix.os }}-cache-avd-${{ hashFiles('travis/setup_avd*.sh') }}
restore-keys: |
${{ matrix.os }}-cache-avd-
- name: Install Android AVD
run: |
sudo usermod -aG kvm $USER
+95 -8
View File
@@ -5,10 +5,29 @@ jobs:
test:
strategy:
matrix:
python_version: ['2.7', '3.10']
python_version: ['3.10', '3.12', '3.13', '3.14', '3.15']
os: [ubuntu-latest]
include:
- python_version: '2.7'
os: ubuntu-22.04
runs-on: ${{ matrix.os }}
timeout-minutes: 30
services:
libcdb-cache:
image: nginx
volumes:
- /home/runner/libcdb-cache:/var/cache/nginx
ports:
- 3000:3000 # https://debuginfod.elfutils.org proxy cache
- 3001:3001 # https://libc.rip/ proxy cache
- 3002:3002 # http://archive.ubuntu.com/ proxy cache
- 3003:3003 # https://gitlab.com/ proxy cache
- 3004:3004 # https://debuginfod.ubuntu.com/ proxy cache
env:
DEBUGINFOD_URLS: "http://localhost:3000/ http://localhost:3004/"
PWN_LIBCRIP_URL: http://localhost:3001/
PWN_UBUNTU_ARCHIVE_URL: http://localhost:3002/
PWN_GITLAB_LIBCDB_URL: http://localhost:3003/
steps:
- uses: actions/checkout@v4
with:
@@ -18,26 +37,54 @@ jobs:
run: |
git fetch origin
git log --oneline --graph -10
- name: Fix libcdb-cache permissions
id: fix-perms
run: |
sudo chown -R runner:runner /home/runner/libcdb-cache
echo "date=$(/bin/date -u "+%Y%m%d%H%M%S")" >> $GITHUB_OUTPUT
- name: Cache for libcdb requests
uses: actions/cache@v4
with:
path: ~/libcdb-cache
key: libcdb-python${{ matrix.python_version }}-${{ steps.fix-perms.outputs.date }}
restore-keys: |
libcdb-python${{ matrix.python_version }}-
libcdb-
- name: Install libcdb-cache service config
run: |
sudo chown -R 101:101 /home/runner/libcdb-cache
container_id=$(docker ps --all --filter volume=/home/runner/libcdb-cache --no-trunc --format "{{.ID}}")
docker cp ./travis/libcdb_nginx_cache.conf $container_id:/etc/nginx/nginx.conf
docker restart $container_id
- name: Install RPyC for gdb
run: |
# The version packaged in python3-rpyc is too old on Ubuntu 22.04
# The version packaged in python3-rpyc is too old on Ubuntu 24.04
# We use ^6.0 from pip.
sudo apt-get update && sudo apt-get install -y python3-pip gdb gdbserver
/usr/bin/python -m pip install rpyc
/usr/bin/python -m pip install --break-system-packages rpyc || /usr/bin/python -m pip install rpyc
gdb --batch --quiet --nx --nh --ex 'py import rpyc; print(rpyc.version.version)'
- name: Cache for pip
uses: actions/cache@v4
id: cache-pip
if: matrix.python_version == '2.7'
with:
path: ~/.cache/pip
key: ${{ matrix.os }}-cache-pip
key: ${{ matrix.os }}-${{ matrix.python_version }}-cache-pip-${{ hashFiles('**/pyproject.toml', '**/requirements*.txt') }}
restore-keys: ${{ matrix.os }}-${{ matrix.python_version }}-cache-pip-
- name: Set up Python ${{ matrix.python_version }}
if: matrix.python_version != '2.7'
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python_version }}
cache: 'pip'
cache-dependency-path: |
**/pyproject.toml
**/requirements*.txt
- name: Set up Python 2.7
if: matrix.python_version == '2.7'
@@ -74,10 +121,12 @@ jobs:
binutils-aarch64-linux-gnu \
binutils-arm-linux-gnueabihf \
binutils-mips-linux-gnu \
binutils-mipsel-linux-gnu \
binutils-msp430 \
binutils-powerpc-linux-gnu \
binutils-s390x-linux-gnu \
binutils-sparc64-linux-gnu \
binutils-riscv64-linux-gnu \
gcc-multilib \
libc6-dbg \
elfutils \
@@ -101,6 +150,8 @@ jobs:
pip install --upgrade wheel build
pip install --upgrade flake8 appdirs
pip install --upgrade --editable .
# Pin to known working version until 2.1.5 is out. https://github.com/unicorn-engine/unicorn/issues/2134
pip install 'unicorn==2.1.2'
- name: Sanity checks
run: PWNLIB_NOTERM=1 python -bb -c 'from pwn import *; print(pwnlib.term.term_mode)'
@@ -149,11 +200,18 @@ jobs:
pwn shellcraft --list |tail
pwn shellcraft -l --syscalls |tail
pwn shellcraft -l execve
pwn shellcraft -l execve + exit
pwn shellcraft --show i386.linux.loader_append
pwn shellcraft --show i386.linux.loader_append + i386.linux.sh
pwn shellcraft -f asm --color amd64.linux.sh
pwn shellcraft -f asm --color amd64.linux.setreuid + amd64.linux.cat /etc/passwd
pwn shellcraft -f asm --color amd64.linux.setreuid = amd64.linux.cat /key+secret --delim =
pwn shellcraft -f elf amd64.linux.syscalls.exit 0 </dev/null |pwn hex
pwn shellcraft -f elf amd64.linux.cat /etc/passwd + amd64.linux.syscalls.exit 0 </dev/null |pwn hex
pwn shellcraft -f i --color amd64.linux.cat /etc/passwd </dev/null
pwn shellcraft -f i --color amd64.linux.cat /etc/passwd + amd64.linux.sh </dev/null
pwn shellcraft -f c amd64.linux.syscalls.exit 0 </dev/null
pwn shellcraft -f c amd64.linux.cat /etc/passwd + amd64.linux.syscalls.exit 0 </dev/null
pwn shellcraft -f str aarch64.linux.sh </dev/null
pwn shellcraft -abr -f elf -o /dev/null amd64.linux.cat /etc/passwd </dev/null
pwn shellcraft -nzr thumb.linux.syscalls.execve /bin/cat '["/bin/cat", "/etc/os-release"]' </dev/null
@@ -195,16 +253,45 @@ jobs:
python -m build
- uses: actions/upload-artifact@v4
if: matrix.python_version != '2.7'
if: matrix.python_version == '3.10'
with:
name: packages
path: dist/
include-hidden-files: true
- uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.python_version }}
path: .coverage*
include-hidden-files: true
- name: Fix libcdb-cache permissions
run: |
container_id=$(docker ps --filter volume=/home/runner/libcdb-cache --no-trunc --format "{{.ID}}")
docker stop $container_id
sudo chown -R runner:runner /home/runner/libcdb-cache
windows-test:
runs-on: windows-latest
timeout-minutes: 30
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install --upgrade pip
pip install --upgrade --editable .
- name: Sanity checks
run: |
python -bb -c 'from pwn import *'
python -bb examples/text.py
upload-coverage:
runs-on: ubuntu-latest
@@ -221,7 +308,7 @@ jobs:
- name: Install coveralls
run: |
pip install tomli coveralls
pip install --break-system-packages tomli coveralls || pip install tomli coveralls
- name: Upload coverage to coveralls.io
run: |
+5 -5
View File
@@ -22,7 +22,7 @@ jobs:
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build and push base image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
if: github.event_name == 'workflow_dispatch'
with:
context: "{{defaultContext}}:extra/docker/base"
@@ -30,7 +30,7 @@ jobs:
tags: pwntools/pwntools:base
- name: Build and push stable image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/stable')
with:
context: "{{defaultContext}}:extra/docker/stable"
@@ -38,7 +38,7 @@ jobs:
tags: pwntools/pwntools:stable
- name: Build and push beta image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/beta')
with:
context: "{{defaultContext}}:extra/docker/beta"
@@ -46,7 +46,7 @@ jobs:
tags: pwntools/pwntools:beta
- name: Build and push dev image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/dev')
with:
context: "{{defaultContext}}:extra/docker/dev"
@@ -56,7 +56,7 @@ jobs:
pwntools/pwntools:latest
- name: Build and push ci image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/dev')
with:
context: "{{defaultContext}}:travis/docker"
+5 -7
View File
@@ -5,23 +5,21 @@ jobs:
lint:
strategy:
matrix:
python-version: [3.8]
python-version: ['3.10']
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Cache for pip
uses: actions/cache@v4
id: cache-pip
with:
path: ~/.cache/pip
key: ${{ matrix.os }}-cache-pip
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: |
**/pyproject.toml
**/requirements*.txt
- name: Critical lint
run: |
+9 -10
View File
@@ -5,33 +5,32 @@ jobs:
build:
strategy:
matrix:
python-version: [3.8]
python-version: ['3.10']
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Cache for pip
uses: actions/cache@v4
id: cache-pip
with:
path: ~/.cache/pip
key: ${{ matrix.os }}-cache-pip
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: |
**/pyproject.toml
**/requirements*.txt
- name: PyLint
run: |
set -x
pip install pylint
pip install 'pylint<4'
pip install --upgrade -e .
pylint --exit-zero --errors-only pwnlib -f parseable | cut -d ' ' -f2- > current.txt
run_pylint() { pylint --exit-zero --errors-only pwnlib -f parseable | cut -d ' ' -f2- | sed 's/line [0-9]\+/line XXXX/g'; }
run_pylint > current.txt
git fetch origin
git checkout origin/"$GITHUB_BASE_REF"
pylint --exit-zero --errors-only pwnlib -f parseable | cut -d ' ' -f2- > base.txt
run_pylint > base.txt
if diff base.txt current.txt | grep '>'; then
false
fi
+1 -1
View File
@@ -5,7 +5,7 @@ version: 2
build:
os: ubuntu-22.04
tools:
python: "3"
python: "3.12"
sphinx:
configuration: docs/source/conf.py
+205 -9
View File
@@ -9,9 +9,12 @@ The table below shows which release corresponds to each branch, and what date th
| Version | Branch | Release Date |
| ---------------- | -------- | ---------------------- |
| [4.15.0](#4150-dev) | `dev` |
| [4.14.0](#4140-beta) | `beta` |
| [4.13.0](#4130-stable) | `stable` | Aug 12, 2024
| [5.0.0](#500-dev) | `dev` |
| [4.15.0](#4150-stable) | `stable` | Oct 12, 2025
| [4.14.1](#4141) | | Mar 24, 2025
| [4.14.0](#4140) | | Jan 15, 2025
| [4.13.1](#4131) | | Sep 29, 2024
| [4.13.0](#4130) | | Aug 12, 2024
| [4.12.0](#4120) | | Feb 22, 2024
| [4.11.1](#4111) | | Nov 14, 2023
| [4.11.0](#4110) | | Sep 15, 2023
@@ -70,11 +73,189 @@ The table below shows which release corresponds to each branch, and what date th
| [3.0.0](#300) | | Aug 20, 2016
| [2.2.0](#220) | | Jan 5, 2015
## 4.15.0 (`dev`)
## 5.0.0 (`dev`)
- [#2419][2419] riscv: avoid compressed instructions (if you need compressed, use .option rvc)
- [#2551][2551] Detect when kitty is being used as terminal
- [#2519][2519] Drop Python 2.7 support / Require Python 3.10
- [#2507][2507] Add `+LINUX` and `+WINDOWS` doctest options and start proper testing on Windows
- [#2522][2522] Support starting a kitty debugging window with the 'kitten' command
- [#2526][2526] Properly make use of extra arguments in `packing` utilities. `sign` parameter requires keyword syntax to specify it.
- [#2517][2517] Allow to passthru kwargs on `ssh.__getattr__` convenience function to fix SSH motd problems
- [#2529][2529] Add LoongArch64 support
- [#2504][2504] doc: add example case for `tuple` (host, port pair) in `gdb.attach`
- [#2546][2546] ssh: Allow passing disabled_algorithms keyword argument from ssh to paramiko
- [#2538][2538] Add `ssh -L` / `ssh.connect_remote()` workaround when `AllowTcpForwarding` is disabled
- [#2574][2574] Allow creating an ELF from in-memory bytes
- [#2575][2575] Detect when Terminator is being used as terminal
- [#2578][2578] Add gnome-terminal, Alacritty, Ttilix for run_in_new_terminal
- [#2590][2590] Add support for finding corefiles under WSL2
- [#2496][2496] Add linux ko file search support
- [#2542][2542] Decode `_IO_*` flags in `FileStructure` member
- [#2608][2608] Abort on `libcdb file libc.so --unstrip` if eu-unstrip is not installed
- [#2611][2611] Cleanup `pwnlib.lexer` exports and imports
- [#2615][2615] tube/process: Fix redirecting stderr to stdout on Windows
[2419]: https://github.com/Gallopsled/pwntools/pull/2419
[2551]: https://github.com/Gallopsled/pwntools/pull/2551
[2519]: https://github.com/Gallopsled/pwntools/pull/2519
[2507]: https://github.com/Gallopsled/pwntools/pull/2507
[2522]: https://github.com/Gallopsled/pwntools/pull/2522
[2526]: https://github.com/Gallopsled/pwntools/pull/2526
[2517]: https://github.com/Gallopsled/pwntools/pull/2517
[2529]: https://github.com/Gallopsled/pwntools/pull/2529
[2504]: https://github.com/Gallopsled/pwntools/pull/2504
[2546]: https://github.com/Gallopsled/pwntools/pull/2546
[2538]: https://github.com/Gallopsled/pwntools/pull/2538
[2574]: https://github.com/Gallopsled/pwntools/pull/2574
[2575]: https://github.com/Gallopsled/pwntools/pull/2575
[2578]: https://github.com/Gallopsled/pwntools/pull/2578
[2590]: https://github.com/Gallopsled/pwntools/pull/2590
[2496]: https://github.com/Gallopsled/pwntools/pull/2496
[2542]: https://github.com/Gallopsled/pwntools/pull/2542
[2608]: https://github.com/Gallopsled/pwntools/pull/2608
[2611]: https://github.com/Gallopsled/pwntools/pull/2611
[2615]: https://github.com/Gallopsled/pwntools/pull/2615
## 4.14.0 (`beta`)
## 4.15.1
- [#2694][2694] fix: pad bytes fields to correct field size in FileStructure
- [#2701][2701] Fix `adb._build_date()` crash on devices with non-standard locale date strings
- [#2721][2721] Allow running with Unicorn 2.1.[34] but throw when emulating MIPS
- [#2773][2773] Disable debuginfod doctests in libcdb.unstrip_libc
- [#2772][2772] fix(packing): `dd()` no longer crashes on a `bytearray` destination
- [#2787][2787] gdb.corefile: Run gdb directly to prevent detach race
- [#2795][2795] regsort: Fix self-assignment detection through register aliases
- [#2524][2524] Raise EOFError during `process.recv` when stdout closes on Windows
- [#2530][2530] Do NOT error when passing directory arguments in `checksec` commandline tool.
- [#2506][2506] ROP: fix `ROP(ELF(exe)).leave` is `None` in some ELF
- [#2592][2592] pwnlib.config: Fix customization of `context.timeout`
- [#2598][2598] aarch64: Fix ABI definition
- [#2610][2610] Fix `log.progress` ignoring `context.log_console`
- [#2627][2627] Remove `pwnlib.util.iters.lookahead` (broken anyway, fails on Python 3.14+)
- [#2653][2653] Add aarch64_be qemu mapping
- [#2642][2642] Remove `pip` as explicit dependency
- [#2646][2646] fix(libcdb-cli): return early if no matched libc found
- [#2669][2669] asm: try native binutils before fallback architectures
- [#2677][2677] refactor: replace unsafe eval with safeeval.const in ROP cache loading
- [#2699][2699] Fix `tty` and `raw` arguments in `ssh.process()`
- [#2688][2688] Close SSH client connection when authentication failed
- [#2704][2704] ssh: Fix distro lookup on Ubuntu 24.04+
- [#2762][2762] fix(srop): correct amd64 SigreturnFrame `uc_sigmask` offset
- [#2767][2767] Support paginated libc.rip API requests to include all search results
- [#2739][2739] shellcraft: migrate lazy importer to find_spec for Python 3.12+
- [#2792][2792] Fix deprecation warning for not using `RLIM_INFINITY` in `resource.setrlimit` (Python 3.15)
[2694]: https://github.com/Gallopsled/pwntools/pull/2694
[2701]: https://github.com/Gallopsled/pwntools/pull/2701
[2721]: https://github.com/Gallopsled/pwntools/pull/2721
[2773]: https://github.com/Gallopsled/pwntools/pull/2773
[2772]: https://github.com/Gallopsled/pwntools/pull/2772
[2787]: https://github.com/Gallopsled/pwntools/pull/2787
[2795]: https://github.com/Gallopsled/pwntools/pull/2795
[2524]: https://github.com/Gallopsled/pwntools/pull/2524
[2530]: https://github.com/Gallopsled/pwntools/pull/2530
[2506]: https://github.com/Gallopsled/pwntools/pull/2506
[2592]: https://github.com/Gallopsled/pwntools/pull/2592
[2598]: https://github.com/Gallopsled/pwntools/pull/2598
[2610]: https://github.com/Gallopsled/pwntools/pull/2610
[2627]: https://github.com/Gallopsled/pwntools/pull/2627
[2653]: https://github.com/Gallopsled/pwntools/pull/2653
[2642]: https://github.com/Gallopsled/pwntools/pull/2642
[2646]: https://github.com/Gallopsled/pwntools/pull/2646
[2669]: https://github.com/Gallopsled/pwntools/pull/2669
[2677]: https://github.com/Gallopsled/pwntools/pull/2677
[2699]: https://github.com/Gallopsled/pwntools/pull/2699
[2688]: https://github.com/Gallopsled/pwntools/pull/2688
[2704]: https://github.com/Gallopsled/pwntools/pull/2704
[2762]: https://github.com/Gallopsled/pwntools/pull/2762
[2767]: https://github.com/Gallopsled/pwntools/pull/2767
[2739]: https://github.com/Gallopsled/pwntools/pull/2739
[2792]: https://github.com/Gallopsled/pwntools/pull/2792
## 4.15.0 (`stable`)
- [#2508][2508] Ignore a warning when compiling with asm on nix
- [#2471][2471] Properly close spawned kitty window
- [#2358][2358] Cache output of `asm()`
- [#2457][2457] Catch exception of non-ELF files in checksec.
- [#2444][2444] Add `ELF.close()` to release resources
- [#2413][2413] libcdb: improve the search speed of `search_by_symbol_offsets` in local libc-database
- [#2470][2470] Fix waiting for gdb under WSL2
- [#2479][2479] Support extracting libraries from Docker image in `pwn template`
- [#2483][2483] Only print `checksec` output of `ELF.libc` when it was printed for the `ELF` already
- [#2482][2482] Throw error when using `sni` and setting `server_hostname` manually in `remote`
- [#2478][2478] libcdb-cli: add `--offline-only`, refactor unstrip and add fetch parser for download libc-database
- [#2484][2484] Allow to disable caching
- [#2291][2291] Fix attaching to a gdbserver with tuple `gdb.attach(('0.0.0.0',12345))`
- [#2410][2410] Add `tube.upload_manually` to upload files in chunks
- [#2502][2502] Fix loading ELF files without valid .dynamic section
- [#2476][2476] Deprecate 'keepends' argument in favor of 'drop' in `tube.recvline*`
- [#2364][2364] Deprecate direct commandline scripts invocation and exclude nonsense ones
- [#2570][2570] Fix `pwn template` to skip Docker library extraction for statically linked binaries
- [#2545][2545] SSH: fix download/upload with -1 exit status
- [#2567][2567] Fix mistakenly parsing of ld-linux error messages.
- [#2576][2576] regsort: respect register aliases
- [#2595][2595] libcdb: Add Ubuntu and Debian debuginfod servers to default list
- [#2593][2593] Use unicorn on macOS w/ SIP enabled
- [#2587][2587] Support longer function names in Windows `getexport` shellcode
- [#2596][2596] Ignore `colored_traceback` error when TERM envvar is unset
- [#2579][2579] Fix poll error in `process.libs()` and clean up maps parsing
- [#2602][2602] Allow setting debugger path via context.gdb_binary
- [#2609][2609] Fix log level of child remotes of `server` tube
- [#2612][2612] Fix lookup of binutils for `mipsel` architecture
- [#2624][2624] Fix regression: gdbserver can't handle command-line argument containing whitespace
[2508]: https://github.com/Gallopsled/pwntools/pull/2508
[2471]: https://github.com/Gallopsled/pwntools/pull/2471
[2358]: https://github.com/Gallopsled/pwntools/pull/2358
[2457]: https://github.com/Gallopsled/pwntools/pull/2457
[2444]: https://github.com/Gallopsled/pwntools/pull/2444
[2413]: https://github.com/Gallopsled/pwntools/pull/2413
[2470]: https://github.com/Gallopsled/pwntools/pull/2470
[2479]: https://github.com/Gallopsled/pwntools/pull/2479
[2483]: https://github.com/Gallopsled/pwntools/pull/2483
[2482]: https://github.com/Gallopsled/pwntools/pull/2482
[2478]: https://github.com/Gallopsled/pwntools/pull/2478
[2484]: https://github.com/Gallopsled/pwntools/pull/2484
[2291]: https://github.com/Gallopsled/pwntools/pull/2291
[2410]: https://github.com/Gallopsled/pwntools/pull/2410
[2502]: https://github.com/Gallopsled/pwntools/pull/2502
[2476]: https://github.com/Gallopsled/pwntools/pull/2476
[2364]: https://github.com/Gallopsled/pwntools/pull/2364
[2570]: https://github.com/Gallopsled/pwntools/pull/2570
[2545]: https://github.com/Gallopsled/pwntools/pull/2545
[2567]: https://github.com/Gallopsled/pwntools/pull/2567
[2576]: https://github.com/Gallopsled/pwntools/pull/2576
[2595]: https://github.com/Gallopsled/pwntools/pull/2595
[2593]: https://github.com/Gallopsled/pwntools/pull/2593
[2587]: https://github.com/Gallopsled/pwntools/pull/2587
[2596]: https://github.com/Gallopsled/pwntools/pull/2596
[2579]: https://github.com/Gallopsled/pwntools/pull/2579
[2602]: https://github.com/Gallopsled/pwntools/pull/2602
[2609]: https://github.com/Gallopsled/pwntools/pull/2609
[2612]: https://github.com/Gallopsled/pwntools/pull/2612
[2624]: https://github.com/Gallopsled/pwntools/pull/2624
## 4.14.1
- [#2451][2451] Show symbols defined to value 0 (start of file)
- [#2533][2533] Fix installation on Python 3.5 and lower
- [#2518][2518] fix: update apport coredump path handling for CorefileFinder
- [#2552][2552] Fix memcpy shellcraft template off-by-one
- [#2559][2559] Fix parsing corefile with missing auxv
- [#2562][2562] Fix syntax highlighting of multiline comments in ASM
- [#2565][2565] Exclude broken Unicorn
[2451]: https://github.com/Gallopsled/pwntools/pull/2451
[2533]: https://github.com/Gallopsled/pwntools/pull/2533
[2518]: https://github.com/Gallopsled/pwntools/pull/2518
[2552]: https://github.com/Gallopsled/pwntools/pull/2552
[2559]: https://github.com/Gallopsled/pwntools/pull/2559
[2562]: https://github.com/Gallopsled/pwntools/pull/2562
[2565]: https://github.com/Gallopsled/pwntools/pull/2565
## 4.14.0
- [#2356][2356] Add local libc database provider for libcdb
- [#2360][2360] Add offline parameter for `search_by_hash` series function
@@ -96,6 +277,7 @@ The table below shows which release corresponds to each branch, and what date th
- [#2382][2382] added optional port, gdb_args and gdbserver_args parameters to gdb.debug()
- [#2435][2435] Speed up gdbserver handshake in gdb.debug()
- [#2436][2436] Add resolution_addr parameter to Ret2dlresolvePayload
- [#2497][2497] Fix remote.fromsocket() to handle AF_INET6 socket
[2436]: https://github.com/Gallopsled/pwntools/pull/2436
[2371]: https://github.com/Gallopsled/pwntools/pull/2371
@@ -117,8 +299,22 @@ The table below shows which release corresponds to each branch, and what date th
[2382]: https://github.com/Gallopsled/pwntools/pull/2382
[2435]: https://github.com/Gallopsled/pwntools/pull/2435
[2437]: https://github.com/Gallopsled/pwntools/pull/2437
[2497]: https://github.com/Gallopsled/pwntools/pull/2497
## 4.13.0 (`stable`)
## 4.13.1
- [#2445][2445] Fix parsing the PLT on Windows
- [#2466][2466] Fix PLT emulation with Unicorn 2.1.0
- [#2466][2466] Switch to PyPi Simple API for update checks
- [#2467][2467] Fix loading at all on Windows
- [#2469][2469] GDB 15+ rpyc detection
[2445]: https://github.com/Gallopsled/pwntools/pull/2445
[2466]: https://github.com/Gallopsled/pwntools/pull/2466
[2467]: https://github.com/Gallopsled/pwntools/pull/2467
[2469]: https://github.com/Gallopsled/pwntools/pull/2469
## 4.13.0
- [#2242][2242] Term module revamp: activating special handling of terminal only when necessary
- [#2277][2277] elf: Resolve more relocations into GOT entries
@@ -130,7 +326,7 @@ The table below shows which release corresponds to each branch, and what date th
- [#2308][2308] Fix WinExec shellcraft to make sure it's 16 byte aligned
- [#2279][2279] Make `pwn template` always set context.binary
- [#2310][2310] Add support to start a process on Windows
- [#2335][2335] Add lookup optimizations in DynELF
- [#2335][2335] Add lookup optimizations in DynELF
- [#2334][2334] Speed up disasm commandline tool with colored output
- [#2328][2328] Lookup using $PATHEXT file extensions in `which` on Windows
- [#2189][2189] Explicitly define p64/u64 functions for IDE support
@@ -217,7 +413,7 @@ The table below shows which release corresponds to each branch, and what date th
## 4.11.0
- [#2185][2185] make fmtstr module able to create payload without $ notation
- [#2185][2185] make fmtstr module able to create payload without $ notation
- [#2103][2103] Add search for libc binary by leaked function addresses `libcdb.search_by_symbol_offsets()`
- [#2177][2177] Support for RISC-V 64-bit architecture
- [#2186][2186] Enhance `ELF.nx` and `ELF.execstack`
@@ -492,7 +688,7 @@ In memoriam — [Zach Riggle][zach] — long time contributor and maintainer of
[fecf9f]: http://github.com/Gallopsled/pwntools/commit/fecf9f
[1454]: https://github.com/Gallopsled/pwntools/pull/1454
## 4.1.7 (`stable`)
## 4.1.7
- [#1615][1615] Fix aarch64 pushstr and pushstr_array
+3 -3
View File
@@ -32,13 +32,13 @@ To get you started, we've provided some example solutions for past CTF challenge
# Installation
Pwntools is best supported on 64-bit Ubuntu LTS releases (14.04, 16.04, 18.04, and 20.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.).
Pwntools is best supported on 64-bit Ubuntu LTS releases (18.04, 20.04, 22.04, and 24.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.).
Python3 is suggested, but Pwntools still works with Python 2.7. Most of the functionality of pwntools is self-contained and Python-only. You should be able to get running quickly with
```sh
apt-get update
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
sudo apt-get update
sudo apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntools
```
+5 -4
View File
@@ -2,13 +2,14 @@ capstone
coverage[toml]
python-dateutil
doc2dash
docutils<0.18
docutils<0.18; python_version<'3'
docutils>=0.18; python_version>='3'
intervaltree
isort
mako>=1.0.0
paramiko>=1.15.2
pip>=6.0.8
pyelftools>=0.2.3
pyelftools>=0.29, <0.30; python_version<'3'
pyelftools>=0.29; python_version>='3'
pygments>=2.0
pypandoc
pyserial>=2.7
@@ -17,6 +18,6 @@ psutil
requests>=2.5.1
ropgadget>=5.3
sphinx==1.8.6; python_version<'3'
sphinx>=4.5.0; python_version>='3'
sphinx>=8.1.3, <9; python_version>='3'
sphinx_rtd_theme
sphinxcontrib-autoprogram<=0.1.5
+3
View File
@@ -360,6 +360,9 @@ def linkcode_resolve(domain, info):
else:
filename = info['module'].replace('.', '/') + '.py'
if isinstance(val, property):
val = val.fget
if isinstance(val, (types.ModuleType, types.MethodType, types.FunctionType, types.TracebackType, types.FrameType, types.CodeType) + six.class_types):
try:
lines, first = inspect.getsourcelines(val)
+1
View File
@@ -77,6 +77,7 @@ Each of the ``pwntools`` modules is documented here.
update
useragents
util/*
windbg
.. toctree::
:hidden:
+7 -4
View File
@@ -15,6 +15,9 @@ following system libraries installed.
install/*
Note: For Mac OS X you will need to have cmake ``brew install cmake`` and pkg-config ``brew install pkg-config`` installed.
Released Version
-----------------
@@ -25,8 +28,8 @@ Python3
.. code-block:: bash
$ apt-get update
$ apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
$ sudo apt-get update
$ sudo apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
$ python3 -m pip install --upgrade pip
$ python3 -m pip install --upgrade pwntools
@@ -40,8 +43,8 @@ Additionally, due to `pip` dropping support for Python2, a specfic version of `p
.. code-block:: bash
$ apt-get update
$ apt-get install python python-pip python-dev git libssl-dev libffi-dev build-essential
$ sudo apt-get update
$ sudo apt-get install python python-pip python-dev git libssl-dev libffi-dev build-essential
$ python2 -m pip install --upgrade pip==20.3.4
$ python2 -m pip install --upgrade pwntools
+13 -6
View File
@@ -18,28 +18,35 @@ Ubuntu Xenial (16.04) has official packages for most architectures, and does not
.. code-block:: bash
$ apt-get install software-properties-common
$ apt-add-repository ppa:pwntools/binutils
$ apt-get update
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:pwntools/binutils
$ sudo apt-get update
Then, install the binutils for your architecture.
.. code-block:: bash
$ apt-get install binutils-$ARCH-linux-gnu
$ sudo apt-get install binutils-$ARCH-linux-gnu
Mac OS X
^^^^^^^^^^^^^^^^
Mac OS X is just as easy, but requires building binutils from source.
However, we've made ``homebrew`` recipes to make this a single command.
However, we've made ``homebrew`` recipes to make this just two commands.
After installing `brew <https://brew.sh>`__, grab the appropriate
recipe from our `binutils
repo <https://github.com/Gallopsled/pwntools-binutils/>`__.
.. code-block:: bash
$ brew install https://raw.githubusercontent.com/Gallopsled/pwntools-binutils/master/macos/binutils-$ARCH.rb
$ wget https://raw.githubusercontent.com/Gallopsled/pwntools-binutils/master/macos/binutils-$ARCH.rb
$ brew install ./binutils-$ARCH.rb
Windows
^^^^^^^^^^^^^^^^
Windows support is experimental. You can try installing a prebuilt version of binutils
for your desired architecture from the `GNU Toolchains <https://gnutoolchains.com/>`__ project.
Alternate OSes
^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -10,7 +10,7 @@ Ubuntu
.. code-block:: bash
$ apt-get install python-dev
$ sudo apt-get install python-dev
Mac OS X
^^^^^^^^^^^^^^^^
+2
View File
@@ -34,6 +34,8 @@ This exposes a standard interface to talk to processes, sockets, serial ports,
and all manner of things, along with some nifty helpers for common tasks.
For example, remote connections via :mod:`pwnlib.tubes.remote`.
::
>>> conn = remote('ftp.ubuntu.com',21)
>>> conn.recvline() # doctest: +ELLIPSIS
b'220 ...'
+9
View File
@@ -1 +1,10 @@
.. testsetup:: *
from pwn import *
:mod:`pwnlib.protocols.adb` --- Protocol implementations
========================================================
.. automodule:: pwnlib.protocols.adb
:members:
+19
View File
@@ -0,0 +1,19 @@
.. testsetup:: *
from pwn import *
context.clear(arch='riscv64')
:mod:`pwnlib.shellcraft.riscv64` --- Shellcode for RISCV64
==========================================================
:mod:`pwnlib.shellcraft.riscv64`
--------------------------------
.. automodule:: pwnlib.shellcraft.riscv64
:members:
:mod:`pwnlib.shellcraft.riscv64.linux`
--------------------------------------
.. automodule:: pwnlib.shellcraft.riscv64.linux
:members:
+9
View File
@@ -0,0 +1,9 @@
.. testsetup:: *
from pwn import *
:mod:`pwnlib.windbg` --- Working with WinDbg
============================================
.. automodule:: pwnlib.windbg
:members:
+6 -4
View File
@@ -32,18 +32,20 @@ RUN apt-get update \
binutils-aarch64-linux-gnu \
binutils-mips-linux-gnu \
binutils-mipsel-linux-gnu \
binutils-msp430 \
binutils-powerpc-linux-gnu \
binutils-powerpc64-linux-gnu \
binutils-s390x-linux-gnu \
binutils-sparc64-linux-gnu \
binutils-riscv64-linux-gnu \
tmux \
patchelf \
&& locale-gen en_US.UTF-8 \
&& update-locale LANG=en_US.UTF-8 \
&& PYTHONPATH=`echo /usr/share/python-wheels/pip-*.whl` python2.7 -m pip install --upgrade pip setuptools wheel \
&& python2.7 -m pip install --upgrade pwntools \
&& python3 -m pip install --upgrade pip \
&& python3 -m pip install --upgrade pwntools \
&& PYTHONPATH=`echo /usr/share/python-wheels/pip-*.whl` python2.7 -m pip install --no-cache-dir --upgrade pip setuptools wheel \
&& python2.7 -m pip install --no-cache-dir --upgrade pwntools \
&& python3 -m pip install --no-cache-dir --upgrade pip \
&& python3 -m pip install --no-cache-dir --upgrade pwntools \
&& PWNLIB_NOTERM=1 pwn update \
&& useradd -m pwntools \
&& passwd --delete --unlock pwntools \
+2 -2
View File
@@ -1,7 +1,7 @@
FROM pwntools/pwntools:stable
USER root
RUN python2.7 -m pip install --upgrade git+https://github.com/Gallopsled/pwntools@beta \
&& python3 -m pip install --force-reinstall --upgrade git+https://github.com/Gallopsled/pwntools@beta
RUN python2.7 -m pip install --no-cache-dir --upgrade git+https://github.com/Gallopsled/pwntools@beta \
&& python3 -m pip install --no-cache-dir --force-reinstall --upgrade git+https://github.com/Gallopsled/pwntools@beta
RUN PWNLIB_NOTERM=1 pwn update
USER pwntools
+1 -1
View File
@@ -5,4 +5,4 @@ RUN apt-get -y dist-upgrade
RUN apt-get -y install python3 python3-pip
RUN apt-get -y install git wget unzip
RUN pip3 install --upgrade git+https://github.com/Gallopsled/pwntools@dev
RUN pip3 install --no-cache-dir --upgrade git+https://github.com/Gallopsled/pwntools@dev
+2 -2
View File
@@ -1,7 +1,7 @@
FROM pwntools/pwntools:base
USER root
RUN python2.7 -m pip install --upgrade git+https://github.com/Gallopsled/pwntools@stable \
&& python3 -m pip install --force-reinstall --upgrade git+https://github.com/Gallopsled/pwntools@stable
RUN python2.7 -m pip install --no-cache-dir --upgrade git+https://github.com/Gallopsled/pwntools@stable \
&& python3 -m pip install --no-cache-dir --force-reinstall --upgrade git+https://github.com/Gallopsled/pwntools@stable
RUN PWNLIB_NOTERM=1 pwn update
USER pwntools
+9 -1
View File
@@ -89,7 +89,15 @@ try:
except ImportError:
pass
else:
colored_traceback.add_hook()
try:
colored_traceback.add_hook()
except Exception:
# Exception: curses.error
# colored_traceback (curses.setupterm()) fails if TERM is unset.
# This is not critical, so we just ignore it.
# We cannot import `curses` for `curses.error` because it is not
# available on all platforms (e.g. Windows).
pass
# Equivalence with the default behavior of "from import *"
# __all__ = [x for x in tuple(globals()) if not x.startswith('_')]
+1
View File
@@ -36,6 +36,7 @@ __all__ = [
'util',
'update',
'version',
'windbg',
]
from . import args
+1 -1
View File
@@ -142,7 +142,7 @@ class SigreturnABI(SyscallABI):
linux_i386 = ABI('esp', [], 4, 0)
linux_amd64 = ABI('rsp', ['rdi','rsi','rdx','rcx','r8','r9'], 8, 0)
linux_arm = ABI('sp', ['r0', 'r1', 'r2', 'r3'], 8, 0)
linux_aarch64 = ABI('sp', ['x0', 'x1', 'x2', 'x3'], 16, 0)
linux_aarch64 = ABI('sp', ['x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7'], 16, 0)
linux_mips = ABI('$sp', ['$a0','$a1','$a2','$a3'], 4, 0)
linux_ppc = ABI('sp', ['r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'], 4, 0)
linux_ppc64 = ABI('sp', ['r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'], 8, 0)
+26 -6
View File
@@ -123,7 +123,7 @@ def current_device(any=False):
>>> device = adb.current_device(any=True)
>>> device # doctest: +ELLIPSIS
AdbDevice(serial='emulator-5554', type='device', port='emulator', product='sdk_...phone_...', model='...', device='generic...')
AdbDevice(serial='emulator-5554', type='device', port='emulator', product='sdk_...phone..._...', model='...', device='...')
>>> device.port
'emulator'
"""
@@ -259,7 +259,7 @@ class AdbDevice(Device):
>>> device.os
'android'
>>> device.product # doctest: +ELLIPSIS
'sdk_...phone_...'
'sdk_...phone..._...'
>>> device.serial
'emulator-5554'
"""
@@ -880,7 +880,7 @@ def which(name, all = False, *a, **kw):
>>> adb.which('sh')
'/system/bin/sh'
>>> adb.which('sh', all=True)
['/system/bin/sh']
['/system/bin/sh', '/vendor/bin/sh']
>>> adb.which('foobar') is None
True
@@ -988,7 +988,7 @@ def proc_exe(pid):
:skipif: skip_android
>>> adb.proc_exe(1)
b'/init'
b'/system/bin/init'
"""
with context.quiet:
io = process(['realpath','/proc/%d/exe' % pid])
@@ -1275,8 +1275,28 @@ properties = Property()
def _build_date():
"""Returns the build date in the form YYYY-MM-DD as a string"""
import datetime
# Use ro.build.date.utc (integer epoch seconds) which is set by the
# AOSP build system and available on all standard Android devices.
# This avoids ro.build.date which is locale-dependent and can contain
# non-ASCII characters that dateutil cannot parse. See #2513.
utc = getprop('ro.build.date.utc')
if utc and utc.strip().isdigit():
try:
as_datetime = datetime.datetime.fromtimestamp(int(utc.strip()), dateutil.tz.UTC)
return as_datetime.strftime('%Y-%b-%d')
except (OSError, OverflowError, ValueError):
pass
# Fallback for non-standard builds missing ro.build.date.utc.
as_string = getprop('ro.build.date')
as_datetime = dateutil.parser.parse(as_string)
if not as_string:
return ''
try:
as_datetime = dateutil.parser.parse(as_string)
except (ValueError, OverflowError):
return as_string
return as_datetime.strftime('%Y-%b-%d')
def find_ndk_project_root(source):
@@ -1365,7 +1385,7 @@ def compile(source):
>>> filename = adb.compile(temp)
>>> sent = adb.push(filename, "/data/local/tmp")
>>> adb.process(sent).recvall() # doctest: +ELLIPSIS
b'... /system/lib64/libc.so\n...'
b'... /system/lib64/libc++.so\n...'
"""
ndk_build = misc.which('ndk-build')
+6
View File
@@ -159,6 +159,11 @@ def STDERR(v):
"""Sends logging to ``stderr`` by default, instead of ``stdout``"""
context.log_console = sys.stderr
def LOCAL_LIBCDB(v):
"""Sets path to local libc-database via ``context.local_libcdb``, e.g.
``LOCAL_LIBCDB='/path/to/libc-databse'``"""
context.local_libcdb = v
hooks = {
'LOG_LEVEL': LOG_LEVEL,
'LOG_FILE': LOG_FILE,
@@ -170,6 +175,7 @@ hooks = {
'NOASLR': NOASLR,
'NOPTRACE': NOPTRACE,
'STDERR': STDERR,
'LOCAL_LIBCDB': LOCAL_LIBCDB,
}
def initialize():
+92 -16
View File
@@ -59,6 +59,9 @@ from pwnlib import shellcraft
from pwnlib.context import LocalContext
from pwnlib.context import context
from pwnlib.log import getLogger
from pwnlib.util.hashes import sha1sumhex
from pwnlib.util.packing import _encode
from pwnlib.version import __version__
log = getLogger(__name__)
@@ -167,6 +170,8 @@ def which_binutils(util, check_version=False):
'.../bin/arm-...-as'
>>> which_binutils('as', arch='powerpc') #doctest: +ELLIPSIS
'.../bin/powerpc...-as'
>>> which_binutils('as', arch='mips', endianness='little') #doctest: +ELLIPSIS
'.../bin/mipsel...-as'
>>> which_binutils('as', arch='msp430') #doctest: +SKIP
...
Traceback (most recent call last):
@@ -175,28 +180,44 @@ def which_binutils(util, check_version=False):
"""
arch = context.arch
# Handle endianness-specific naming for mips/mips64
arch = {
('mips', 'little'): 'mipsel',
('mips64', 'little'): 'mips64el',
}.get((arch, context.endianness), arch)
# Fix up pwntools vs Debian triplet naming, and account
# for 'thumb' being its own pwntools architecture.
arches = [arch] + {
aliases = {
'thumb': ['arm', 'aarch64'],
'i386': ['x86_64', 'amd64'],
'i686': ['x86_64', 'amd64'],
'amd64': ['x86_64', 'i386'],
'mips64': ['mips'],
'powerpc64': ['powerpc'],
'sparc64': ['sparc'],
'riscv32': ['riscv32', 'riscv64', 'riscv'],
'riscv64': ['riscv64', 'riscv32', 'riscv'],
'amd64': ['x86_64'],
}.get(arch, [])
# Some binutils can support multiple architectures. Try them as fallbacks.
fallback_arches = {
'i386': ['x86_64', 'amd64'],
'amd64': ['i386'],
'arm': ['aarch64'],
'mips': ['mipsel'],
'mipsel': ['mips'],
'mips64': ['mips64el', 'mips', 'mipsel'],
'mips64el': ['mips64', 'mipsel', 'mips'],
'powerpc64': ['powerpc'],
'sparc64': ['sparc'],
'riscv32': ['riscv64', 'riscv'],
'riscv64': ['riscv32', 'riscv'],
}.get(arch, [])
arches = [arch] + aliases + fallback_arches
# If one of the candidate architectures matches the native
# architecture, use that as a last resort.
# architecture, use that as a last resort before trying fallbacks.
machine = platform.machine()
machine = 'i386' if machine == 'i686' else machine
try:
with context.local(arch = machine):
if context.arch in arches:
arches.append(None)
arches = [arch] + aliases + [None] + fallback_arches
except AttributeError:
log.warn_once("Your local binutils won't be used because architecture %r is not supported." % machine)
@@ -206,6 +227,11 @@ def which_binutils(util, check_version=False):
if platform.system() == 'Darwin':
utils = ['g'+util, util]
if platform.system() == 'Windows':
utils = [util + '.exe']
# Try the explicit tools for the target architecture first,
# then the native one optionally, then fallbacks.
for arch in arches:
for gutil in utils:
# e.g. objdump
@@ -220,7 +246,7 @@ def which_binutils(util, check_version=False):
'%s-%s' % (arch, gutil)]
for pattern in patterns:
for dir in environ['PATH'].split(':'):
for dir in environ['PATH'].split(os.pathsep):
for res in sorted(glob(path.join(dir, pattern))):
if check_version:
ver = check_binutils_version(res)
@@ -457,15 +483,20 @@ def cpp(shellcode):
>>> cpp("SYS_setresuid", os = "freebsd")
'311\n'
"""
if platform.system() == 'Windows':
cpp = which_binutils('cpp')
else:
cpp = 'cpp'
code = _include_header() + shellcode
cmd = [
'cpp',
cpp,
'-Wno-unused-command-line-argument',
'-C',
'-nostdinc',
'-undef',
'-P',
'-I' + _incdir,
'/dev/stdin'
]
return _run(cmd, code).strip('\n').rstrip() + '\n'
@@ -751,8 +782,23 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
b'0@*\x00'
>>> asm("la %r0, 42", arch = 's390', bits=64)
b'A\x00\x00*'
The output is cached:
>>> start = time.time()
>>> asm("lea rax, [rip+0]", arch = 'amd64', cache_dir = None) # force uncached time
b'H\x8d\x05\x00\x00\x00\x00'
>>> uncached_time = time.time() - start
>>> asm("lea rax, [rip+0]", arch = 'amd64') # cache it
b'H\x8d\x05\x00\x00\x00\x00'
>>> start = time.time()
>>> asm("lea rax, [rip+0]", arch = 'amd64')
b'H\x8d\x05\x00\x00\x00\x00'
>>> cached_time = time.time() - start
>>> uncached_time > cached_time
True
"""
result = ''
result = b''
assembler = _assembler()
linker = _linker()
@@ -763,6 +809,30 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
log.debug('Assembling\n%s' % code)
cache_file = None
if context.cache_dir:
cache_dir = os.path.join(context.cache_dir, 'asm-cache')
if not os.path.isdir(cache_dir):
os.makedirs(cache_dir)
# Include the context in the hash in addition to the shellcode
hash_params = '{}_{}_{}_{}'.format(vma, extract, shared, __version__)
fingerprint_params = _encode(code) + _encode(hash_params) + _encode(' '.join(assembler)) + _encode(' '.join(linker)) + _encode(' '.join(objcopy))
asm_hash = sha1sumhex(fingerprint_params)
cache_file = os.path.join(cache_dir, asm_hash)
if os.path.exists(cache_file):
log.debug('Using cached assembly output from %r', cache_file)
if extract:
with open(cache_file, 'rb') as f:
return f.read()
# Create a temporary copy of the cached file to avoid modification.
tmpdir = tempfile.mkdtemp(prefix = 'pwn-asm-')
atexit.register(shutil.rmtree, tmpdir)
step3 = os.path.join(tmpdir, 'step3')
shutil.copy(cache_file, step3)
return step3
tmpdir = tempfile.mkdtemp(prefix = 'pwn-asm-')
step1 = path.join(tmpdir, 'step1')
step2 = path.join(tmpdir, 'step2')
@@ -810,6 +880,8 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
shutil.copy(step2, step3)
if not extract:
if cache_file is not None:
shutil.copy(step3, cache_file)
return step3
_run(objcopy + [step3, step4])
@@ -823,6 +895,10 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
else:
atexit.register(lambda: shutil.rmtree(tmpdir))
if cache_file is not None and result != b'':
with open(cache_file, 'wb') as f:
f.write(result)
return result
@LocalContext
@@ -855,8 +931,8 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
0: b8 17 00 00 00 mov eax, 0x17
>>> print(disasm(unhex('48c7c017000000'), arch = 'amd64'))
0: 48 c7 c0 17 00 00 00 mov rax, 0x17
>>> print(disasm(unhex('04001fe552009000'), arch = 'arm'))
0: e51f0004 ldr r0, [pc, #-4] ; 0x4
>>> print(disasm(unhex('04001fe552009000'), arch = 'arm')) # doctest: +ELLIPSIS
0: e51f0004 ldr r0, [pc, #-4] ...
4: 00900052 addseq r0, r0, r2, asr r0
>>> print(disasm(unhex('4ff00500'), arch = 'thumb', bits=32))
0: f04f 0005 mov.w r0, #5
+1 -1
View File
@@ -137,4 +137,4 @@ def main(args):
args.output.write(b'\n')
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+7 -6
View File
@@ -4,7 +4,7 @@ from __future__ import division
import argparse
import sys
from pwnlib.elf import ELF
from pwn import *
from pwnlib.commandline import common
parser = common.parser_commands.add_parser(
@@ -15,7 +15,6 @@ parser = common.parser_commands.add_parser(
parser.add_argument(
'elf',
nargs='*',
type=argparse.FileType('rb'),
help='Files to check'
)
parser.add_argument(
@@ -23,19 +22,21 @@ parser.add_argument(
nargs='*',
dest='elf2',
metavar='elf',
type=argparse.FileType('rb'),
help='File to check (for compatibility with checksec.sh)'
)
def main(args):
files = args.elf or args.elf2 or []
files = args.elf or args.elf2 or []
if not files:
parser.print_usage()
return
for f in files:
e = ELF(f.name)
try:
e = ELF(f)
except Exception as e:
print("{name}: {error}".format(name=f, error=e))
if __name__ == '__main__':
common.main(__file__)
common.main(__file__, main)
+20 -3
View File
@@ -25,8 +25,25 @@ parser = argparse.ArgumentParser(description='Pwntools Command-line Interface',
prog='pwn')
parser_commands = parser.add_subparsers(dest='command')
def main(file=sys.argv[0]):
import pwnlib.commandline.main
def main(file=sys.argv[0], command_main=None):
name = os.path.splitext(os.path.basename(file))[0]
if command_main is None:
import importlib
command_main = importlib.import_module('pwnlib.commandline.%s' % name).main
sys.argv.insert(1, name)
pwnlib.commandline.main.main()
entrypoint({name: command_main})
def deprecated_main():
file=sys.argv[0]
name = os.path.splitext(os.path.basename(file))[0]
import warnings
warnings.warn("The '%s' command is deprecated and will be removed in a future version. Please use 'pwn %s' instead." % (name, name), DeprecationWarning, stacklevel=2)
main(file)
def entrypoint(commands):
if len(sys.argv) < 2:
parser.print_usage()
sys.exit()
args = parser.parse_args()
with context.local(log_console = sys.stderr):
commands[args.command](args)
+1 -1
View File
@@ -133,4 +133,4 @@ def main(args):
print('(%s) == %s' % (' | '.join(k for v, k in good), args.constant))
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -107,4 +107,4 @@ def main(args):
out.write(b'\n')
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -102,4 +102,4 @@ def main(args):
gdb.debug(target, gdbscript=gdbscript, sysroot=args.sysroot).interactive()
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -24,4 +24,4 @@ def main(args):
ELF(e.path)
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -110,4 +110,4 @@ def main(args):
print(disasm(dat, vma=safeeval.const(args.address)))
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -59,4 +59,4 @@ def main(a):
print(diff(x, y))
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -34,4 +34,4 @@ def main(a):
getattr(sys.stdout, 'buffer', sys.stdout).write(elf.get_data())
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -46,4 +46,4 @@ def main(args):
print(os.strerror(value))
if __name__ == '__main__':
common.main(__file__)
common.main(__file__, main)
+1 -1
View File
@@ -50,4 +50,4 @@ def main(args):
print(encoded)
if __name__ == '__main__':
common.main(__file__)
common.main(__file__, main)
+111 -68
View File
@@ -37,19 +37,12 @@ lookup_parser.add_argument(
)
lookup_parser.add_argument(
'--download-libc',
'-d', '--download-libc',
action = 'store_true',
default = False,
help = 'Attempt to download the matching libc.so'
)
lookup_parser.add_argument(
'--unstrip',
action = 'store_true',
default = True,
help = 'Attempt to unstrip the libc binary with debug symbols from a debuginfod server'
)
lookup_parser.add_argument(
'--no-unstrip',
action = 'store_false',
@@ -57,6 +50,14 @@ lookup_parser.add_argument(
help = 'Do NOT attempt to unstrip the libc binary with debug symbols from a debuginfod server'
)
lookup_parser.add_argument(
'--offline-only',
action = 'store_true',
default = False,
dest = 'offline_only',
help = 'Attempt to searching with offline only mode'
)
hash_parser = libc_commands.add_parser(
'hash',
help = 'Display information of a libc version given an unique hash',
@@ -80,19 +81,12 @@ hash_parser.add_argument(
)
hash_parser.add_argument(
'--download-libc',
'-d', '--download-libc',
action = 'store_true',
default = False,
help = 'Attempt to download the matching libc.so'
)
hash_parser.add_argument(
'--unstrip',
action = 'store_true',
default = True,
help = 'Attempt to unstrip the libc binary with debug symbols from a debuginfod server'
)
hash_parser.add_argument(
'--no-unstrip',
action = 'store_false',
@@ -100,6 +94,14 @@ hash_parser.add_argument(
help = 'Do NOT attempt to unstrip the libc binary with debug symbols from a debuginfod server'
)
hash_parser.add_argument(
'--offline-only',
action = 'store_true',
default = False,
dest = 'offline_only',
help = 'Attempt to searching with offline only mode'
)
file_parser = libc_commands.add_parser(
'file',
help = 'Dump information about a libc binary',
@@ -130,25 +132,34 @@ file_parser.add_argument(
file_parser.add_argument(
'--unstrip',
action = 'store_true',
default = False,
dest = 'unstrip',
help = 'Attempt to unstrip the libc binary inplace with debug symbols from a debuginfod server'
)
fetch_parser = libc_commands.add_parser(
'fetch',
help = 'Fetch libc database',
description = 'Fetch libc database. If no argument passed, it will init and upgrade libc-database repository',
)
fetch_parser.add_argument(
'path',
nargs = '?',
default = context.local_libcdb,
help = 'Set libc-database path, If it is empty, the default path will be `context.local_libcdb` (%s)' % context.local_libcdb
)
fetch_parser.add_argument(
'-u', '--update',
metavar = 'update',
nargs = '+',
choices = ['all', 'ubuntu', 'debian', 'rpm', 'centos', 'arch', 'alpine', 'kali', 'parrotsec', 'launchpad'],
help = 'Fetch the desired libc categories'
)
common_symbols = ['dup2', 'printf', 'puts', 'read', 'system', 'write']
def find_libc(params):
import requests
url = "https://libc.rip/api/find"
result = requests.post(url, json=params, timeout=20)
log.debug('Request: %s', params)
log.debug('Result: %s', result.json())
if result.status_code != 200 or len(result.json()) == 0:
log.failure("Could not find libc for %s on libc.rip", params)
return []
return result.json()
def print_libc(libc):
def print_libc_info(libc):
log.info('%s', text.red(libc['id']))
log.indented('\t%-20s %s', text.green('BuildID:'), libc['buildid'])
log.indented('\t%-20s %s', text.green('MD5:'), libc['md5'])
@@ -158,14 +169,39 @@ def print_libc(libc):
for symbol in libc['symbols'].items():
log.indented('\t%25s = %s', symbol[0], symbol[1])
def handle_remote_libc(args, libc):
print_libc(libc)
if args.download_libc:
path = libcdb.search_by_build_id(libc['buildid'], args.unstrip)
if path:
if args.unstrip:
libcdb.unstrip_libc(path)
shutil.copy(path, './{}.so'.format(libc['id']))
def print_libc_elf(exe):
from hashlib import md5, sha1, sha256
log.info('%s', text.red(os.path.basename(exe.path)))
libc_version = get_libc_version(exe)
if libc_version:
log.indented('%-20s %s', text.green('Version:'), libc_version)
if exe.buildid:
log.indented('%-20s %s', text.green('BuildID:'), enhex(exe.buildid))
log.indented('%-20s %s', text.green('MD5:'), md5(exe.data).hexdigest())
log.indented('%-20s %s', text.green('SHA1:'), sha1(exe.data).hexdigest())
log.indented('%-20s %s', text.green('SHA256:'), sha256(exe.data).hexdigest())
# Always dump the basic list of common symbols
log.indented('%s', text.green('Symbols:'))
synthetic_symbols = collect_synthetic_symbols(exe)
symbols = common_symbols + (args.symbols or []) + synthetic_symbols
symbols.sort()
for symbol in symbols:
if symbol not in exe.symbols:
log.indented('%25s = %s', symbol, text.red('not found'))
else:
log.indented('%25s = %#x', symbol, translate_offset(exe.symbols[symbol], args, exe))
def get_libc_version(exe):
res = re.search(br'libc[ -](\d+\.\d+)', exe.data)
if res:
return res.group(1).decode()
return None
def translate_offset(offs, args, exe):
if args.offset:
@@ -182,7 +218,7 @@ def collect_synthetic_symbols(exe):
available_symbols.append('str_bin_sh')
except StopIteration:
pass
libc_start_main_return = exe.libc_start_main_return
if libc_start_main_return > 0:
exe.symbols['__libc_start_main_ret'] = libc_start_main_return
@@ -200,52 +236,59 @@ def main(args):
if len(pairs) % 2 != 0:
log.failure('Uneven number of arguments. Please provide "symbol offset" pairs')
return
symbols = {pairs[i]:pairs[i+1] for i in range(0, len(pairs), 2)}
matched_libcs = find_libc({'symbols': symbols})
matched_libcs = libcdb.search_by_symbol_offsets(symbols, offline_only=args.offline_only, return_raw=True)
if not matched_libcs:
return
for libc in matched_libcs:
handle_remote_libc(args, libc)
print_libc_info(libc)
if args.download_libc:
path = libcdb.search_by_build_id(libc['buildid'], args.unstrip)
if path:
shutil.copy(path, './{}.so'.format(libc['id']))
elif args.libc_command == 'hash':
inverted_map = {v: k for k, v in libcdb.MAP_TYPES.items()}
hash_type = inverted_map.get(args.hash_type, args.hash_type)
for hash_value in args.hash_value:
matched_libcs = find_libc({args.hash_type: hash_value})
for libc in matched_libcs:
handle_remote_libc(args, libc)
path = libcdb.search_by_hash(hash_value, hash_type, unstrip=args.unstrip, offline_only=args.offline_only)
exe = ELF(path, checksec=False)
print_libc_elf(exe)
if args.download_libc:
# if we cannot get actual libc version then copy with cache name
shutil.copy(path, './libc-{}.so'.format(get_libc_version(exe) or Path(path).stem))
elif args.libc_command == 'file':
from hashlib import md5, sha1, sha256
for file in args.files:
if not os.path.exists(file) or not os.path.isfile(file):
log.failure('File does not exist %s', args.file)
continue
if args.unstrip:
libcdb.unstrip_libc(file)
exe = ELF(file, checksec=False)
log.info('%s', text.red(os.path.basename(file)))
print_libc_elf(ELF(file, checksec=False))
libc_version = re.search(br'libc[ -](\d+\.\d+)', exe.data)
if libc_version:
log.indented('%-20s %s', text.green('Version:'), libc_version.group(1).decode())
elif args.libc_command == 'fetch':
if exe.buildid:
log.indented('%-20s %s', text.green('BuildID:'), enhex(exe.buildid))
log.indented('%-20s %s', text.green('MD5:'), md5(exe.data).hexdigest())
log.indented('%-20s %s', text.green('SHA1:'), sha1(exe.data).hexdigest())
log.indented('%-20s %s', text.green('SHA256:'), sha256(exe.data).hexdigest())
if args.update:
subprocess.check_call(['./get'] + args.update, cwd=args.path)
# Always dump the basic list of common symbols
log.indented('%s', text.green('Symbols:'))
synthetic_symbols = collect_synthetic_symbols(exe)
else:
if not Path(args.path).exists():
if yesno("Would you like to initialize the libc-database repository? "
"If the path already exists, this prompt will not display, and automatically upgrade repository."):
log.waitfor("init libc-database repository")
subprocess.check_call(['git', 'clone', 'https://github.com/niklasb/libc-database/', args.path])
else:
log.waitfor("upgrade libc-database repository")
subprocess.check_call(['git', 'pull'], cwd=args.path)
symbols = common_symbols + (args.symbols or []) + synthetic_symbols
symbols.sort()
for symbol in symbols:
if symbol not in exe.symbols:
log.indented('%25s = %s', symbol, text.red('not found'))
else:
log.indented('%25s = %#x', symbol, translate_offset(exe.symbols[symbol], args, exe))
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+2 -10
View File
@@ -1,7 +1,5 @@
from __future__ import absolute_import
import sys
from pwnlib.commandline import asm
from pwnlib.commandline import checksec
from pwnlib.commandline import common
@@ -23,8 +21,7 @@ from pwnlib.commandline import template
from pwnlib.commandline import unhex
from pwnlib.commandline import update
from pwnlib.commandline import version
from pwnlib.commandline.common import parser
from pwnlib.context import context
from pwnlib.commandline.common import parser as parser
commands = {
'asm': asm.main,
@@ -50,12 +47,7 @@ commands = {
}
def main():
if len(sys.argv) < 2:
parser.print_usage()
sys.exit()
args = parser.parse_args()
with context.local(log_console = sys.stderr):
commands[args.command](args)
common.entrypoint(commands)
if __name__ == '__main__':
main()
+1 -1
View File
@@ -109,4 +109,4 @@ def main(args):
pass
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -53,4 +53,4 @@ def main(args):
args.output.write(result)
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -110,4 +110,4 @@ def main(args):
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+112 -80
View File
@@ -71,17 +71,9 @@ p.add_argument(
p.add_argument(
'shellcode',
nargs = '?',
help = 'The shellcode you want',
type = str
)
p.add_argument(
'args',
nargs = '*',
metavar = 'arg',
default = (),
help = 'Argument to the chosen shellcode',
help = 'The shellcodes you want. shellcode [args ...] [+ shellcode [args ...]]',
type = str
)
p.add_argument(
@@ -91,6 +83,12 @@ p.add_argument(
action='store_true'
)
p.add_argument(
'--delim',
help='Set the delimiter between multilple shellcodes',
default='+'
)
p.add_argument(
'-b',
'--before',
@@ -172,24 +170,50 @@ p.add_argument(
help='Generated ELF is a shared library'
)
def get_template(name):
func = shellcraft
for attr in name.split('.'):
func = getattr(func, attr)
return func
def get_template(shellcodes):
funcs = []
for shellcode in shellcodes:
func = shellcraft
cur_name = shellcode[0]
args = []
if len(shellcode) > 1:
args = shellcode[1:]
for attr in cur_name.split('.'):
func = getattr(func, attr)
funcs.append((cur_name, func, args))
return funcs
def is_not_a_syscall_template(name):
template_src = shellcraft._get_source(name)
return '/syscalls' not in template_src
def main(args):
delim = '+'
if args.delim:
delim = args.delim.strip()
shellcodes = []
if args.shellcode:
current = []
for s in args.shellcode:
if s.strip() == delim:
shellcodes.append(current)
current = []
else:
current.append(s)
if len(current) > 0:
shellcodes.append(current)
if args.list:
templates = shellcraft.templates
if args.shellcode:
templates = filter(lambda a: args.shellcode in a, templates)
template_array = []
for s in shellcodes:
template_array.extend(list(filter(lambda a: s[0] in a, templates)))
templates = template_array
elif not args.syscalls:
templates = filter(is_not_a_syscall_template, templates)
templates = list(filter(is_not_a_syscall_template, templates))
print('\n'.join(templates))
exit()
@@ -199,84 +223,92 @@ def main(args):
exit()
try:
func = get_template(args.shellcode)
funcs = get_template(shellcodes)
except AttributeError:
log.error("Unknown shellcraft template %r. Use --list to see available shellcodes." % args.shellcode)
if args.show:
# remove doctests
doc = []
in_doctest = False
block_indent = None
caption = None
lines = func.__doc__.splitlines()
i = 0
while i < len(lines):
line = lines[i]
if line.lstrip().startswith('>>>'):
# this line starts a doctest
in_doctest = True
block_indent = None
if caption:
# delete back up to the caption
doc = doc[:caption - i]
caption = None
elif line == '':
# skip blank lines
pass
elif in_doctest:
# indentation marks the end of a doctest
indent = len(line) - len(line.lstrip())
if block_indent is None:
if not line.lstrip().startswith('...'):
block_indent = indent
elif indent < block_indent:
in_doctest = False
for (name, func, _args) in funcs:
# remove doctests
doc = []
in_doctest = False
block_indent = None
caption = None
lines = func.__doc__.splitlines()
i = 0
if len(funcs) > 1:
print('%s:' % name)
while i < len(lines):
line = lines[i]
if line.lstrip().startswith('>>>'):
# this line starts a doctest
in_doctest = True
block_indent = None
# re-evalutate this line
continue
elif line.endswith(':'):
# save index of caption
caption = i
else:
# this is not blank space and we're not in a doctest, so the
# previous caption (if any) was not for a doctest
caption = None
if caption:
# delete back up to the caption
doc = doc[:caption - i]
caption = None
elif line == '':
# skip blank lines
pass
elif in_doctest:
# indentation marks the end of a doctest
indent = len(line) - len(line.lstrip())
if block_indent is None:
if not line.lstrip().startswith('...'):
block_indent = indent
elif indent < block_indent:
in_doctest = False
block_indent = None
# re-evalutate this line
continue
elif line.endswith(':'):
# save index of caption
caption = i
else:
# this is not blank space and we're not in a doctest, so the
# previous caption (if any) was not for a doctest
caption = None
if not in_doctest:
doc.append(line)
i += 1
print('\n'.join(doc).rstrip())
if not in_doctest:
doc.append(line)
i += 1
print('\n'.join(doc).rstrip())
if len(funcs) > 1:
print('')
exit()
defargs = len(six.get_function_defaults(func) or ())
reqargs = six.get_function_code(func).co_argcount - defargs
if len(args.args) < reqargs:
if defargs > 0:
log.critical('%s takes at least %d arguments' % (args.shellcode, reqargs))
sys.exit(1)
else:
log.critical('%s takes exactly %d arguments' % (args.shellcode, reqargs))
sys.exit(1)
code_array = []
for (name, func, func_args) in funcs:
defargs = len(six.get_function_defaults(func) or ())
reqargs = six.get_function_code(func).co_argcount - defargs
# Captain uglyness saves the day!
for i, val in enumerate(args.args):
try:
args.args[i] = util.safeeval.expr(val)
except ValueError:
pass
if len(func_args) < reqargs:
if defargs > 0:
log.critical('%s takes at least %d arguments' % (name, reqargs))
sys.exit(1)
else:
log.critical('%s takes exactly %d arguments' % (name, reqargs))
sys.exit(1)
# And he strikes again!
list(map(common.context_arg, args.shellcode.split('.')))
code = func(*args.args)
# Captain uglyness saves the day!
for i, val in enumerate(func_args):
try:
func_args[i] = util.safeeval.expr(val)
except ValueError:
pass
# And he strikes again!
list(map(common.context_arg, name.split('.')))
code_array.append(func(*func_args))
code = "".join(code_array)
if args.before:
code = shellcraft.trap() + code
if args.after:
code = code + shellcraft.trap()
if args.format in ['a', 'asm', 'assembly']:
if args.color:
from pygments import highlight
@@ -319,7 +351,7 @@ def main(args):
else:
args.format = 'raw'
arch = args.shellcode.split('.')[0]
arch = name.split('.')[0]
if args.debug:
if not args.avoid:
@@ -352,4 +384,4 @@ def main(args):
args.out.write(code)
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+115 -2
View File
@@ -1,9 +1,12 @@
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from pwn import *
from pwnlib.commandline import common
from pwnlib.util.misc import which, parse_ldd_output, write
from sys import stderr
from mako.lookup import TemplateLookup, Template
parser = common.parser_commands.add_parser(
@@ -32,18 +35,113 @@ parser.add_argument('--template', help='Path to a custom template. Tries to use
os.path.join(printable_data_path, "templates", "pwnup.mako"))
parser.add_argument('--no-auto', help='Do not automatically detect missing binaries', action='store_false', dest='auto')
def get_docker_image_libraries():
"""Tries to retrieve challenge libraries from a Docker image built from the Dockerfile in the current working directory.
The libraries are retrieved by parsing the output of running ldd on /bin/sh.
Supports regular Docker images as well as jail images.
"""
with log.progress("Extracting challenge libraries from Docker image") as progress:
if not which("docker"):
progress.failure("docker command not found")
return None, None
# maps jail image name to the root directory of the child image
jail_image_to_chroot_dir = {
"pwn.red/jail": "/srv",
}
dockerfile = open("Dockerfile", "r").read()
jail = None
chroot_dir = "/"
for jail_image in jail_image_to_chroot_dir:
if re.search(r"^FROM %s" % jail_image, dockerfile, re.MULTILINE):
jail = jail_image
chroot_dir = jail_image_to_chroot_dir[jail_image]
break
try:
progress.status("Building image")
image_sha = subprocess.check_output(["docker", "build", "-q", "."], stderr=subprocess.PIPE, shell=False).decode().strip()
progress.status("Retrieving library paths")
ldd_command = ["-c", "chroot %s /bin/sh -c 'ldd /bin/sh'" % chroot_dir]
ldd_output = subprocess.check_output([
"docker",
"run",
"--rm",
"--entrypoint",
"/bin/sh",
] + (["--privileged"] if jail else []) + [
image_sha,
] + ldd_command,
stderr=subprocess.PIPE,
shell=False
).decode()
libc, ld = None, None
libc_basename, ld_basename = None, None
for lib_path in parse_ldd_output(ldd_output):
if "libc." in lib_path:
libc = lib_path
libc_basename = os.path.basename(lib_path)
if "ld-" in lib_path:
ld = lib_path
ld_basename = os.path.basename(lib_path)
if not (libc and ld):
progress.failure("Could not find libraries")
return None, None
progress.status("Copying libraries to current directory")
for filename, basename in zip((libc, ld), (libc_basename, ld_basename)):
cat_command = ["-c", "chroot %s /bin/sh -c '/bin/cat %s'" % (chroot_dir, filename)]
contents = subprocess.check_output([
"docker",
"run",
"--rm",
"--entrypoint",
"/bin/sh",
] + (["--privileged"] if jail else []) + [
image_sha
] + cat_command,
stderr=subprocess.PIPE,
shell=False
)
write(basename, contents)
except subprocess.CalledProcessError as e:
print(e.stderr.decode(), file=sys.stderr)
progress.failure("docker failed with status: %d" % e.returncode)
return None, None
progress.success("Retrieved libraries from Docker image")
return libc_basename, ld_basename
def detect_missing_binaries(args):
"""Automatically detects challenge binaries and libraries in the current directory.
This function scans the current directory for executable files, libc, and ld libraries.
If a Dockerfile is present and no libraries are found, it attempts to extract them from
the Docker image, but only if the binary is not statically linked.
Args:
args: Argument namespace containing exe and libc attributes.
Returns:
tuple: A pair of (executable_path, libc_path) where either may be None if not found.
"""
log.info("Automatically detecting challenge binaries...")
# look for challenge binary, libc, and ld in current directory
exe, libc, ld = args.exe, args.libc, None
has_dockerfile = False
other_files = []
for filename in os.listdir():
for filename in os.listdir("."):
if not os.path.isfile(filename):
continue
if not libc and ('libc-' in filename or 'libc.' in filename):
libc = filename
elif not ld and 'ld-' in filename:
ld = filename
elif filename == "Dockerfile":
has_dockerfile = True
else:
if os.access(filename, os.X_OK):
other_files.append(filename)
@@ -52,6 +150,21 @@ def detect_missing_binaries(args):
exe = other_files[0]
elif len(other_files) > 1:
log.warning("Failed to find challenge binary. There are multiple binaries in the current directory: %s", other_files)
# Check if the binary is statically linked before trying to extract libraries from Docker
is_statically_linked = False
if exe:
try:
binary = ELF(exe, checksec=False)
is_statically_linked = binary.statically_linked
if is_statically_linked:
log.info("Binary is statically linked, no need for external libraries")
except Exception as e:
log.warning("Could not check if binary is statically linked: %s", e)
# Only extract libraries from Docker if the binary is not statically linked
if has_dockerfile and exe and not (libc or ld) and not is_statically_linked:
libc, ld = get_docker_image_libraries()
if exe != args.exe:
log.success("Found challenge binary %r", exe)
@@ -122,5 +235,5 @@ def main(args):
except OSError: pass
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -30,4 +30,4 @@ def main(args):
raise
if __name__ == '__main__':
common.main(__file__)
common.main(__file__, main)
+1 -1
View File
@@ -30,4 +30,4 @@ def main(a):
subprocess.check_call(result, shell=False)
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+1 -1
View File
@@ -29,4 +29,4 @@ def main(a):
log.info("Pwntools v%s" % version)
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
pwnlib.commandline.common.main(__file__, main)
+163 -19
View File
@@ -88,6 +88,7 @@ VOL_CAP_FMT_NO_PERMISSIONS = Constant('VOL_CAP_FMT_NO_PERMISSIONS',0x00400000)
VOL_CAP_FMT_SHARED_SPACE = Constant('VOL_CAP_FMT_SHARED_SPACE',0x00800000)
VOL_CAP_FMT_VOL_GROUPS = Constant('VOL_CAP_FMT_VOL_GROUPS',0x01000000)
VOL_CAP_FMT_SEALED = Constant('VOL_CAP_FMT_SEALED',0x02000000)
VOL_CAP_FMT_CLONE_MAPPING = Constant('VOL_CAP_FMT_CLONE_MAPPING',0x04000000)
VOL_CAP_INT_SEARCHFS = Constant('VOL_CAP_INT_SEARCHFS',0x00000001)
VOL_CAP_INT_ATTRLIST = Constant('VOL_CAP_INT_ATTRLIST',0x00000002)
VOL_CAP_INT_NFSEXPORT = Constant('VOL_CAP_INT_NFSEXPORT',0x00000004)
@@ -109,6 +110,8 @@ VOL_CAP_INT_RENAME_SWAP = Constant('VOL_CAP_INT_RENAME_SWAP',0x00040000)
VOL_CAP_INT_RENAME_EXCL = Constant('VOL_CAP_INT_RENAME_EXCL',0x00080000)
VOL_CAP_INT_RENAME_OPENFAIL = Constant('VOL_CAP_INT_RENAME_OPENFAIL',0x00100000)
VOL_CAP_INT_RENAME_SECLUDE = Constant('VOL_CAP_INT_RENAME_SECLUDE',0x00200000)
VOL_CAP_INT_ATTRIBUTION_TAG = Constant('VOL_CAP_INT_ATTRIBUTION_TAG',0x00400000)
VOL_CAP_INT_PUNCHHOLE = Constant('VOL_CAP_INT_PUNCHHOLE',0x00800000)
ATTR_CMN_NAME = Constant('ATTR_CMN_NAME',0x00000001)
ATTR_CMN_DEVID = Constant('ATTR_CMN_DEVID',0x00000002)
ATTR_CMN_FSID = Constant('ATTR_CMN_FSID',0x00000004)
@@ -293,6 +296,8 @@ IO_SYSCALL_DISPATCH = Constant('IO_SYSCALL_DISPATCH',0x100000)
IO_SWAP_DISPATCH = Constant('IO_SWAP_DISPATCH',0x200000)
IO_SKIP_ENCRYPTION = Constant('IO_SKIP_ENCRYPTION',0x400000)
IO_EVTONLY = Constant('IO_EVTONLY',0x800000)
IO_NOCACHE_SYSSPACE = Constant('IO_NOCACHE_SYSSPACE',0x1000000)
IO_NOCACHE_SWRITE = Constant('IO_NOCACHE_SWRITE',0x2000000)
LOOKUP = Constant('LOOKUP',0)
CREATE = Constant('CREATE',1)
DELETE = Constant('DELETE',2)
@@ -347,6 +352,7 @@ VNODE_UPDATE_PURGE = Constant('VNODE_UPDATE_PURGE',0x08)
VNODE_LOOKUP_NOFOLLOW = Constant('VNODE_LOOKUP_NOFOLLOW',0x01)
VNODE_LOOKUP_NOCROSSMOUNT = Constant('VNODE_LOOKUP_NOCROSSMOUNT',0x02)
VNODE_LOOKUP_CROSSMOUNTNOWAIT = Constant('VNODE_LOOKUP_CROSSMOUNTNOWAIT',0x04)
VNODE_LOOKUP_NOFOLLOW_ANY = Constant('VNODE_LOOKUP_NOFOLLOW_ANY',0x08)
VNODE_RELOAD = Constant('VNODE_RELOAD',0x01)
VNODE_WAIT = Constant('VNODE_WAIT',0x02)
VNODE_WRITEABLE = Constant('VNODE_WRITEABLE',0x04)
@@ -425,7 +431,7 @@ LOCKPARENT = Constant('LOCKPARENT',0x0008)
WANTPARENT = Constant('WANTPARENT',0x0010)
UIO_MAXIOV = Constant('UIO_MAXIOV',1024)
UIO_SMALLIOV = Constant('UIO_SMALLIOV',8)
EVFILT_SYSCOUNT = Constant('EVFILT_SYSCOUNT',17)
EVFILT_SYSCOUNT = Constant('EVFILT_SYSCOUNT',18)
KEVENT_FLAG_NONE = Constant('KEVENT_FLAG_NONE',0x000000)
KEVENT_FLAG_IMMEDIATE = Constant('KEVENT_FLAG_IMMEDIATE',0x000001)
KEVENT_FLAG_ERROR_EVENTS = Constant('KEVENT_FLAG_ERROR_EVENTS',0x000002)
@@ -503,6 +509,7 @@ IMGPF_IS_64BIT_ADDR = Constant('IMGPF_IS_64BIT_ADDR',0x00000008)
IMGPF_SPAWN = Constant('IMGPF_SPAWN',0x00000010)
IMGPF_DISABLE_ASLR = Constant('IMGPF_DISABLE_ASLR',0x00000020)
IMGPF_ALLOW_DATA_EXEC = Constant('IMGPF_ALLOW_DATA_EXEC',0x00000040)
IMGPF_3P_PLUGINS = Constant('IMGPF_3P_PLUGINS',0x00000080)
IMGPF_EXEC = Constant('IMGPF_EXEC',0x00000100)
IMGPF_HIGH_BITS_ASLR = Constant('IMGPF_HIGH_BITS_ASLR',0x00000200)
IMGPF_IS_64BIT_DATA = Constant('IMGPF_IS_64BIT_DATA',0x00000400)
@@ -512,6 +519,7 @@ IMGPF_PLUGIN_HOST_DISABLE_A_KEYS = Constant('IMGPF_PLUGIN_HOST_DISABLE_A_KEYS',0
IMGPF_HW_TPRO = Constant('IMGPF_HW_TPRO',0x00004000)
IMGPF_ROSETTA = Constant('IMGPF_ROSETTA',0x10000000)
IMGPF_ALT_ROSETTA = Constant('IMGPF_ALT_ROSETTA',0x20000000)
IMGPF_RESERVED_2 = Constant('IMGPF_RESERVED_2',0x40000000)
IMGPF_NOJOP = Constant('IMGPF_NOJOP',0x80000000)
IMGPF_SB_DEFAULT = Constant('IMGPF_SB_DEFAULT',0)
IMGPF_SB_TRUE = Constant('IMGPF_SB_TRUE',1)
@@ -560,9 +568,34 @@ WSTOPPED = Constant('WSTOPPED',0x00000008)
WCONTINUED = Constant('WCONTINUED',0x00000010)
WNOWAIT = Constant('WNOWAIT',0x00000020)
WAIT_MYPGRP = Constant('WAIT_MYPGRP',0)
PRIO_DARWIN_GPU = Constant('PRIO_DARWIN_GPU',5)
PRIO_DARWIN_GPU_ALLOW = Constant('PRIO_DARWIN_GPU_ALLOW',0x1)
PRIO_DARWIN_GPU_DENY = Constant('PRIO_DARWIN_GPU_DENY',0x2)
PRIO_DARWIN_ROLE = Constant('PRIO_DARWIN_ROLE',6)
PRIO_DARWIN_ROLE_DEFAULT = Constant('PRIO_DARWIN_ROLE_DEFAULT',0x0)
PRIO_DARWIN_ROLE_UI_FOCAL = Constant('PRIO_DARWIN_ROLE_UI_FOCAL',0x1)
PRIO_DARWIN_ROLE_UI = Constant('PRIO_DARWIN_ROLE_UI',0x2)
PRIO_DARWIN_ROLE_NON_UI = Constant('PRIO_DARWIN_ROLE_NON_UI',0x3)
PRIO_DARWIN_ROLE_UI_NON_FOCAL = Constant('PRIO_DARWIN_ROLE_UI_NON_FOCAL',0x4)
PRIO_DARWIN_ROLE_TAL_LAUNCH = Constant('PRIO_DARWIN_ROLE_TAL_LAUNCH',0x5)
PRIO_DARWIN_ROLE_DARWIN_BG = Constant('PRIO_DARWIN_ROLE_DARWIN_BG',0x6)
PRIO_DARWIN_GAME_MODE = Constant('PRIO_DARWIN_GAME_MODE',7)
PRIO_DARWIN_CARPLAY_MODE = Constant('PRIO_DARWIN_CARPLAY_MODE',8)
PRIO_DARWIN_GAME_MODE_OFF = Constant('PRIO_DARWIN_GAME_MODE_OFF',0x0)
PRIO_DARWIN_GAME_MODE_ON = Constant('PRIO_DARWIN_GAME_MODE_ON',0x1)
PRIO_DARWIN_CARPLAY_MODE_OFF = Constant('PRIO_DARWIN_CARPLAY_MODE_OFF',0x0)
PRIO_DARWIN_CARPLAY_MODE_ON = Constant('PRIO_DARWIN_CARPLAY_MODE_ON',0x1)
IOMON_ENABLE = Constant('IOMON_ENABLE',0x01)
IOMON_DISABLE = Constant('IOMON_DISABLE',0x02)
IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY = Constant('IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY',1)
IOPOL_TYPE_VFS_ALTLINK = Constant('IOPOL_TYPE_VFS_ALTLINK',11)
IOPOL_TYPE_VFS_NOCACHE_WRITE_FS_BLKSIZE = Constant('IOPOL_TYPE_VFS_NOCACHE_WRITE_FS_BLKSIZE',12)
IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT = Constant('IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT',0)
IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE = Constant('IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE',1)
IOPOL_VFS_ALTLINK_DISABLED = Constant('IOPOL_VFS_ALTLINK_DISABLED',0)
IOPOL_VFS_ALTLINK_ENABLED = Constant('IOPOL_VFS_ALTLINK_ENABLED',1)
IOPOL_CMD_GET = Constant('IOPOL_CMD_GET',0x00000001)
IOPOL_CMD_SET = Constant('IOPOL_CMD_SET',0x00000002)
IPC_CREAT = Constant('IPC_CREAT',0o001000)
IPC_EXCL = Constant('IPC_EXCL',0o002000)
IPC_NOWAIT = Constant('IPC_NOWAIT',0o004000)
@@ -677,6 +710,7 @@ F_SETLEASE = Constant('F_SETLEASE',106)
F_GETLEASE = Constant('F_GETLEASE',107)
F_TRANSFEREXTENTS = Constant('F_TRANSFEREXTENTS',110)
F_ATTRIBUTION_TAG = Constant('F_ATTRIBUTION_TAG',111)
F_ADDSIGS_MAIN_BINARY = Constant('F_ADDSIGS_MAIN_BINARY',113)
FCNTL_FS_SPECIFIC_BASE = Constant('FCNTL_FS_SPECIFIC_BASE',0x00010000)
F_DUPFD_CLOEXEC = Constant('F_DUPFD_CLOEXEC',67)
FD_CLOEXEC = Constant('FD_CLOEXEC',1)
@@ -904,6 +938,7 @@ MADV_FREE_REUSABLE = Constant('MADV_FREE_REUSABLE',7)
MADV_FREE_REUSE = Constant('MADV_FREE_REUSE',8)
MADV_CAN_REUSE = Constant('MADV_CAN_REUSE',9)
MADV_PAGEOUT = Constant('MADV_PAGEOUT',10)
MADV_ZERO = Constant('MADV_ZERO',11)
MINCORE_INCORE = Constant('MINCORE_INCORE',0x1)
MINCORE_REFERENCED = Constant('MINCORE_REFERENCED',0x2)
MINCORE_MODIFIED = Constant('MINCORE_MODIFIED',0x4)
@@ -1111,6 +1146,9 @@ DBG_MACH_EXCP_EMUL = Constant('DBG_MACH_EXCP_EMUL',0x0E)
DBG_MACH_IHDLR = Constant('DBG_MACH_IHDLR',0x10)
DBG_MACH_IPC = Constant('DBG_MACH_IPC',0x20)
DBG_MACH_RESOURCE = Constant('DBG_MACH_RESOURCE',0x25)
DBG_MACH_EXCLAVES = Constant('DBG_MACH_EXCLAVES',0x2A)
DBG_MACH_EXCLAVES_SCHEDULER = Constant('DBG_MACH_EXCLAVES_SCHEDULER',0x2B)
DBG_MACH_EPOCH_SYNC = Constant('DBG_MACH_EPOCH_SYNC',0x2C)
DBG_MACH_VM = Constant('DBG_MACH_VM',0x30)
DBG_MACH_LEAKS = Constant('DBG_MACH_LEAKS',0x31)
DBG_MACH_WORKINGSET = Constant('DBG_MACH_WORKINGSET',0x32)
@@ -1136,6 +1174,7 @@ DBG_MACH_HV = Constant('DBG_MACH_HV',0xAC)
DBG_MACH_KCOV = Constant('DBG_MACH_KCOV',0xAD)
DBG_MACH_MACHDEP_EXCP_SC_x86 = Constant('DBG_MACH_MACHDEP_EXCP_SC_x86',0xAE)
DBG_MACH_MACHDEP_EXCP_SC_ARM = Constant('DBG_MACH_MACHDEP_EXCP_SC_ARM',0xAF)
DBG_MACH_VM_RECLAIM = Constant('DBG_MACH_VM_RECLAIM',0xB0)
DBC_MACH_IO_MMIO_READ = Constant('DBC_MACH_IO_MMIO_READ',0x1)
DBC_MACH_IO_MMIO_WRITE = Constant('DBC_MACH_IO_MMIO_WRITE',0x2)
DBC_MACH_IO_PHYS_READ = Constant('DBC_MACH_IO_PHYS_READ',0x3)
@@ -1177,7 +1216,6 @@ MACH_RW_DEMOTE = Constant('MACH_RW_DEMOTE',0x1d)
MACH_SCHED_MAINTENANCE = Constant('MACH_SCHED_MAINTENANCE',0x1f)
MACH_DISPATCH = Constant('MACH_DISPATCH',0x20)
MACH_QUANTUM_HANDOFF = Constant('MACH_QUANTUM_HANDOFF',0x21)
MACH_MULTIQ_DEQUEUE = Constant('MACH_MULTIQ_DEQUEUE',0x22)
MACH_SCHED_THREAD_SWITCH = Constant('MACH_SCHED_THREAD_SWITCH',0x23)
MACH_SCHED_SMT_BALANCE = Constant('MACH_SCHED_SMT_BALANCE',0x24)
MACH_REMOTE_DEFERRED_AST = Constant('MACH_REMOTE_DEFERRED_AST',0x25)
@@ -1229,6 +1267,7 @@ MACH_RT_DISALLOWED_WORK_INTERVAL = Constant('MACH_RT_DISALLOWED_WORK_INTERVAL',0
MACH_SCHED_WI_EXTERNAL_WAKEUP = Constant('MACH_SCHED_WI_EXTERNAL_WAKEUP',0x61)
MACH_SCHED_AST_CHECK = Constant('MACH_SCHED_AST_CHECK',0x62)
MACH_SCHED_PREEMPT_TIMER_ACTIVE = Constant('MACH_SCHED_PREEMPT_TIMER_ACTIVE',0x63)
MACH_PROCESSOR_SHUTDOWN = Constant('MACH_PROCESSOR_SHUTDOWN',0x64)
MACH_SCHED_CLUTCH_ROOT_BUCKET_STATE = Constant('MACH_SCHED_CLUTCH_ROOT_BUCKET_STATE',0x0)
MACH_SCHED_CLUTCH_TG_BUCKET_STATE = Constant('MACH_SCHED_CLUTCH_TG_BUCKET_STATE',0x1)
MACH_SCHED_CLUTCH_THREAD_SELECT = Constant('MACH_SCHED_CLUTCH_THREAD_SELECT',0x2)
@@ -1254,20 +1293,83 @@ WORKGROUP_INTERVAL_SET_WORKLOAD_ID = Constant('WORKGROUP_INTERVAL_SET_WORKLOAD_I
WORKGROUP_INTERVAL_SET_WORKLOAD_ID_NAME = Constant('WORKGROUP_INTERVAL_SET_WORKLOAD_ID_NAME',0x7)
KCOV_STKSZ_THRESHOLD_ABOVE = Constant('KCOV_STKSZ_THRESHOLD_ABOVE',0x0)
KCOV_STKSZ_THRESHOLD_BELOW = Constant('KCOV_STKSZ_THRESHOLD_BELOW',0x1)
MACH_MULTIQ_BOUND = Constant('MACH_MULTIQ_BOUND',1)
MACH_MULTIQ_GROUP = Constant('MACH_MULTIQ_GROUP',2)
MACH_MULTIQ_GLOBAL = Constant('MACH_MULTIQ_GLOBAL',3)
DBG_ZERO_FILL_FAULT = Constant('DBG_ZERO_FILL_FAULT',1)
DBG_PAGEIN_FAULT = Constant('DBG_PAGEIN_FAULT',2)
DBG_COW_FAULT = Constant('DBG_COW_FAULT',3)
DBG_CACHE_HIT_FAULT = Constant('DBG_CACHE_HIT_FAULT',4)
DBG_NZF_PAGE_FAULT = Constant('DBG_NZF_PAGE_FAULT',5)
DBG_GUARD_FAULT = Constant('DBG_GUARD_FAULT',6)
DBG_PAGEINV_FAULT = Constant('DBG_PAGEINV_FAULT',7)
DBG_PAGEIND_FAULT = Constant('DBG_PAGEIND_FAULT',8)
DBG_COMPRESSOR_FAULT = Constant('DBG_COMPRESSOR_FAULT',9)
DBG_COMPRESSOR_SWAPIN_FAULT = Constant('DBG_COMPRESSOR_SWAPIN_FAULT',10)
DBG_COR_FAULT = Constant('DBG_COR_FAULT',11)
DBG_VM_VNODE_PAGEOUT = Constant('DBG_VM_VNODE_PAGEOUT',0x001)
DBG_VM_FAULT_INTERNAL = Constant('DBG_VM_FAULT_INTERNAL',0x002)
DBG_VM_PURGEABLE_TOKEN_ADD = Constant('DBG_VM_PURGEABLE_TOKEN_ADD',0x040)
DBG_VM_PURGEABLE_TOKEN_DELETE = Constant('DBG_VM_PURGEABLE_TOKEN_DELETE',0x041)
DBG_VM_PURGEABLE_TOKEN_RIPEN = Constant('DBG_VM_PURGEABLE_TOKEN_RIPEN',0x042)
DBG_VM_PURGEABLE_OBJECT_ADD = Constant('DBG_VM_PURGEABLE_OBJECT_ADD',0x048)
DBG_VM_PURGEABLE_OBJECT_REMOVE = Constant('DBG_VM_PURGEABLE_OBJECT_REMOVE',0x049)
DBG_VM_PURGEABLE_OBJECT_PURGE = Constant('DBG_VM_PURGEABLE_OBJECT_PURGE',0x04a)
DBG_VM_PURGEABLE_OBJECT_PURGE_ALL = Constant('DBG_VM_PURGEABLE_OBJECT_PURGE_ALL',0x04b)
DBG_VM_PURGEABLE_OBJECT_PURGE_ONE = Constant('DBG_VM_PURGEABLE_OBJECT_PURGE_ONE',0x04c)
DBG_VM_PURGEABLE_OBJECT_PURGE_LOOP = Constant('DBG_VM_PURGEABLE_OBJECT_PURGE_LOOP',0x04e)
DBG_VM_MAP_PARTIAL_REAP = Constant('DBG_VM_MAP_PARTIAL_REAP',0x054)
DBG_VM_MAP_WILLNEED = Constant('DBG_VM_MAP_WILLNEED',0x055)
DBG_VM_FAULT_CHECK_ZFDELAY = Constant('DBG_VM_FAULT_CHECK_ZFDELAY',0x100)
DBG_VM_FAULT_COWDELAY = Constant('DBG_VM_FAULT_COWDELAY',0x101)
DBG_VM_FAULT_ZFDELAY = Constant('DBG_VM_FAULT_ZFDELAY',0x102)
DBG_VM_FAULT_COMPRESSORDELAY = Constant('DBG_VM_FAULT_COMPRESSORDELAY',0x103)
DBG_VM_PAGEOUT_SCAN = Constant('DBG_VM_PAGEOUT_SCAN',0x104)
DBG_VM_PAGEOUT_BALANCE = Constant('DBG_VM_PAGEOUT_BALANCE',0x105)
DBG_VM_PAGEOUT_FREELIST = Constant('DBG_VM_PAGEOUT_FREELIST',0x106)
DBG_VM_PAGEOUT_PURGEONE = Constant('DBG_VM_PAGEOUT_PURGEONE',0x107)
DBG_VM_PAGEOUT_CACHE_EVICT = Constant('DBG_VM_PAGEOUT_CACHE_EVICT',0x108)
DBG_VM_PAGEOUT_THREAD_BLOCK = Constant('DBG_VM_PAGEOUT_THREAD_BLOCK',0x109)
DBG_VM_PAGEOUT_JETSAM = Constant('DBG_VM_PAGEOUT_JETSAM',0x10A)
DBG_VM_INFO1 = Constant('DBG_VM_INFO1',0x10B)
DBG_VM_INFO2 = Constant('DBG_VM_INFO2',0x10C)
DBG_VM_INFO3 = Constant('DBG_VM_INFO3',0x10D)
DBG_VM_INFO4 = Constant('DBG_VM_INFO4',0x10E)
DBG_VM_INFO5 = Constant('DBG_VM_INFO5',0x10F)
DBG_VM_INFO6 = Constant('DBG_VM_INFO6',0x110)
DBG_VM_INFO7 = Constant('DBG_VM_INFO7',0x111)
DBG_VM_INFO8 = Constant('DBG_VM_INFO8',0x112)
DBG_VM_INFO9 = Constant('DBG_VM_INFO9',0x113)
DBG_VM_INFO10 = Constant('DBG_VM_INFO10',0x114)
DBG_VM_UPL_PAGE_WAIT = Constant('DBG_VM_UPL_PAGE_WAIT',0x120)
DBG_VM_IOPL_PAGE_WAIT = Constant('DBG_VM_IOPL_PAGE_WAIT',0x121)
DBG_VM_PAGE_WAIT_BLOCK = Constant('DBG_VM_PAGE_WAIT_BLOCK',0x122)
DBG_VM_PAGE_SLEEP = Constant('DBG_VM_PAGE_SLEEP',0x123)
DBG_VM_PAGE_EXPEDITE = Constant('DBG_VM_PAGE_EXPEDITE',0x124)
DBG_VM_PAGE_EXPEDITE_NO_MEMORY = Constant('DBG_VM_PAGE_EXPEDITE_NO_MEMORY',0x125)
DBG_VM_PAGE_GRAB = Constant('DBG_VM_PAGE_GRAB',0x126)
DBG_VM_PAGE_RELEASE = Constant('DBG_VM_PAGE_RELEASE',0x127)
DBG_VM_COMPRESSOR_COMPACT_AND_SWAP = Constant('DBG_VM_COMPRESSOR_COMPACT_AND_SWAP',0x128)
DBG_VM_COMPRESSOR_DELAYED_COMPACT = Constant('DBG_VM_COMPRESSOR_DELAYED_COMPACT',0x129)
DBG_VM_OBJECT_SLEEP = Constant('DBG_VM_OBJECT_SLEEP',0x12a)
DBG_VM_PAGE_WAKEUP = Constant('DBG_VM_PAGE_WAKEUP',0x12b)
DBG_VM_PAGE_WAKEUP_DONE = Constant('DBG_VM_PAGE_WAKEUP_DONE',0x12c)
DBG_VM_PRESSURE_EVENT = Constant('DBG_VM_PRESSURE_EVENT',0x130)
DBG_VM_EXECVE = Constant('DBG_VM_EXECVE',0x131)
DBG_VM_WAKEUP_COMPACTOR_SWAPPER = Constant('DBG_VM_WAKEUP_COMPACTOR_SWAPPER',0x132)
DBG_VM_UPL_REQUEST = Constant('DBG_VM_UPL_REQUEST',0x133)
DBG_VM_IOPL_REQUEST = Constant('DBG_VM_IOPL_REQUEST',0x134)
DBG_VM_KERN_REQUEST = Constant('DBG_VM_KERN_REQUEST',0x135)
DBG_VM_DATA_WRITE = Constant('DBG_VM_DATA_WRITE',0x140)
DBG_VM_PRESSURE_LEVEL_CHANGE = Constant('DBG_VM_PRESSURE_LEVEL_CHANGE',0x141)
DBG_VM_PHYS_WRITE_ACCT = Constant('DBG_VM_PHYS_WRITE_ACCT',0x142)
DBG_VM_MAP_LOOKUP_ENTRY_FAILURE = Constant('DBG_VM_MAP_LOOKUP_ENTRY_FAILURE',0x143)
VM_DISCONNECT_ALL_PAGE_MAPPINGS = Constant('VM_DISCONNECT_ALL_PAGE_MAPPINGS',0x00)
VM_DISCONNECT_TASK_PAGE_MAPPINGS = Constant('VM_DISCONNECT_TASK_PAGE_MAPPINGS',0x01)
VM_REAL_FAULT_ADDR_INTERNAL = Constant('VM_REAL_FAULT_ADDR_INTERNAL',0x02)
VM_REAL_FAULT_ADDR_PURGABLE = Constant('VM_REAL_FAULT_ADDR_PURGABLE',0x03)
VM_REAL_FAULT_ADDR_EXTERNAL = Constant('VM_REAL_FAULT_ADDR_EXTERNAL',0x04)
VM_REAL_FAULT_ADDR_SHAREDCACHE = Constant('VM_REAL_FAULT_ADDR_SHAREDCACHE',0x05)
VM_REAL_FAULT_FAST = Constant('VM_REAL_FAULT_FAST',0x06)
VM_REAL_FAULT_SLOW = Constant('VM_REAL_FAULT_SLOW',0x07)
VM_MAP_LOOKUP_OBJECT = Constant('VM_MAP_LOOKUP_OBJECT',0x08)
DBG_ZERO_FILL_FAULT = Constant('DBG_ZERO_FILL_FAULT',0x01)
DBG_PAGEIN_FAULT = Constant('DBG_PAGEIN_FAULT',0x02)
DBG_COW_FAULT = Constant('DBG_COW_FAULT',0x03)
DBG_CACHE_HIT_FAULT = Constant('DBG_CACHE_HIT_FAULT',0x04)
DBG_NZF_PAGE_FAULT = Constant('DBG_NZF_PAGE_FAULT',0x05)
DBG_GUARD_FAULT = Constant('DBG_GUARD_FAULT',0x06)
DBG_PAGEINV_FAULT = Constant('DBG_PAGEINV_FAULT',0x07)
DBG_PAGEIND_FAULT = Constant('DBG_PAGEIND_FAULT',0x08)
DBG_COMPRESSOR_FAULT = Constant('DBG_COMPRESSOR_FAULT',0x09)
DBG_COMPRESSOR_SWAPIN_FAULT = Constant('DBG_COMPRESSOR_SWAPIN_FAULT',0x0a)
DBG_COR_FAULT = Constant('DBG_COR_FAULT',0x0b)
MACH_TASK_SUSPEND = Constant('MACH_TASK_SUSPEND',0x0)
MACH_TASK_RESUME = Constant('MACH_TASK_RESUME',0x1)
MACH_THREAD_SET_VOUCHER = Constant('MACH_THREAD_SET_VOUCHER',0x2)
@@ -1282,6 +1384,31 @@ MACH_IPC_KMSG_INFO = Constant('MACH_IPC_KMSG_INFO',0xa)
MACH_IPC_KMSG_LINK = Constant('MACH_IPC_KMSG_LINK',0xb)
MACH_IPC_PORT_ENTRY_MODIFY = Constant('MACH_IPC_PORT_ENTRY_MODIFY',0xc)
MACH_IPC_DESTROY_GUARDED_DESC = Constant('MACH_IPC_DESTROY_GUARDED_DESC',0xd)
MACH_THREAD_SUSPEND = Constant('MACH_THREAD_SUSPEND',0xe)
MACH_THREAD_RESUME = Constant('MACH_THREAD_RESUME',0xf)
MACH_EXCLAVES_SWITCH = Constant('MACH_EXCLAVES_SWITCH',0x0)
MACH_EXCLAVES_XNUPROXY = Constant('MACH_EXCLAVES_XNUPROXY',0x1)
MACH_EXCLAVES_RPC = Constant('MACH_EXCLAVES_RPC',0x2)
MACH_EXCLAVES_UPCALL = Constant('MACH_EXCLAVES_UPCALL',0x3)
MACH_EXCLAVES_BOOT_TASK = Constant('MACH_EXCLAVES_BOOT_TASK',0x4)
MACH_EXCLAVES_SCHEDULER_YIELD = Constant('MACH_EXCLAVES_SCHEDULER_YIELD',0x0)
MACH_EXCLAVES_SCHEDULER_SPAWNED = Constant('MACH_EXCLAVES_SCHEDULER_SPAWNED',0x1)
MACH_EXCLAVES_SCHEDULER_TERMINATED = Constant('MACH_EXCLAVES_SCHEDULER_TERMINATED',0x2)
MACH_EXCLAVES_SCHEDULER_WAIT = Constant('MACH_EXCLAVES_SCHEDULER_WAIT',0x3)
MACH_EXCLAVES_SCHEDULER_WAKE = Constant('MACH_EXCLAVES_SCHEDULER_WAKE',0x4)
MACH_EXCLAVES_SCHEDULER_SUSPENDED = Constant('MACH_EXCLAVES_SCHEDULER_SUSPENDED',0x5)
MACH_EXCLAVES_SCHEDULER_RESUMED = Constant('MACH_EXCLAVES_SCHEDULER_RESUMED',0x6)
MACH_EXCLAVES_SCHEDULER_INTERRUPTED = Constant('MACH_EXCLAVES_SCHEDULER_INTERRUPTED',0x7)
MACH_EXCLAVES_SCHEDULER_NOTHING_SCHEDULED = Constant('MACH_EXCLAVES_SCHEDULER_NOTHING_SCHEDULED',0x8)
MACH_EXCLAVES_SCHEDULER_ALL_EXCLAVES_BOOTED = Constant('MACH_EXCLAVES_SCHEDULER_ALL_EXCLAVES_BOOTED',0x9)
MACH_EXCLAVES_SCHEDULER_EARLY_ALLOC = Constant('MACH_EXCLAVES_SCHEDULER_EARLY_ALLOC',0xa)
MACH_EPOCH_SYNC_WAIT_STALE = Constant('MACH_EPOCH_SYNC_WAIT_STALE',0x0)
MACH_EPOCH_SYNC_WAIT = Constant('MACH_EPOCH_SYNC_WAIT',0x1)
MACH_EPOCH_SYNC_WAKE_NO_WAITERS = Constant('MACH_EPOCH_SYNC_WAKE_NO_WAITERS',0x2)
MACH_EPOCH_SYNC_WAKE_ONE = Constant('MACH_EPOCH_SYNC_WAKE_ONE',0x3)
MACH_EPOCH_SYNC_WAKE_ALL = Constant('MACH_EPOCH_SYNC_WAKE_ALL',0x4)
MACH_EPOCH_SYNC_WAKE_ONE_WITH_OWNER = Constant('MACH_EPOCH_SYNC_WAKE_ONE_WITH_OWNER',0x5)
MACH_EPOCH_SYNC_WAKE_THREAD = Constant('MACH_EPOCH_SYNC_WAKE_THREAD',0x6)
MACH_THREAD_GROUP_NEW = Constant('MACH_THREAD_GROUP_NEW',0x0)
MACH_THREAD_GROUP_FREE = Constant('MACH_THREAD_GROUP_FREE',0x1)
MACH_THREAD_GROUP_SET = Constant('MACH_THREAD_GROUP_SET',0x2)
@@ -1424,6 +1551,13 @@ HV_X86_VM_MAP_TRAP = Constant('HV_X86_VM_MAP_TRAP',0x2a)
HV_X86_VM_PROTECT_TRAP = Constant('HV_X86_VM_PROTECT_TRAP',0x2b)
HV_X86_VM_UNMAP_TRAP = Constant('HV_X86_VM_UNMAP_TRAP',0x2c)
HV_X86_TSC_OFFSET_SET = Constant('HV_X86_TSC_OFFSET_SET',0x2d)
VM_RECLAIM_UPDATE_ACCOUNTING = Constant('VM_RECLAIM_UPDATE_ACCOUNTING',0x01)
VM_RECLAIM_ENTRIES = Constant('VM_RECLAIM_ENTRIES',0x02)
VM_RECLAIM_CHUNK = Constant('VM_RECLAIM_CHUNK',0x03)
VM_RECLAIM_ENTRY = Constant('VM_RECLAIM_ENTRY',0x04)
VM_RECLAIM_ALL_MEMORY = Constant('VM_RECLAIM_ALL_MEMORY',0x05)
VM_RECLAIM_ASYNC_MEMORY = Constant('VM_RECLAIM_ASYNC_MEMORY',0x06)
VM_RECLAIM_INIT = Constant('VM_RECLAIM_INIT',0x07)
DBG_NETIP = Constant('DBG_NETIP',1)
DBG_NETARP = Constant('DBG_NETARP',2)
DBG_NETUDP = Constant('DBG_NETUDP',3)
@@ -2109,6 +2243,7 @@ XATTR_REPLACE = Constant('XATTR_REPLACE',0x0004)
XATTR_NOSECURITY = Constant('XATTR_NOSECURITY',0x0008)
XATTR_NODEFAULT = Constant('XATTR_NODEFAULT',0x0010)
XATTR_SHOWCOMPRESSION = Constant('XATTR_SHOWCOMPRESSION',0x0020)
XATTR_NOFOLLOW_ANY = Constant('XATTR_NOFOLLOW_ANY',0x0040)
XATTR_MAXNAMELEN = Constant('XATTR_MAXNAMELEN',127)
PR_SLOWHZ = Constant('PR_SLOWHZ',2)
PRC_IFDOWN = Constant('PRC_IFDOWN',0)
@@ -2142,6 +2277,7 @@ CTL_FLAG_REG_ID_UNIT = Constant('CTL_FLAG_REG_ID_UNIT',0x2)
CTL_FLAG_REG_SOCK_STREAM = Constant('CTL_FLAG_REG_SOCK_STREAM',0x4)
CTL_DATA_NOWAKEUP = Constant('CTL_DATA_NOWAKEUP',0x1)
CTL_DATA_EOR = Constant('CTL_DATA_EOR',0x2)
__has_safe_buffers = Constant('__has_safe_buffers',0)
__DARWIN_ONLY_64_BIT_INO_T = Constant('__DARWIN_ONLY_64_BIT_INO_T',0)
__DARWIN_ONLY_UNIX_CONFORMANCE = Constant('__DARWIN_ONLY_UNIX_CONFORMANCE',0)
__DARWIN_ONLY_VERS_1050 = Constant('__DARWIN_ONLY_VERS_1050',0)
@@ -2479,7 +2615,8 @@ VQ_QUOTA = Constant('VQ_QUOTA',0x1000)
VQ_NEARLOWDISK = Constant('VQ_NEARLOWDISK',0x2000)
VQ_DESIRED_DISK = Constant('VQ_DESIRED_DISK',0x4000)
VQ_FREE_SPACE_CHANGE = Constant('VQ_FREE_SPACE_CHANGE',0x8000)
VQ_FLAG10000 = Constant('VQ_FLAG10000',0x10000)
VQ_PURGEABLE_SPACE_CHANGE = Constant('VQ_PURGEABLE_SPACE_CHANGE',0x10000)
VQ_FLAG20000 = Constant('VQ_FLAG20000',0x20000)
VFS_IOATTR_FLAGS_FUA = Constant('VFS_IOATTR_FLAGS_FUA',0x00000001)
VFS_IOATTR_FLAGS_UNMAP = Constant('VFS_IOATTR_FLAGS_UNMAP',0x00000002)
VFS_IOATTR_FLAGS_SWAPPIN_SUPPORTED = Constant('VFS_IOATTR_FLAGS_SWAPPIN_SUPPORTED',0x00000010)
@@ -2510,7 +2647,7 @@ LK_NOWAIT = Constant('LK_NOWAIT',1)
NFSV4_MAX_FH_SIZE = Constant('NFSV4_MAX_FH_SIZE',128)
NFSV3_MAX_FH_SIZE = Constant('NFSV3_MAX_FH_SIZE',64)
NFSV2_MAX_FH_SIZE = Constant('NFSV2_MAX_FH_SIZE',32)
CRYPTEX_AUTH_STRUCT_VERSION = Constant('CRYPTEX_AUTH_STRUCT_VERSION',1)
CRYPTEX_AUTH_STRUCT_VERSION = Constant('CRYPTEX_AUTH_STRUCT_VERSION',2)
EV_FD = Constant('EV_FD',1)
EV_RE = Constant('EV_RE',1)
EV_WR = Constant('EV_WR',2)
@@ -2534,6 +2671,10 @@ KDEBUG_LEVEL_STANDARD = Constant('KDEBUG_LEVEL_STANDARD',2)
KDEBUG_LEVEL_FULL = Constant('KDEBUG_LEVEL_FULL',3)
KDBG_FLAG_FILTERED = Constant('KDBG_FLAG_FILTERED',0x01)
KDBG_FLAG_NOPROCFILT = Constant('KDBG_FLAG_NOPROCFILT',0x02)
__DARWIN_LITTLE_ENDIAN = Constant('__DARWIN_LITTLE_ENDIAN',1234)
__DARWIN_BIG_ENDIAN = Constant('__DARWIN_BIG_ENDIAN',4321)
__DARWIN_PDP_ENDIAN = Constant('__DARWIN_PDP_ENDIAN',3412)
USE_CLANG_TYPES = Constant('USE_CLANG_TYPES',0)
__DARWIN_NULL = Constant('__DARWIN_NULL',0)
UBC_PUSHDIRTY = Constant('UBC_PUSHDIRTY',0x01)
UBC_PUSHALL = Constant('UBC_PUSHALL',0x02)
@@ -3069,7 +3210,9 @@ SYS_record_system_event = Constant('SYS_record_system_event',552)
SYS_mkfifoat = Constant('SYS_mkfifoat',553)
SYS_mknodat = Constant('SYS_mknodat',554)
SYS_ungraftdmg = Constant('SYS_ungraftdmg',555)
SYS_MAXSYSCALL = Constant('SYS_MAXSYSCALL',556)
SYS_coalition_policy_set = Constant('SYS_coalition_policy_set',556)
SYS_coalition_policy_get = Constant('SYS_coalition_policy_get',557)
SYS_MAXSYSCALL = Constant('SYS_MAXSYSCALL',558)
SYS_invalid = Constant('SYS_invalid',63)
SOCK_STREAM = Constant('SOCK_STREAM',1)
SOCK_DGRAM = Constant('SOCK_DGRAM',2)
@@ -3117,6 +3260,7 @@ SO_NUMRCVPKT = Constant('SO_NUMRCVPKT',0x1112)
SO_NET_SERVICE_TYPE = Constant('SO_NET_SERVICE_TYPE',0x1116)
SO_NETSVC_MARKING_LEVEL = Constant('SO_NETSVC_MARKING_LEVEL',0x1119)
SO_RESOLVER_SIGNATURE = Constant('SO_RESOLVER_SIGNATURE',0x1131)
SO_BINDTODEVICE = Constant('SO_BINDTODEVICE',0x1134)
NET_SERVICE_TYPE_BE = Constant('NET_SERVICE_TYPE_BE',0)
NET_SERVICE_TYPE_BK = Constant('NET_SERVICE_TYPE_BK',1)
NET_SERVICE_TYPE_SIG = Constant('NET_SERVICE_TYPE_SIG',2)
+163 -19
View File
@@ -88,6 +88,7 @@ VOL_CAP_FMT_NO_PERMISSIONS = Constant('VOL_CAP_FMT_NO_PERMISSIONS',0x00400000)
VOL_CAP_FMT_SHARED_SPACE = Constant('VOL_CAP_FMT_SHARED_SPACE',0x00800000)
VOL_CAP_FMT_VOL_GROUPS = Constant('VOL_CAP_FMT_VOL_GROUPS',0x01000000)
VOL_CAP_FMT_SEALED = Constant('VOL_CAP_FMT_SEALED',0x02000000)
VOL_CAP_FMT_CLONE_MAPPING = Constant('VOL_CAP_FMT_CLONE_MAPPING',0x04000000)
VOL_CAP_INT_SEARCHFS = Constant('VOL_CAP_INT_SEARCHFS',0x00000001)
VOL_CAP_INT_ATTRLIST = Constant('VOL_CAP_INT_ATTRLIST',0x00000002)
VOL_CAP_INT_NFSEXPORT = Constant('VOL_CAP_INT_NFSEXPORT',0x00000004)
@@ -109,6 +110,8 @@ VOL_CAP_INT_RENAME_SWAP = Constant('VOL_CAP_INT_RENAME_SWAP',0x00040000)
VOL_CAP_INT_RENAME_EXCL = Constant('VOL_CAP_INT_RENAME_EXCL',0x00080000)
VOL_CAP_INT_RENAME_OPENFAIL = Constant('VOL_CAP_INT_RENAME_OPENFAIL',0x00100000)
VOL_CAP_INT_RENAME_SECLUDE = Constant('VOL_CAP_INT_RENAME_SECLUDE',0x00200000)
VOL_CAP_INT_ATTRIBUTION_TAG = Constant('VOL_CAP_INT_ATTRIBUTION_TAG',0x00400000)
VOL_CAP_INT_PUNCHHOLE = Constant('VOL_CAP_INT_PUNCHHOLE',0x00800000)
ATTR_CMN_NAME = Constant('ATTR_CMN_NAME',0x00000001)
ATTR_CMN_DEVID = Constant('ATTR_CMN_DEVID',0x00000002)
ATTR_CMN_FSID = Constant('ATTR_CMN_FSID',0x00000004)
@@ -293,6 +296,8 @@ IO_SYSCALL_DISPATCH = Constant('IO_SYSCALL_DISPATCH',0x100000)
IO_SWAP_DISPATCH = Constant('IO_SWAP_DISPATCH',0x200000)
IO_SKIP_ENCRYPTION = Constant('IO_SKIP_ENCRYPTION',0x400000)
IO_EVTONLY = Constant('IO_EVTONLY',0x800000)
IO_NOCACHE_SYSSPACE = Constant('IO_NOCACHE_SYSSPACE',0x1000000)
IO_NOCACHE_SWRITE = Constant('IO_NOCACHE_SWRITE',0x2000000)
LOOKUP = Constant('LOOKUP',0)
CREATE = Constant('CREATE',1)
DELETE = Constant('DELETE',2)
@@ -347,6 +352,7 @@ VNODE_UPDATE_PURGE = Constant('VNODE_UPDATE_PURGE',0x08)
VNODE_LOOKUP_NOFOLLOW = Constant('VNODE_LOOKUP_NOFOLLOW',0x01)
VNODE_LOOKUP_NOCROSSMOUNT = Constant('VNODE_LOOKUP_NOCROSSMOUNT',0x02)
VNODE_LOOKUP_CROSSMOUNTNOWAIT = Constant('VNODE_LOOKUP_CROSSMOUNTNOWAIT',0x04)
VNODE_LOOKUP_NOFOLLOW_ANY = Constant('VNODE_LOOKUP_NOFOLLOW_ANY',0x08)
VNODE_RELOAD = Constant('VNODE_RELOAD',0x01)
VNODE_WAIT = Constant('VNODE_WAIT',0x02)
VNODE_WRITEABLE = Constant('VNODE_WRITEABLE',0x04)
@@ -425,7 +431,7 @@ LOCKPARENT = Constant('LOCKPARENT',0x0008)
WANTPARENT = Constant('WANTPARENT',0x0010)
UIO_MAXIOV = Constant('UIO_MAXIOV',1024)
UIO_SMALLIOV = Constant('UIO_SMALLIOV',8)
EVFILT_SYSCOUNT = Constant('EVFILT_SYSCOUNT',17)
EVFILT_SYSCOUNT = Constant('EVFILT_SYSCOUNT',18)
KEVENT_FLAG_NONE = Constant('KEVENT_FLAG_NONE',0x000000)
KEVENT_FLAG_IMMEDIATE = Constant('KEVENT_FLAG_IMMEDIATE',0x000001)
KEVENT_FLAG_ERROR_EVENTS = Constant('KEVENT_FLAG_ERROR_EVENTS',0x000002)
@@ -503,6 +509,7 @@ IMGPF_IS_64BIT_ADDR = Constant('IMGPF_IS_64BIT_ADDR',0x00000008)
IMGPF_SPAWN = Constant('IMGPF_SPAWN',0x00000010)
IMGPF_DISABLE_ASLR = Constant('IMGPF_DISABLE_ASLR',0x00000020)
IMGPF_ALLOW_DATA_EXEC = Constant('IMGPF_ALLOW_DATA_EXEC',0x00000040)
IMGPF_3P_PLUGINS = Constant('IMGPF_3P_PLUGINS',0x00000080)
IMGPF_EXEC = Constant('IMGPF_EXEC',0x00000100)
IMGPF_HIGH_BITS_ASLR = Constant('IMGPF_HIGH_BITS_ASLR',0x00000200)
IMGPF_IS_64BIT_DATA = Constant('IMGPF_IS_64BIT_DATA',0x00000400)
@@ -512,6 +519,7 @@ IMGPF_PLUGIN_HOST_DISABLE_A_KEYS = Constant('IMGPF_PLUGIN_HOST_DISABLE_A_KEYS',0
IMGPF_HW_TPRO = Constant('IMGPF_HW_TPRO',0x00004000)
IMGPF_ROSETTA = Constant('IMGPF_ROSETTA',0x10000000)
IMGPF_ALT_ROSETTA = Constant('IMGPF_ALT_ROSETTA',0x20000000)
IMGPF_RESERVED_2 = Constant('IMGPF_RESERVED_2',0x40000000)
IMGPF_NOJOP = Constant('IMGPF_NOJOP',0x80000000)
IMGPF_SB_DEFAULT = Constant('IMGPF_SB_DEFAULT',0)
IMGPF_SB_TRUE = Constant('IMGPF_SB_TRUE',1)
@@ -560,9 +568,34 @@ WSTOPPED = Constant('WSTOPPED',0x00000008)
WCONTINUED = Constant('WCONTINUED',0x00000010)
WNOWAIT = Constant('WNOWAIT',0x00000020)
WAIT_MYPGRP = Constant('WAIT_MYPGRP',0)
PRIO_DARWIN_GPU = Constant('PRIO_DARWIN_GPU',5)
PRIO_DARWIN_GPU_ALLOW = Constant('PRIO_DARWIN_GPU_ALLOW',0x1)
PRIO_DARWIN_GPU_DENY = Constant('PRIO_DARWIN_GPU_DENY',0x2)
PRIO_DARWIN_ROLE = Constant('PRIO_DARWIN_ROLE',6)
PRIO_DARWIN_ROLE_DEFAULT = Constant('PRIO_DARWIN_ROLE_DEFAULT',0x0)
PRIO_DARWIN_ROLE_UI_FOCAL = Constant('PRIO_DARWIN_ROLE_UI_FOCAL',0x1)
PRIO_DARWIN_ROLE_UI = Constant('PRIO_DARWIN_ROLE_UI',0x2)
PRIO_DARWIN_ROLE_NON_UI = Constant('PRIO_DARWIN_ROLE_NON_UI',0x3)
PRIO_DARWIN_ROLE_UI_NON_FOCAL = Constant('PRIO_DARWIN_ROLE_UI_NON_FOCAL',0x4)
PRIO_DARWIN_ROLE_TAL_LAUNCH = Constant('PRIO_DARWIN_ROLE_TAL_LAUNCH',0x5)
PRIO_DARWIN_ROLE_DARWIN_BG = Constant('PRIO_DARWIN_ROLE_DARWIN_BG',0x6)
PRIO_DARWIN_GAME_MODE = Constant('PRIO_DARWIN_GAME_MODE',7)
PRIO_DARWIN_CARPLAY_MODE = Constant('PRIO_DARWIN_CARPLAY_MODE',8)
PRIO_DARWIN_GAME_MODE_OFF = Constant('PRIO_DARWIN_GAME_MODE_OFF',0x0)
PRIO_DARWIN_GAME_MODE_ON = Constant('PRIO_DARWIN_GAME_MODE_ON',0x1)
PRIO_DARWIN_CARPLAY_MODE_OFF = Constant('PRIO_DARWIN_CARPLAY_MODE_OFF',0x0)
PRIO_DARWIN_CARPLAY_MODE_ON = Constant('PRIO_DARWIN_CARPLAY_MODE_ON',0x1)
IOMON_ENABLE = Constant('IOMON_ENABLE',0x01)
IOMON_DISABLE = Constant('IOMON_DISABLE',0x02)
IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY = Constant('IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY',1)
IOPOL_TYPE_VFS_ALTLINK = Constant('IOPOL_TYPE_VFS_ALTLINK',11)
IOPOL_TYPE_VFS_NOCACHE_WRITE_FS_BLKSIZE = Constant('IOPOL_TYPE_VFS_NOCACHE_WRITE_FS_BLKSIZE',12)
IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT = Constant('IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT',0)
IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE = Constant('IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE',1)
IOPOL_VFS_ALTLINK_DISABLED = Constant('IOPOL_VFS_ALTLINK_DISABLED',0)
IOPOL_VFS_ALTLINK_ENABLED = Constant('IOPOL_VFS_ALTLINK_ENABLED',1)
IOPOL_CMD_GET = Constant('IOPOL_CMD_GET',0x00000001)
IOPOL_CMD_SET = Constant('IOPOL_CMD_SET',0x00000002)
IPC_CREAT = Constant('IPC_CREAT',0o001000)
IPC_EXCL = Constant('IPC_EXCL',0o002000)
IPC_NOWAIT = Constant('IPC_NOWAIT',0o004000)
@@ -677,6 +710,7 @@ F_SETLEASE = Constant('F_SETLEASE',106)
F_GETLEASE = Constant('F_GETLEASE',107)
F_TRANSFEREXTENTS = Constant('F_TRANSFEREXTENTS',110)
F_ATTRIBUTION_TAG = Constant('F_ATTRIBUTION_TAG',111)
F_ADDSIGS_MAIN_BINARY = Constant('F_ADDSIGS_MAIN_BINARY',113)
FCNTL_FS_SPECIFIC_BASE = Constant('FCNTL_FS_SPECIFIC_BASE',0x00010000)
F_DUPFD_CLOEXEC = Constant('F_DUPFD_CLOEXEC',67)
FD_CLOEXEC = Constant('FD_CLOEXEC',1)
@@ -904,6 +938,7 @@ MADV_FREE_REUSABLE = Constant('MADV_FREE_REUSABLE',7)
MADV_FREE_REUSE = Constant('MADV_FREE_REUSE',8)
MADV_CAN_REUSE = Constant('MADV_CAN_REUSE',9)
MADV_PAGEOUT = Constant('MADV_PAGEOUT',10)
MADV_ZERO = Constant('MADV_ZERO',11)
MINCORE_INCORE = Constant('MINCORE_INCORE',0x1)
MINCORE_REFERENCED = Constant('MINCORE_REFERENCED',0x2)
MINCORE_MODIFIED = Constant('MINCORE_MODIFIED',0x4)
@@ -1111,6 +1146,9 @@ DBG_MACH_EXCP_EMUL = Constant('DBG_MACH_EXCP_EMUL',0x0E)
DBG_MACH_IHDLR = Constant('DBG_MACH_IHDLR',0x10)
DBG_MACH_IPC = Constant('DBG_MACH_IPC',0x20)
DBG_MACH_RESOURCE = Constant('DBG_MACH_RESOURCE',0x25)
DBG_MACH_EXCLAVES = Constant('DBG_MACH_EXCLAVES',0x2A)
DBG_MACH_EXCLAVES_SCHEDULER = Constant('DBG_MACH_EXCLAVES_SCHEDULER',0x2B)
DBG_MACH_EPOCH_SYNC = Constant('DBG_MACH_EPOCH_SYNC',0x2C)
DBG_MACH_VM = Constant('DBG_MACH_VM',0x30)
DBG_MACH_LEAKS = Constant('DBG_MACH_LEAKS',0x31)
DBG_MACH_WORKINGSET = Constant('DBG_MACH_WORKINGSET',0x32)
@@ -1136,6 +1174,7 @@ DBG_MACH_HV = Constant('DBG_MACH_HV',0xAC)
DBG_MACH_KCOV = Constant('DBG_MACH_KCOV',0xAD)
DBG_MACH_MACHDEP_EXCP_SC_x86 = Constant('DBG_MACH_MACHDEP_EXCP_SC_x86',0xAE)
DBG_MACH_MACHDEP_EXCP_SC_ARM = Constant('DBG_MACH_MACHDEP_EXCP_SC_ARM',0xAF)
DBG_MACH_VM_RECLAIM = Constant('DBG_MACH_VM_RECLAIM',0xB0)
DBC_MACH_IO_MMIO_READ = Constant('DBC_MACH_IO_MMIO_READ',0x1)
DBC_MACH_IO_MMIO_WRITE = Constant('DBC_MACH_IO_MMIO_WRITE',0x2)
DBC_MACH_IO_PHYS_READ = Constant('DBC_MACH_IO_PHYS_READ',0x3)
@@ -1177,7 +1216,6 @@ MACH_RW_DEMOTE = Constant('MACH_RW_DEMOTE',0x1d)
MACH_SCHED_MAINTENANCE = Constant('MACH_SCHED_MAINTENANCE',0x1f)
MACH_DISPATCH = Constant('MACH_DISPATCH',0x20)
MACH_QUANTUM_HANDOFF = Constant('MACH_QUANTUM_HANDOFF',0x21)
MACH_MULTIQ_DEQUEUE = Constant('MACH_MULTIQ_DEQUEUE',0x22)
MACH_SCHED_THREAD_SWITCH = Constant('MACH_SCHED_THREAD_SWITCH',0x23)
MACH_SCHED_SMT_BALANCE = Constant('MACH_SCHED_SMT_BALANCE',0x24)
MACH_REMOTE_DEFERRED_AST = Constant('MACH_REMOTE_DEFERRED_AST',0x25)
@@ -1229,6 +1267,7 @@ MACH_RT_DISALLOWED_WORK_INTERVAL = Constant('MACH_RT_DISALLOWED_WORK_INTERVAL',0
MACH_SCHED_WI_EXTERNAL_WAKEUP = Constant('MACH_SCHED_WI_EXTERNAL_WAKEUP',0x61)
MACH_SCHED_AST_CHECK = Constant('MACH_SCHED_AST_CHECK',0x62)
MACH_SCHED_PREEMPT_TIMER_ACTIVE = Constant('MACH_SCHED_PREEMPT_TIMER_ACTIVE',0x63)
MACH_PROCESSOR_SHUTDOWN = Constant('MACH_PROCESSOR_SHUTDOWN',0x64)
MACH_SCHED_CLUTCH_ROOT_BUCKET_STATE = Constant('MACH_SCHED_CLUTCH_ROOT_BUCKET_STATE',0x0)
MACH_SCHED_CLUTCH_TG_BUCKET_STATE = Constant('MACH_SCHED_CLUTCH_TG_BUCKET_STATE',0x1)
MACH_SCHED_CLUTCH_THREAD_SELECT = Constant('MACH_SCHED_CLUTCH_THREAD_SELECT',0x2)
@@ -1254,20 +1293,83 @@ WORKGROUP_INTERVAL_SET_WORKLOAD_ID = Constant('WORKGROUP_INTERVAL_SET_WORKLOAD_I
WORKGROUP_INTERVAL_SET_WORKLOAD_ID_NAME = Constant('WORKGROUP_INTERVAL_SET_WORKLOAD_ID_NAME',0x7)
KCOV_STKSZ_THRESHOLD_ABOVE = Constant('KCOV_STKSZ_THRESHOLD_ABOVE',0x0)
KCOV_STKSZ_THRESHOLD_BELOW = Constant('KCOV_STKSZ_THRESHOLD_BELOW',0x1)
MACH_MULTIQ_BOUND = Constant('MACH_MULTIQ_BOUND',1)
MACH_MULTIQ_GROUP = Constant('MACH_MULTIQ_GROUP',2)
MACH_MULTIQ_GLOBAL = Constant('MACH_MULTIQ_GLOBAL',3)
DBG_ZERO_FILL_FAULT = Constant('DBG_ZERO_FILL_FAULT',1)
DBG_PAGEIN_FAULT = Constant('DBG_PAGEIN_FAULT',2)
DBG_COW_FAULT = Constant('DBG_COW_FAULT',3)
DBG_CACHE_HIT_FAULT = Constant('DBG_CACHE_HIT_FAULT',4)
DBG_NZF_PAGE_FAULT = Constant('DBG_NZF_PAGE_FAULT',5)
DBG_GUARD_FAULT = Constant('DBG_GUARD_FAULT',6)
DBG_PAGEINV_FAULT = Constant('DBG_PAGEINV_FAULT',7)
DBG_PAGEIND_FAULT = Constant('DBG_PAGEIND_FAULT',8)
DBG_COMPRESSOR_FAULT = Constant('DBG_COMPRESSOR_FAULT',9)
DBG_COMPRESSOR_SWAPIN_FAULT = Constant('DBG_COMPRESSOR_SWAPIN_FAULT',10)
DBG_COR_FAULT = Constant('DBG_COR_FAULT',11)
DBG_VM_VNODE_PAGEOUT = Constant('DBG_VM_VNODE_PAGEOUT',0x001)
DBG_VM_FAULT_INTERNAL = Constant('DBG_VM_FAULT_INTERNAL',0x002)
DBG_VM_PURGEABLE_TOKEN_ADD = Constant('DBG_VM_PURGEABLE_TOKEN_ADD',0x040)
DBG_VM_PURGEABLE_TOKEN_DELETE = Constant('DBG_VM_PURGEABLE_TOKEN_DELETE',0x041)
DBG_VM_PURGEABLE_TOKEN_RIPEN = Constant('DBG_VM_PURGEABLE_TOKEN_RIPEN',0x042)
DBG_VM_PURGEABLE_OBJECT_ADD = Constant('DBG_VM_PURGEABLE_OBJECT_ADD',0x048)
DBG_VM_PURGEABLE_OBJECT_REMOVE = Constant('DBG_VM_PURGEABLE_OBJECT_REMOVE',0x049)
DBG_VM_PURGEABLE_OBJECT_PURGE = Constant('DBG_VM_PURGEABLE_OBJECT_PURGE',0x04a)
DBG_VM_PURGEABLE_OBJECT_PURGE_ALL = Constant('DBG_VM_PURGEABLE_OBJECT_PURGE_ALL',0x04b)
DBG_VM_PURGEABLE_OBJECT_PURGE_ONE = Constant('DBG_VM_PURGEABLE_OBJECT_PURGE_ONE',0x04c)
DBG_VM_PURGEABLE_OBJECT_PURGE_LOOP = Constant('DBG_VM_PURGEABLE_OBJECT_PURGE_LOOP',0x04e)
DBG_VM_MAP_PARTIAL_REAP = Constant('DBG_VM_MAP_PARTIAL_REAP',0x054)
DBG_VM_MAP_WILLNEED = Constant('DBG_VM_MAP_WILLNEED',0x055)
DBG_VM_FAULT_CHECK_ZFDELAY = Constant('DBG_VM_FAULT_CHECK_ZFDELAY',0x100)
DBG_VM_FAULT_COWDELAY = Constant('DBG_VM_FAULT_COWDELAY',0x101)
DBG_VM_FAULT_ZFDELAY = Constant('DBG_VM_FAULT_ZFDELAY',0x102)
DBG_VM_FAULT_COMPRESSORDELAY = Constant('DBG_VM_FAULT_COMPRESSORDELAY',0x103)
DBG_VM_PAGEOUT_SCAN = Constant('DBG_VM_PAGEOUT_SCAN',0x104)
DBG_VM_PAGEOUT_BALANCE = Constant('DBG_VM_PAGEOUT_BALANCE',0x105)
DBG_VM_PAGEOUT_FREELIST = Constant('DBG_VM_PAGEOUT_FREELIST',0x106)
DBG_VM_PAGEOUT_PURGEONE = Constant('DBG_VM_PAGEOUT_PURGEONE',0x107)
DBG_VM_PAGEOUT_CACHE_EVICT = Constant('DBG_VM_PAGEOUT_CACHE_EVICT',0x108)
DBG_VM_PAGEOUT_THREAD_BLOCK = Constant('DBG_VM_PAGEOUT_THREAD_BLOCK',0x109)
DBG_VM_PAGEOUT_JETSAM = Constant('DBG_VM_PAGEOUT_JETSAM',0x10A)
DBG_VM_INFO1 = Constant('DBG_VM_INFO1',0x10B)
DBG_VM_INFO2 = Constant('DBG_VM_INFO2',0x10C)
DBG_VM_INFO3 = Constant('DBG_VM_INFO3',0x10D)
DBG_VM_INFO4 = Constant('DBG_VM_INFO4',0x10E)
DBG_VM_INFO5 = Constant('DBG_VM_INFO5',0x10F)
DBG_VM_INFO6 = Constant('DBG_VM_INFO6',0x110)
DBG_VM_INFO7 = Constant('DBG_VM_INFO7',0x111)
DBG_VM_INFO8 = Constant('DBG_VM_INFO8',0x112)
DBG_VM_INFO9 = Constant('DBG_VM_INFO9',0x113)
DBG_VM_INFO10 = Constant('DBG_VM_INFO10',0x114)
DBG_VM_UPL_PAGE_WAIT = Constant('DBG_VM_UPL_PAGE_WAIT',0x120)
DBG_VM_IOPL_PAGE_WAIT = Constant('DBG_VM_IOPL_PAGE_WAIT',0x121)
DBG_VM_PAGE_WAIT_BLOCK = Constant('DBG_VM_PAGE_WAIT_BLOCK',0x122)
DBG_VM_PAGE_SLEEP = Constant('DBG_VM_PAGE_SLEEP',0x123)
DBG_VM_PAGE_EXPEDITE = Constant('DBG_VM_PAGE_EXPEDITE',0x124)
DBG_VM_PAGE_EXPEDITE_NO_MEMORY = Constant('DBG_VM_PAGE_EXPEDITE_NO_MEMORY',0x125)
DBG_VM_PAGE_GRAB = Constant('DBG_VM_PAGE_GRAB',0x126)
DBG_VM_PAGE_RELEASE = Constant('DBG_VM_PAGE_RELEASE',0x127)
DBG_VM_COMPRESSOR_COMPACT_AND_SWAP = Constant('DBG_VM_COMPRESSOR_COMPACT_AND_SWAP',0x128)
DBG_VM_COMPRESSOR_DELAYED_COMPACT = Constant('DBG_VM_COMPRESSOR_DELAYED_COMPACT',0x129)
DBG_VM_OBJECT_SLEEP = Constant('DBG_VM_OBJECT_SLEEP',0x12a)
DBG_VM_PAGE_WAKEUP = Constant('DBG_VM_PAGE_WAKEUP',0x12b)
DBG_VM_PAGE_WAKEUP_DONE = Constant('DBG_VM_PAGE_WAKEUP_DONE',0x12c)
DBG_VM_PRESSURE_EVENT = Constant('DBG_VM_PRESSURE_EVENT',0x130)
DBG_VM_EXECVE = Constant('DBG_VM_EXECVE',0x131)
DBG_VM_WAKEUP_COMPACTOR_SWAPPER = Constant('DBG_VM_WAKEUP_COMPACTOR_SWAPPER',0x132)
DBG_VM_UPL_REQUEST = Constant('DBG_VM_UPL_REQUEST',0x133)
DBG_VM_IOPL_REQUEST = Constant('DBG_VM_IOPL_REQUEST',0x134)
DBG_VM_KERN_REQUEST = Constant('DBG_VM_KERN_REQUEST',0x135)
DBG_VM_DATA_WRITE = Constant('DBG_VM_DATA_WRITE',0x140)
DBG_VM_PRESSURE_LEVEL_CHANGE = Constant('DBG_VM_PRESSURE_LEVEL_CHANGE',0x141)
DBG_VM_PHYS_WRITE_ACCT = Constant('DBG_VM_PHYS_WRITE_ACCT',0x142)
DBG_VM_MAP_LOOKUP_ENTRY_FAILURE = Constant('DBG_VM_MAP_LOOKUP_ENTRY_FAILURE',0x143)
VM_DISCONNECT_ALL_PAGE_MAPPINGS = Constant('VM_DISCONNECT_ALL_PAGE_MAPPINGS',0x00)
VM_DISCONNECT_TASK_PAGE_MAPPINGS = Constant('VM_DISCONNECT_TASK_PAGE_MAPPINGS',0x01)
VM_REAL_FAULT_ADDR_INTERNAL = Constant('VM_REAL_FAULT_ADDR_INTERNAL',0x02)
VM_REAL_FAULT_ADDR_PURGABLE = Constant('VM_REAL_FAULT_ADDR_PURGABLE',0x03)
VM_REAL_FAULT_ADDR_EXTERNAL = Constant('VM_REAL_FAULT_ADDR_EXTERNAL',0x04)
VM_REAL_FAULT_ADDR_SHAREDCACHE = Constant('VM_REAL_FAULT_ADDR_SHAREDCACHE',0x05)
VM_REAL_FAULT_FAST = Constant('VM_REAL_FAULT_FAST',0x06)
VM_REAL_FAULT_SLOW = Constant('VM_REAL_FAULT_SLOW',0x07)
VM_MAP_LOOKUP_OBJECT = Constant('VM_MAP_LOOKUP_OBJECT',0x08)
DBG_ZERO_FILL_FAULT = Constant('DBG_ZERO_FILL_FAULT',0x01)
DBG_PAGEIN_FAULT = Constant('DBG_PAGEIN_FAULT',0x02)
DBG_COW_FAULT = Constant('DBG_COW_FAULT',0x03)
DBG_CACHE_HIT_FAULT = Constant('DBG_CACHE_HIT_FAULT',0x04)
DBG_NZF_PAGE_FAULT = Constant('DBG_NZF_PAGE_FAULT',0x05)
DBG_GUARD_FAULT = Constant('DBG_GUARD_FAULT',0x06)
DBG_PAGEINV_FAULT = Constant('DBG_PAGEINV_FAULT',0x07)
DBG_PAGEIND_FAULT = Constant('DBG_PAGEIND_FAULT',0x08)
DBG_COMPRESSOR_FAULT = Constant('DBG_COMPRESSOR_FAULT',0x09)
DBG_COMPRESSOR_SWAPIN_FAULT = Constant('DBG_COMPRESSOR_SWAPIN_FAULT',0x0a)
DBG_COR_FAULT = Constant('DBG_COR_FAULT',0x0b)
MACH_TASK_SUSPEND = Constant('MACH_TASK_SUSPEND',0x0)
MACH_TASK_RESUME = Constant('MACH_TASK_RESUME',0x1)
MACH_THREAD_SET_VOUCHER = Constant('MACH_THREAD_SET_VOUCHER',0x2)
@@ -1282,6 +1384,31 @@ MACH_IPC_KMSG_INFO = Constant('MACH_IPC_KMSG_INFO',0xa)
MACH_IPC_KMSG_LINK = Constant('MACH_IPC_KMSG_LINK',0xb)
MACH_IPC_PORT_ENTRY_MODIFY = Constant('MACH_IPC_PORT_ENTRY_MODIFY',0xc)
MACH_IPC_DESTROY_GUARDED_DESC = Constant('MACH_IPC_DESTROY_GUARDED_DESC',0xd)
MACH_THREAD_SUSPEND = Constant('MACH_THREAD_SUSPEND',0xe)
MACH_THREAD_RESUME = Constant('MACH_THREAD_RESUME',0xf)
MACH_EXCLAVES_SWITCH = Constant('MACH_EXCLAVES_SWITCH',0x0)
MACH_EXCLAVES_XNUPROXY = Constant('MACH_EXCLAVES_XNUPROXY',0x1)
MACH_EXCLAVES_RPC = Constant('MACH_EXCLAVES_RPC',0x2)
MACH_EXCLAVES_UPCALL = Constant('MACH_EXCLAVES_UPCALL',0x3)
MACH_EXCLAVES_BOOT_TASK = Constant('MACH_EXCLAVES_BOOT_TASK',0x4)
MACH_EXCLAVES_SCHEDULER_YIELD = Constant('MACH_EXCLAVES_SCHEDULER_YIELD',0x0)
MACH_EXCLAVES_SCHEDULER_SPAWNED = Constant('MACH_EXCLAVES_SCHEDULER_SPAWNED',0x1)
MACH_EXCLAVES_SCHEDULER_TERMINATED = Constant('MACH_EXCLAVES_SCHEDULER_TERMINATED',0x2)
MACH_EXCLAVES_SCHEDULER_WAIT = Constant('MACH_EXCLAVES_SCHEDULER_WAIT',0x3)
MACH_EXCLAVES_SCHEDULER_WAKE = Constant('MACH_EXCLAVES_SCHEDULER_WAKE',0x4)
MACH_EXCLAVES_SCHEDULER_SUSPENDED = Constant('MACH_EXCLAVES_SCHEDULER_SUSPENDED',0x5)
MACH_EXCLAVES_SCHEDULER_RESUMED = Constant('MACH_EXCLAVES_SCHEDULER_RESUMED',0x6)
MACH_EXCLAVES_SCHEDULER_INTERRUPTED = Constant('MACH_EXCLAVES_SCHEDULER_INTERRUPTED',0x7)
MACH_EXCLAVES_SCHEDULER_NOTHING_SCHEDULED = Constant('MACH_EXCLAVES_SCHEDULER_NOTHING_SCHEDULED',0x8)
MACH_EXCLAVES_SCHEDULER_ALL_EXCLAVES_BOOTED = Constant('MACH_EXCLAVES_SCHEDULER_ALL_EXCLAVES_BOOTED',0x9)
MACH_EXCLAVES_SCHEDULER_EARLY_ALLOC = Constant('MACH_EXCLAVES_SCHEDULER_EARLY_ALLOC',0xa)
MACH_EPOCH_SYNC_WAIT_STALE = Constant('MACH_EPOCH_SYNC_WAIT_STALE',0x0)
MACH_EPOCH_SYNC_WAIT = Constant('MACH_EPOCH_SYNC_WAIT',0x1)
MACH_EPOCH_SYNC_WAKE_NO_WAITERS = Constant('MACH_EPOCH_SYNC_WAKE_NO_WAITERS',0x2)
MACH_EPOCH_SYNC_WAKE_ONE = Constant('MACH_EPOCH_SYNC_WAKE_ONE',0x3)
MACH_EPOCH_SYNC_WAKE_ALL = Constant('MACH_EPOCH_SYNC_WAKE_ALL',0x4)
MACH_EPOCH_SYNC_WAKE_ONE_WITH_OWNER = Constant('MACH_EPOCH_SYNC_WAKE_ONE_WITH_OWNER',0x5)
MACH_EPOCH_SYNC_WAKE_THREAD = Constant('MACH_EPOCH_SYNC_WAKE_THREAD',0x6)
MACH_THREAD_GROUP_NEW = Constant('MACH_THREAD_GROUP_NEW',0x0)
MACH_THREAD_GROUP_FREE = Constant('MACH_THREAD_GROUP_FREE',0x1)
MACH_THREAD_GROUP_SET = Constant('MACH_THREAD_GROUP_SET',0x2)
@@ -1424,6 +1551,13 @@ HV_X86_VM_MAP_TRAP = Constant('HV_X86_VM_MAP_TRAP',0x2a)
HV_X86_VM_PROTECT_TRAP = Constant('HV_X86_VM_PROTECT_TRAP',0x2b)
HV_X86_VM_UNMAP_TRAP = Constant('HV_X86_VM_UNMAP_TRAP',0x2c)
HV_X86_TSC_OFFSET_SET = Constant('HV_X86_TSC_OFFSET_SET',0x2d)
VM_RECLAIM_UPDATE_ACCOUNTING = Constant('VM_RECLAIM_UPDATE_ACCOUNTING',0x01)
VM_RECLAIM_ENTRIES = Constant('VM_RECLAIM_ENTRIES',0x02)
VM_RECLAIM_CHUNK = Constant('VM_RECLAIM_CHUNK',0x03)
VM_RECLAIM_ENTRY = Constant('VM_RECLAIM_ENTRY',0x04)
VM_RECLAIM_ALL_MEMORY = Constant('VM_RECLAIM_ALL_MEMORY',0x05)
VM_RECLAIM_ASYNC_MEMORY = Constant('VM_RECLAIM_ASYNC_MEMORY',0x06)
VM_RECLAIM_INIT = Constant('VM_RECLAIM_INIT',0x07)
DBG_NETIP = Constant('DBG_NETIP',1)
DBG_NETARP = Constant('DBG_NETARP',2)
DBG_NETUDP = Constant('DBG_NETUDP',3)
@@ -2109,6 +2243,7 @@ XATTR_REPLACE = Constant('XATTR_REPLACE',0x0004)
XATTR_NOSECURITY = Constant('XATTR_NOSECURITY',0x0008)
XATTR_NODEFAULT = Constant('XATTR_NODEFAULT',0x0010)
XATTR_SHOWCOMPRESSION = Constant('XATTR_SHOWCOMPRESSION',0x0020)
XATTR_NOFOLLOW_ANY = Constant('XATTR_NOFOLLOW_ANY',0x0040)
XATTR_MAXNAMELEN = Constant('XATTR_MAXNAMELEN',127)
PR_SLOWHZ = Constant('PR_SLOWHZ',2)
PRC_IFDOWN = Constant('PRC_IFDOWN',0)
@@ -2142,6 +2277,7 @@ CTL_FLAG_REG_ID_UNIT = Constant('CTL_FLAG_REG_ID_UNIT',0x2)
CTL_FLAG_REG_SOCK_STREAM = Constant('CTL_FLAG_REG_SOCK_STREAM',0x4)
CTL_DATA_NOWAKEUP = Constant('CTL_DATA_NOWAKEUP',0x1)
CTL_DATA_EOR = Constant('CTL_DATA_EOR',0x2)
__has_safe_buffers = Constant('__has_safe_buffers',0)
__DARWIN_ONLY_64_BIT_INO_T = Constant('__DARWIN_ONLY_64_BIT_INO_T',0)
__DARWIN_ONLY_UNIX_CONFORMANCE = Constant('__DARWIN_ONLY_UNIX_CONFORMANCE',0)
__DARWIN_ONLY_VERS_1050 = Constant('__DARWIN_ONLY_VERS_1050',0)
@@ -2479,7 +2615,8 @@ VQ_QUOTA = Constant('VQ_QUOTA',0x1000)
VQ_NEARLOWDISK = Constant('VQ_NEARLOWDISK',0x2000)
VQ_DESIRED_DISK = Constant('VQ_DESIRED_DISK',0x4000)
VQ_FREE_SPACE_CHANGE = Constant('VQ_FREE_SPACE_CHANGE',0x8000)
VQ_FLAG10000 = Constant('VQ_FLAG10000',0x10000)
VQ_PURGEABLE_SPACE_CHANGE = Constant('VQ_PURGEABLE_SPACE_CHANGE',0x10000)
VQ_FLAG20000 = Constant('VQ_FLAG20000',0x20000)
VFS_IOATTR_FLAGS_FUA = Constant('VFS_IOATTR_FLAGS_FUA',0x00000001)
VFS_IOATTR_FLAGS_UNMAP = Constant('VFS_IOATTR_FLAGS_UNMAP',0x00000002)
VFS_IOATTR_FLAGS_SWAPPIN_SUPPORTED = Constant('VFS_IOATTR_FLAGS_SWAPPIN_SUPPORTED',0x00000010)
@@ -2510,7 +2647,7 @@ LK_NOWAIT = Constant('LK_NOWAIT',1)
NFSV4_MAX_FH_SIZE = Constant('NFSV4_MAX_FH_SIZE',128)
NFSV3_MAX_FH_SIZE = Constant('NFSV3_MAX_FH_SIZE',64)
NFSV2_MAX_FH_SIZE = Constant('NFSV2_MAX_FH_SIZE',32)
CRYPTEX_AUTH_STRUCT_VERSION = Constant('CRYPTEX_AUTH_STRUCT_VERSION',1)
CRYPTEX_AUTH_STRUCT_VERSION = Constant('CRYPTEX_AUTH_STRUCT_VERSION',2)
EV_FD = Constant('EV_FD',1)
EV_RE = Constant('EV_RE',1)
EV_WR = Constant('EV_WR',2)
@@ -2534,6 +2671,10 @@ KDEBUG_LEVEL_STANDARD = Constant('KDEBUG_LEVEL_STANDARD',2)
KDEBUG_LEVEL_FULL = Constant('KDEBUG_LEVEL_FULL',3)
KDBG_FLAG_FILTERED = Constant('KDBG_FLAG_FILTERED',0x01)
KDBG_FLAG_NOPROCFILT = Constant('KDBG_FLAG_NOPROCFILT',0x02)
__DARWIN_LITTLE_ENDIAN = Constant('__DARWIN_LITTLE_ENDIAN',1234)
__DARWIN_BIG_ENDIAN = Constant('__DARWIN_BIG_ENDIAN',4321)
__DARWIN_PDP_ENDIAN = Constant('__DARWIN_PDP_ENDIAN',3412)
USE_CLANG_TYPES = Constant('USE_CLANG_TYPES',0)
__DARWIN_NULL = Constant('__DARWIN_NULL',0)
UBC_PUSHDIRTY = Constant('UBC_PUSHDIRTY',0x01)
UBC_PUSHALL = Constant('UBC_PUSHALL',0x02)
@@ -3069,7 +3210,9 @@ SYS_record_system_event = Constant('SYS_record_system_event',552 + 0x2000000)
SYS_mkfifoat = Constant('SYS_mkfifoat',553 + 0x2000000)
SYS_mknodat = Constant('SYS_mknodat',554 + 0x2000000)
SYS_ungraftdmg = Constant('SYS_ungraftdmg',555 + 0x2000000)
SYS_MAXSYSCALL = Constant('SYS_MAXSYSCALL',556 + 0x2000000)
SYS_coalition_policy_set = Constant('SYS_coalition_policy_set',556 + 0x2000000)
SYS_coalition_policy_get = Constant('SYS_coalition_policy_get',557 + 0x2000000)
SYS_MAXSYSCALL = Constant('SYS_MAXSYSCALL',558 + 0x2000000)
SYS_invalid = Constant('SYS_invalid',63 + 0x2000000)
SOCK_STREAM = Constant('SOCK_STREAM',1)
SOCK_DGRAM = Constant('SOCK_DGRAM',2)
@@ -3117,6 +3260,7 @@ SO_NUMRCVPKT = Constant('SO_NUMRCVPKT',0x1112)
SO_NET_SERVICE_TYPE = Constant('SO_NET_SERVICE_TYPE',0x1116)
SO_NETSVC_MARKING_LEVEL = Constant('SO_NETSVC_MARKING_LEVEL',0x1119)
SO_RESOLVER_SIGNATURE = Constant('SO_RESOLVER_SIGNATURE',0x1131)
SO_BINDTODEVICE = Constant('SO_BINDTODEVICE',0x1134)
NET_SERVICE_TYPE_BE = Constant('NET_SERVICE_TYPE_BE',0)
NET_SERVICE_TYPE_BK = Constant('NET_SERVICE_TYPE_BK',1)
NET_SERVICE_TYPE_SIG = Constant('NET_SERVICE_TYPE_SIG',2)
File diff suppressed because it is too large. Load diff
+152 -18
View File
@@ -302,7 +302,7 @@ class ContextType(object):
>>> context.os == 'linux'
True
>>> context.arch = 'arm'
>>> vars(context) == {'arch': 'arm', 'bits': 32, 'endian': 'little', 'os': 'linux'}
>>> vars(context) == {'arch': 'arm', 'bits': 32, 'endian': 'little', 'os': 'linux', 'newline': b'\n'}
True
>>> context.endian
'little'
@@ -359,13 +359,16 @@ class ContextType(object):
'encoding': 'auto',
'endian': 'little',
'gdbinit': "",
'gdb_binary': "",
'kernel': None,
'local_libcdb': "/var/lib/libc-database",
'log_level': logging.INFO,
'log_file': _devnull(),
'log_console': sys.stdout,
'randomize': False,
'rename_corefiles': True,
'newline': b'\n',
'throw_eof_on_incomplete_line': None,
'noptrace': False,
'os': 'linux',
'proxy': None,
@@ -375,8 +378,19 @@ class ContextType(object):
'timeout': Timeout.maximum,
}
#: Valid values for :meth:`pwnlib.context.ContextType.os`
oses = sorted(('linux','freebsd','windows','cgc','android','baremetal','darwin'))
unix_like = {'newline': b'\n'}
windows_like = {'newline': b'\r\n'}
#: Keys are valid values for :meth:`pwnlib.context.ContextType.os`
oses = _longest({
'linux': unix_like,
'freebsd': unix_like,
'windows': windows_like,
'cgc': unix_like,
'android': unix_like,
'baremetal': unix_like,
'darwin': unix_like,
})
big_32 = {'endian': 'big', 'bits': 32}
big_64 = {'endian': 'big', 'bits': 64}
@@ -445,14 +459,14 @@ class ContextType(object):
def copy(self):
"""copy() -> dict
r"""copy() -> dict
Returns a copy of the current context as a dictionary.
Examples:
>>> context.clear()
>>> context.os = 'linux'
>>> vars(context) == {'os': 'linux'}
>>> vars(context) == {'os': 'linux', 'newline': b'\n'}
True
"""
return self._tls.copy()
@@ -581,9 +595,9 @@ class ContextType(object):
... log.debug("DEBUG")
... log.info("INFO")
... log.warn("WARN")
[DEBUG] DEBUG
[*] INFO
[!] WARN
[...] DEBUG
[...] INFO
[...] WARN
"""
level = 'error'
if context.log_level <= logging.DEBUG:
@@ -651,7 +665,7 @@ class ContextType(object):
information is printed.
>>> with context.verbose: func()
[DEBUG] Hello
[...] Hello
"""
return self.local(log_level='debug')
@@ -1021,6 +1035,8 @@ class ContextType(object):
"""
if isinstance(value, (bytes, six.text_type)):
# check if mode was specified as "[value],[mode]"
from pwnlib.util.packing import _need_text
value = _need_text(value)
if ',' not in value:
value += ',a'
filename, mode = value.rsplit(',', 1)
@@ -1071,31 +1087,105 @@ class ContextType(object):
stream = open(stream, 'wt')
return stream
@_validator
def local_libcdb(self, path):
"""
Sets path to local libc-database, get more information for libc-database:
https://github.com/niklasb/libc-database
Works in :attr:`pwnlib.libcdb` when searching by local database provider.
The default value is ``/var/lib/libc-database``.
Sets `context.local_libcdb` to empty string or `None` will turn off local libc-database integration.
Examples:
>>> context.local_libcdb = pwnlib.data.elf.path
>>> context.local_libcdb = 'foobar'
Traceback (most recent call last):
...
AttributeError: 'foobar' does not exist, please download libc-database first
"""
if not os.path.isdir(path):
raise AttributeError("'%s' does not exist, please download libc-database first" % path)
return path
@property
def mask(self):
return (1 << self.bits) - 1
@_validator
def os(self, os):
"""
r"""
Operating system of the target machine.
The default value is ``linux``.
Allowed values are listed in :attr:`pwnlib.context.ContextType.oses`.
Side Effects:
If an os is specified some attributes will be set on the context
if a user has not already set a value.
The following property may be modified:
- :attr:`newline`
Raises:
AttributeError: An invalid os was specified
Examples:
>>> context.os = 'linux'
>>> context.clear()
>>> context.os == 'linux' # Default os
True
>>> context.os = 'freebsd'
>>> context.os == 'freebsd'
True
>>> context.os = 'foobar' #doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError: os must be one of ['android', 'baremetal', 'cgc', 'freebsd', 'linux', 'windows']
>>> context.clear()
>>> context.newline == b'\n' # Default value
True
>>> context.os = 'windows'
>>> context.newline == b'\r\n' # New value
True
Note that expressly setting :attr:`newline` means that we use
that value instead of the default
>>> context.clear()
>>> context.newline = b'\n'
>>> context.os = 'windows'
>>> context.newline == b'\n'
True
Setting the os can override the default for :attr:`newline`
>>> context.clear()
>>> context.os = 'windows'
>>> vars(context) == {'os': 'windows', 'newline': b'\r\n'}
True
"""
os = os.lower()
if os not in self.oses:
raise AttributeError("os must be one of %r" % self.oses)
try:
defaults = self.oses[os]
except KeyError:
raise AttributeError("os must be one of %r" % sorted(self.oses))
for k,v in defaults.items():
if k not in self._tls:
self._tls[k] = v
return os
@@ -1288,9 +1378,9 @@ class ContextType(object):
def cache_dir_base(self, new_base):
"""Base directory to use for caching content.
Changing this to a different value will clear the `cache_dir` path
Changing this to a different value will clear the :attr:`cache_dir` path
stored in TLS since a new path will need to be generated to respect the
new `cache_dir_base` value.
new :attr:`cache_dir_base` value.
"""
if new_base != self.cache_dir_base:
@@ -1305,6 +1395,9 @@ class ContextType(object):
Note:
May be either a path string, or :const:`None`.
Set to :const:`None` to disable caching.
Set to :const:`True` to generate the default cache directory path
based on :attr:`cache_dir_base` again.
Example:
@@ -1312,12 +1405,18 @@ class ContextType(object):
>>> cache_dir is not None
True
>>> os.chmod(cache_dir, 0o000)
>>> del context._tls['cache_dir']
>>> context.cache_dir = True
>>> context.cache_dir is None
True
>>> os.chmod(cache_dir, 0o755)
>>> cache_dir == context.cache_dir
True
>>> context.cache_dir = None
>>> context.cache_dir is None
True
>>> context.cache_dir = True
>>> context.cache_dir is not None
True
"""
try:
# If the TLS already has a cache directory path, we return it
@@ -1362,7 +1461,9 @@ class ContextType(object):
@cache_dir.setter
def cache_dir(self, v):
if os.access(v, os.W_OK):
if v is True:
del self._tls["cache_dir"]
elif v is None or os.access(v, os.W_OK):
# Stash this in TLS for later reuse
self._tls["cache_dir"] = v
@@ -1402,6 +1503,25 @@ class ContextType(object):
# circular imports
from pwnlib.util.packing import _need_bytes
return _need_bytes(v)
@_validator
def throw_eof_on_incomplete_line(self, v):
"""Whether to raise an :class:`EOFError` if an EOF is received before a newline in ``tube.recvline``.
Controls if an :class:`EOFError` is treated as newline in ``tube.recvline`` and similar functions
and whether a warning should be logged about it.
Possible values are:
- ``True``: Raise an :class:`EOFError` if an EOF is received before a newline.
- ``False``: Return the data received so far if an EOF is received
before a newline without logging a warning.
- ``None``: Return the data received so far if an EOF is received
before a newline and log a warning.
Default value is ``None``.
"""
return v if v is None else bool(v)
@_validator
@@ -1420,6 +1540,20 @@ class ContextType(object):
"""
return str(value)
@_validator
def gdb_binary(self, value):
"""Path to the binary that is used when running GDB locally.
This is useful when you have multiple versions of gdb installed or the gdb binary is
called something different.
If set to an empty string, pwntools will try to search for a reasonable gdb binary from
the path.
Default value is ``""``.
"""
return str(value)
@_validator
def cyclic_alphabet(self, alphabet):
"""Cyclic alphabet.
@@ -1614,7 +1748,7 @@ def update_context_defaults(section):
default = ContextType.defaults[key]
if isinstance(default, six.string_types + six.integer_types + (tuple, list, dict)):
if isinstance(default, six.string_types + six.integer_types + (float, tuple, list, dict)):
value = safeeval.expr(value)
else:
log.warn("Unsupported configuration option %r in section %r" % (key, 'context'))
+163 -19
View File
@@ -87,6 +87,7 @@
#define VOL_CAP_FMT_SHARED_SPACE 0x00800000
#define VOL_CAP_FMT_VOL_GROUPS 0x01000000
#define VOL_CAP_FMT_SEALED 0x02000000
#define VOL_CAP_FMT_CLONE_MAPPING 0x04000000
#define VOL_CAP_INT_SEARCHFS 0x00000001
#define VOL_CAP_INT_ATTRLIST 0x00000002
#define VOL_CAP_INT_NFSEXPORT 0x00000004
@@ -108,6 +109,8 @@
#define VOL_CAP_INT_RENAME_EXCL 0x00080000
#define VOL_CAP_INT_RENAME_OPENFAIL 0x00100000
#define VOL_CAP_INT_RENAME_SECLUDE 0x00200000
#define VOL_CAP_INT_ATTRIBUTION_TAG 0x00400000
#define VOL_CAP_INT_PUNCHHOLE 0x00800000
#define ATTR_CMN_NAME 0x00000001
#define ATTR_CMN_DEVID 0x00000002
#define ATTR_CMN_FSID 0x00000004
@@ -292,6 +295,8 @@
#define IO_SWAP_DISPATCH 0x200000
#define IO_SKIP_ENCRYPTION 0x400000
#define IO_EVTONLY 0x800000
#define IO_NOCACHE_SYSSPACE 0x1000000
#define IO_NOCACHE_SWRITE 0x2000000
#define LOOKUP 0
#define CREATE 1
#define DELETE 2
@@ -346,6 +351,7 @@
#define VNODE_LOOKUP_NOFOLLOW 0x01
#define VNODE_LOOKUP_NOCROSSMOUNT 0x02
#define VNODE_LOOKUP_CROSSMOUNTNOWAIT 0x04
#define VNODE_LOOKUP_NOFOLLOW_ANY 0x08
#define VNODE_RELOAD 0x01
#define VNODE_WAIT 0x02
#define VNODE_WRITEABLE 0x04
@@ -424,7 +430,7 @@
#define WANTPARENT 0x0010
#define UIO_MAXIOV 1024
#define UIO_SMALLIOV 8
#define EVFILT_SYSCOUNT 17
#define EVFILT_SYSCOUNT 18
#define KEVENT_FLAG_NONE 0x000000
#define KEVENT_FLAG_IMMEDIATE 0x000001
#define KEVENT_FLAG_ERROR_EVENTS 0x000002
@@ -502,6 +508,7 @@
#define IMGPF_SPAWN 0x00000010
#define IMGPF_DISABLE_ASLR 0x00000020
#define IMGPF_ALLOW_DATA_EXEC 0x00000040
#define IMGPF_3P_PLUGINS 0x00000080
#define IMGPF_EXEC 0x00000100
#define IMGPF_HIGH_BITS_ASLR 0x00000200
#define IMGPF_IS_64BIT_DATA 0x00000400
@@ -511,6 +518,7 @@
#define IMGPF_HW_TPRO 0x00004000
#define IMGPF_ROSETTA 0x10000000
#define IMGPF_ALT_ROSETTA 0x20000000
#define IMGPF_RESERVED_2 0x40000000
#define IMGPF_NOJOP 0x80000000
#define IMGPF_SB_DEFAULT 0
#define IMGPF_SB_TRUE 1
@@ -559,9 +567,34 @@
#define WCONTINUED 0x00000010
#define WNOWAIT 0x00000020
#define WAIT_MYPGRP 0
#define PRIO_DARWIN_GPU 5
#define PRIO_DARWIN_GPU_ALLOW 0x1
#define PRIO_DARWIN_GPU_DENY 0x2
#define PRIO_DARWIN_ROLE 6
#define PRIO_DARWIN_ROLE_DEFAULT 0x0
#define PRIO_DARWIN_ROLE_UI_FOCAL 0x1
#define PRIO_DARWIN_ROLE_UI 0x2
#define PRIO_DARWIN_ROLE_NON_UI 0x3
#define PRIO_DARWIN_ROLE_UI_NON_FOCAL 0x4
#define PRIO_DARWIN_ROLE_TAL_LAUNCH 0x5
#define PRIO_DARWIN_ROLE_DARWIN_BG 0x6
#define PRIO_DARWIN_GAME_MODE 7
#define PRIO_DARWIN_CARPLAY_MODE 8
#define PRIO_DARWIN_GAME_MODE_OFF 0x0
#define PRIO_DARWIN_GAME_MODE_ON 0x1
#define PRIO_DARWIN_CARPLAY_MODE_OFF 0x0
#define PRIO_DARWIN_CARPLAY_MODE_ON 0x1
#define IOMON_ENABLE 0x01
#define IOMON_DISABLE 0x02
#define IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY 1
#define IOPOL_TYPE_VFS_ALTLINK 11
#define IOPOL_TYPE_VFS_NOCACHE_WRITE_FS_BLKSIZE 12
#define IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT 0
#define IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE 1
#define IOPOL_VFS_ALTLINK_DISABLED 0
#define IOPOL_VFS_ALTLINK_ENABLED 1
#define IOPOL_CMD_GET 0x00000001
#define IOPOL_CMD_SET 0x00000002
#define IPC_CREAT 0001000
#define IPC_EXCL 0002000
#define IPC_NOWAIT 0004000
@@ -676,6 +709,7 @@
#define F_GETLEASE 107
#define F_TRANSFEREXTENTS 110
#define F_ATTRIBUTION_TAG 111
#define F_ADDSIGS_MAIN_BINARY 113
#define FCNTL_FS_SPECIFIC_BASE 0x00010000
#define F_DUPFD_CLOEXEC 67
#define FD_CLOEXEC 1
@@ -903,6 +937,7 @@
#define MADV_FREE_REUSE 8
#define MADV_CAN_REUSE 9
#define MADV_PAGEOUT 10
#define MADV_ZERO 11
#define MINCORE_INCORE 0x1
#define MINCORE_REFERENCED 0x2
#define MINCORE_MODIFIED 0x4
@@ -1110,6 +1145,9 @@
#define DBG_MACH_IHDLR 0x10
#define DBG_MACH_IPC 0x20
#define DBG_MACH_RESOURCE 0x25
#define DBG_MACH_EXCLAVES 0x2A
#define DBG_MACH_EXCLAVES_SCHEDULER 0x2B
#define DBG_MACH_EPOCH_SYNC 0x2C
#define DBG_MACH_VM 0x30
#define DBG_MACH_LEAKS 0x31
#define DBG_MACH_WORKINGSET 0x32
@@ -1135,6 +1173,7 @@
#define DBG_MACH_KCOV 0xAD
#define DBG_MACH_MACHDEP_EXCP_SC_x86 0xAE
#define DBG_MACH_MACHDEP_EXCP_SC_ARM 0xAF
#define DBG_MACH_VM_RECLAIM 0xB0
#define DBC_MACH_IO_MMIO_READ 0x1
#define DBC_MACH_IO_MMIO_WRITE 0x2
#define DBC_MACH_IO_PHYS_READ 0x3
@@ -1176,7 +1215,6 @@
#define MACH_SCHED_MAINTENANCE 0x1f
#define MACH_DISPATCH 0x20
#define MACH_QUANTUM_HANDOFF 0x21
#define MACH_MULTIQ_DEQUEUE 0x22
#define MACH_SCHED_THREAD_SWITCH 0x23
#define MACH_SCHED_SMT_BALANCE 0x24
#define MACH_REMOTE_DEFERRED_AST 0x25
@@ -1228,6 +1266,7 @@
#define MACH_SCHED_WI_EXTERNAL_WAKEUP 0x61
#define MACH_SCHED_AST_CHECK 0x62
#define MACH_SCHED_PREEMPT_TIMER_ACTIVE 0x63
#define MACH_PROCESSOR_SHUTDOWN 0x64
#define MACH_SCHED_CLUTCH_ROOT_BUCKET_STATE 0x0
#define MACH_SCHED_CLUTCH_TG_BUCKET_STATE 0x1
#define MACH_SCHED_CLUTCH_THREAD_SELECT 0x2
@@ -1253,20 +1292,83 @@
#define WORKGROUP_INTERVAL_SET_WORKLOAD_ID_NAME 0x7
#define KCOV_STKSZ_THRESHOLD_ABOVE 0x0
#define KCOV_STKSZ_THRESHOLD_BELOW 0x1
#define MACH_MULTIQ_BOUND 1
#define MACH_MULTIQ_GROUP 2
#define MACH_MULTIQ_GLOBAL 3
#define DBG_ZERO_FILL_FAULT 1
#define DBG_PAGEIN_FAULT 2
#define DBG_COW_FAULT 3
#define DBG_CACHE_HIT_FAULT 4
#define DBG_NZF_PAGE_FAULT 5
#define DBG_GUARD_FAULT 6
#define DBG_PAGEINV_FAULT 7
#define DBG_PAGEIND_FAULT 8
#define DBG_COMPRESSOR_FAULT 9
#define DBG_COMPRESSOR_SWAPIN_FAULT 10
#define DBG_COR_FAULT 11
#define DBG_VM_VNODE_PAGEOUT 0x001
#define DBG_VM_FAULT_INTERNAL 0x002
#define DBG_VM_PURGEABLE_TOKEN_ADD 0x040
#define DBG_VM_PURGEABLE_TOKEN_DELETE 0x041
#define DBG_VM_PURGEABLE_TOKEN_RIPEN 0x042
#define DBG_VM_PURGEABLE_OBJECT_ADD 0x048
#define DBG_VM_PURGEABLE_OBJECT_REMOVE 0x049
#define DBG_VM_PURGEABLE_OBJECT_PURGE 0x04a
#define DBG_VM_PURGEABLE_OBJECT_PURGE_ALL 0x04b
#define DBG_VM_PURGEABLE_OBJECT_PURGE_ONE 0x04c
#define DBG_VM_PURGEABLE_OBJECT_PURGE_LOOP 0x04e
#define DBG_VM_MAP_PARTIAL_REAP 0x054
#define DBG_VM_MAP_WILLNEED 0x055
#define DBG_VM_FAULT_CHECK_ZFDELAY 0x100
#define DBG_VM_FAULT_COWDELAY 0x101
#define DBG_VM_FAULT_ZFDELAY 0x102
#define DBG_VM_FAULT_COMPRESSORDELAY 0x103
#define DBG_VM_PAGEOUT_SCAN 0x104
#define DBG_VM_PAGEOUT_BALANCE 0x105
#define DBG_VM_PAGEOUT_FREELIST 0x106
#define DBG_VM_PAGEOUT_PURGEONE 0x107
#define DBG_VM_PAGEOUT_CACHE_EVICT 0x108
#define DBG_VM_PAGEOUT_THREAD_BLOCK 0x109
#define DBG_VM_PAGEOUT_JETSAM 0x10A
#define DBG_VM_INFO1 0x10B
#define DBG_VM_INFO2 0x10C
#define DBG_VM_INFO3 0x10D
#define DBG_VM_INFO4 0x10E
#define DBG_VM_INFO5 0x10F
#define DBG_VM_INFO6 0x110
#define DBG_VM_INFO7 0x111
#define DBG_VM_INFO8 0x112
#define DBG_VM_INFO9 0x113
#define DBG_VM_INFO10 0x114
#define DBG_VM_UPL_PAGE_WAIT 0x120
#define DBG_VM_IOPL_PAGE_WAIT 0x121
#define DBG_VM_PAGE_WAIT_BLOCK 0x122
#define DBG_VM_PAGE_SLEEP 0x123
#define DBG_VM_PAGE_EXPEDITE 0x124
#define DBG_VM_PAGE_EXPEDITE_NO_MEMORY 0x125
#define DBG_VM_PAGE_GRAB 0x126
#define DBG_VM_PAGE_RELEASE 0x127
#define DBG_VM_COMPRESSOR_COMPACT_AND_SWAP 0x128
#define DBG_VM_COMPRESSOR_DELAYED_COMPACT 0x129
#define DBG_VM_OBJECT_SLEEP 0x12a
#define DBG_VM_PAGE_WAKEUP 0x12b
#define DBG_VM_PAGE_WAKEUP_DONE 0x12c
#define DBG_VM_PRESSURE_EVENT 0x130
#define DBG_VM_EXECVE 0x131
#define DBG_VM_WAKEUP_COMPACTOR_SWAPPER 0x132
#define DBG_VM_UPL_REQUEST 0x133
#define DBG_VM_IOPL_REQUEST 0x134
#define DBG_VM_KERN_REQUEST 0x135
#define DBG_VM_DATA_WRITE 0x140
#define DBG_VM_PRESSURE_LEVEL_CHANGE 0x141
#define DBG_VM_PHYS_WRITE_ACCT 0x142
#define DBG_VM_MAP_LOOKUP_ENTRY_FAILURE 0x143
#define VM_DISCONNECT_ALL_PAGE_MAPPINGS 0x00
#define VM_DISCONNECT_TASK_PAGE_MAPPINGS 0x01
#define VM_REAL_FAULT_ADDR_INTERNAL 0x02
#define VM_REAL_FAULT_ADDR_PURGABLE 0x03
#define VM_REAL_FAULT_ADDR_EXTERNAL 0x04
#define VM_REAL_FAULT_ADDR_SHAREDCACHE 0x05
#define VM_REAL_FAULT_FAST 0x06
#define VM_REAL_FAULT_SLOW 0x07
#define VM_MAP_LOOKUP_OBJECT 0x08
#define DBG_ZERO_FILL_FAULT 0x01
#define DBG_PAGEIN_FAULT 0x02
#define DBG_COW_FAULT 0x03
#define DBG_CACHE_HIT_FAULT 0x04
#define DBG_NZF_PAGE_FAULT 0x05
#define DBG_GUARD_FAULT 0x06
#define DBG_PAGEINV_FAULT 0x07
#define DBG_PAGEIND_FAULT 0x08
#define DBG_COMPRESSOR_FAULT 0x09
#define DBG_COMPRESSOR_SWAPIN_FAULT 0x0a
#define DBG_COR_FAULT 0x0b
#define MACH_TASK_SUSPEND 0x0
#define MACH_TASK_RESUME 0x1
#define MACH_THREAD_SET_VOUCHER 0x2
@@ -1281,6 +1383,31 @@
#define MACH_IPC_KMSG_LINK 0xb
#define MACH_IPC_PORT_ENTRY_MODIFY 0xc
#define MACH_IPC_DESTROY_GUARDED_DESC 0xd
#define MACH_THREAD_SUSPEND 0xe
#define MACH_THREAD_RESUME 0xf
#define MACH_EXCLAVES_SWITCH 0x0
#define MACH_EXCLAVES_XNUPROXY 0x1
#define MACH_EXCLAVES_RPC 0x2
#define MACH_EXCLAVES_UPCALL 0x3
#define MACH_EXCLAVES_BOOT_TASK 0x4
#define MACH_EXCLAVES_SCHEDULER_YIELD 0x0
#define MACH_EXCLAVES_SCHEDULER_SPAWNED 0x1
#define MACH_EXCLAVES_SCHEDULER_TERMINATED 0x2
#define MACH_EXCLAVES_SCHEDULER_WAIT 0x3
#define MACH_EXCLAVES_SCHEDULER_WAKE 0x4
#define MACH_EXCLAVES_SCHEDULER_SUSPENDED 0x5
#define MACH_EXCLAVES_SCHEDULER_RESUMED 0x6
#define MACH_EXCLAVES_SCHEDULER_INTERRUPTED 0x7
#define MACH_EXCLAVES_SCHEDULER_NOTHING_SCHEDULED 0x8
#define MACH_EXCLAVES_SCHEDULER_ALL_EXCLAVES_BOOTED 0x9
#define MACH_EXCLAVES_SCHEDULER_EARLY_ALLOC 0xa
#define MACH_EPOCH_SYNC_WAIT_STALE 0x0
#define MACH_EPOCH_SYNC_WAIT 0x1
#define MACH_EPOCH_SYNC_WAKE_NO_WAITERS 0x2
#define MACH_EPOCH_SYNC_WAKE_ONE 0x3
#define MACH_EPOCH_SYNC_WAKE_ALL 0x4
#define MACH_EPOCH_SYNC_WAKE_ONE_WITH_OWNER 0x5
#define MACH_EPOCH_SYNC_WAKE_THREAD 0x6
#define MACH_THREAD_GROUP_NEW 0x0
#define MACH_THREAD_GROUP_FREE 0x1
#define MACH_THREAD_GROUP_SET 0x2
@@ -1423,6 +1550,13 @@
#define HV_X86_VM_PROTECT_TRAP 0x2b
#define HV_X86_VM_UNMAP_TRAP 0x2c
#define HV_X86_TSC_OFFSET_SET 0x2d
#define VM_RECLAIM_UPDATE_ACCOUNTING 0x01
#define VM_RECLAIM_ENTRIES 0x02
#define VM_RECLAIM_CHUNK 0x03
#define VM_RECLAIM_ENTRY 0x04
#define VM_RECLAIM_ALL_MEMORY 0x05
#define VM_RECLAIM_ASYNC_MEMORY 0x06
#define VM_RECLAIM_INIT 0x07
#define DBG_NETIP 1
#define DBG_NETARP 2
#define DBG_NETUDP 3
@@ -2108,6 +2242,7 @@
#define XATTR_NOSECURITY 0x0008
#define XATTR_NODEFAULT 0x0010
#define XATTR_SHOWCOMPRESSION 0x0020
#define XATTR_NOFOLLOW_ANY 0x0040
#define XATTR_MAXNAMELEN 127
#define PR_SLOWHZ 2
#define PRC_IFDOWN 0
@@ -2141,6 +2276,7 @@
#define CTL_FLAG_REG_SOCK_STREAM 0x4
#define CTL_DATA_NOWAKEUP 0x1
#define CTL_DATA_EOR 0x2
#define __has_safe_buffers 0
#define __DARWIN_ONLY_64_BIT_INO_T 0
#define __DARWIN_ONLY_UNIX_CONFORMANCE 0
#define __DARWIN_ONLY_VERS_1050 0
@@ -2478,7 +2614,8 @@
#define VQ_NEARLOWDISK 0x2000
#define VQ_DESIRED_DISK 0x4000
#define VQ_FREE_SPACE_CHANGE 0x8000
#define VQ_FLAG10000 0x10000
#define VQ_PURGEABLE_SPACE_CHANGE 0x10000
#define VQ_FLAG20000 0x20000
#define VFS_IOATTR_FLAGS_FUA 0x00000001
#define VFS_IOATTR_FLAGS_UNMAP 0x00000002
#define VFS_IOATTR_FLAGS_SWAPPIN_SUPPORTED 0x00000010
@@ -2509,7 +2646,7 @@
#define NFSV4_MAX_FH_SIZE 128
#define NFSV3_MAX_FH_SIZE 64
#define NFSV2_MAX_FH_SIZE 32
#define CRYPTEX_AUTH_STRUCT_VERSION 1
#define CRYPTEX_AUTH_STRUCT_VERSION 2
#define EV_FD 1
#define EV_RE 1
#define EV_WR 2
@@ -2533,6 +2670,10 @@
#define KDEBUG_LEVEL_FULL 3
#define KDBG_FLAG_FILTERED 0x01
#define KDBG_FLAG_NOPROCFILT 0x02
#define __DARWIN_LITTLE_ENDIAN 1234
#define __DARWIN_BIG_ENDIAN 4321
#define __DARWIN_PDP_ENDIAN 3412
#define USE_CLANG_TYPES 0
#define __DARWIN_NULL 0
#define UBC_PUSHDIRTY 0x01
#define UBC_PUSHALL 0x02
@@ -3068,7 +3209,9 @@
#define SYS_mkfifoat 553
#define SYS_mknodat 554
#define SYS_ungraftdmg 555
#define SYS_MAXSYSCALL 556
#define SYS_coalition_policy_set 556
#define SYS_coalition_policy_get 557
#define SYS_MAXSYSCALL 558
#define SYS_invalid 63
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
@@ -3116,6 +3259,7 @@
#define SO_NET_SERVICE_TYPE 0x1116
#define SO_NETSVC_MARKING_LEVEL 0x1119
#define SO_RESOLVER_SIGNATURE 0x1131
#define SO_BINDTODEVICE 0x1134
#define NET_SERVICE_TYPE_BE 0
#define NET_SERVICE_TYPE_BK 1
#define NET_SERVICE_TYPE_SIG 2
+163 -19
View File
@@ -87,6 +87,7 @@
#define VOL_CAP_FMT_SHARED_SPACE 0x00800000
#define VOL_CAP_FMT_VOL_GROUPS 0x01000000
#define VOL_CAP_FMT_SEALED 0x02000000
#define VOL_CAP_FMT_CLONE_MAPPING 0x04000000
#define VOL_CAP_INT_SEARCHFS 0x00000001
#define VOL_CAP_INT_ATTRLIST 0x00000002
#define VOL_CAP_INT_NFSEXPORT 0x00000004
@@ -108,6 +109,8 @@
#define VOL_CAP_INT_RENAME_EXCL 0x00080000
#define VOL_CAP_INT_RENAME_OPENFAIL 0x00100000
#define VOL_CAP_INT_RENAME_SECLUDE 0x00200000
#define VOL_CAP_INT_ATTRIBUTION_TAG 0x00400000
#define VOL_CAP_INT_PUNCHHOLE 0x00800000
#define ATTR_CMN_NAME 0x00000001
#define ATTR_CMN_DEVID 0x00000002
#define ATTR_CMN_FSID 0x00000004
@@ -292,6 +295,8 @@
#define IO_SWAP_DISPATCH 0x200000
#define IO_SKIP_ENCRYPTION 0x400000
#define IO_EVTONLY 0x800000
#define IO_NOCACHE_SYSSPACE 0x1000000
#define IO_NOCACHE_SWRITE 0x2000000
#define LOOKUP 0
#define CREATE 1
#define DELETE 2
@@ -346,6 +351,7 @@
#define VNODE_LOOKUP_NOFOLLOW 0x01
#define VNODE_LOOKUP_NOCROSSMOUNT 0x02
#define VNODE_LOOKUP_CROSSMOUNTNOWAIT 0x04
#define VNODE_LOOKUP_NOFOLLOW_ANY 0x08
#define VNODE_RELOAD 0x01
#define VNODE_WAIT 0x02
#define VNODE_WRITEABLE 0x04
@@ -424,7 +430,7 @@
#define WANTPARENT 0x0010
#define UIO_MAXIOV 1024
#define UIO_SMALLIOV 8
#define EVFILT_SYSCOUNT 17
#define EVFILT_SYSCOUNT 18
#define KEVENT_FLAG_NONE 0x000000
#define KEVENT_FLAG_IMMEDIATE 0x000001
#define KEVENT_FLAG_ERROR_EVENTS 0x000002
@@ -502,6 +508,7 @@
#define IMGPF_SPAWN 0x00000010
#define IMGPF_DISABLE_ASLR 0x00000020
#define IMGPF_ALLOW_DATA_EXEC 0x00000040
#define IMGPF_3P_PLUGINS 0x00000080
#define IMGPF_EXEC 0x00000100
#define IMGPF_HIGH_BITS_ASLR 0x00000200
#define IMGPF_IS_64BIT_DATA 0x00000400
@@ -511,6 +518,7 @@
#define IMGPF_HW_TPRO 0x00004000
#define IMGPF_ROSETTA 0x10000000
#define IMGPF_ALT_ROSETTA 0x20000000
#define IMGPF_RESERVED_2 0x40000000
#define IMGPF_NOJOP 0x80000000
#define IMGPF_SB_DEFAULT 0
#define IMGPF_SB_TRUE 1
@@ -559,9 +567,34 @@
#define WCONTINUED 0x00000010
#define WNOWAIT 0x00000020
#define WAIT_MYPGRP 0
#define PRIO_DARWIN_GPU 5
#define PRIO_DARWIN_GPU_ALLOW 0x1
#define PRIO_DARWIN_GPU_DENY 0x2
#define PRIO_DARWIN_ROLE 6
#define PRIO_DARWIN_ROLE_DEFAULT 0x0
#define PRIO_DARWIN_ROLE_UI_FOCAL 0x1
#define PRIO_DARWIN_ROLE_UI 0x2
#define PRIO_DARWIN_ROLE_NON_UI 0x3
#define PRIO_DARWIN_ROLE_UI_NON_FOCAL 0x4
#define PRIO_DARWIN_ROLE_TAL_LAUNCH 0x5
#define PRIO_DARWIN_ROLE_DARWIN_BG 0x6
#define PRIO_DARWIN_GAME_MODE 7
#define PRIO_DARWIN_CARPLAY_MODE 8
#define PRIO_DARWIN_GAME_MODE_OFF 0x0
#define PRIO_DARWIN_GAME_MODE_ON 0x1
#define PRIO_DARWIN_CARPLAY_MODE_OFF 0x0
#define PRIO_DARWIN_CARPLAY_MODE_ON 0x1
#define IOMON_ENABLE 0x01
#define IOMON_DISABLE 0x02
#define IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY 1
#define IOPOL_TYPE_VFS_ALTLINK 11
#define IOPOL_TYPE_VFS_NOCACHE_WRITE_FS_BLKSIZE 12
#define IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT 0
#define IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE 1
#define IOPOL_VFS_ALTLINK_DISABLED 0
#define IOPOL_VFS_ALTLINK_ENABLED 1
#define IOPOL_CMD_GET 0x00000001
#define IOPOL_CMD_SET 0x00000002
#define IPC_CREAT 0001000
#define IPC_EXCL 0002000
#define IPC_NOWAIT 0004000
@@ -676,6 +709,7 @@
#define F_GETLEASE 107
#define F_TRANSFEREXTENTS 110
#define F_ATTRIBUTION_TAG 111
#define F_ADDSIGS_MAIN_BINARY 113
#define FCNTL_FS_SPECIFIC_BASE 0x00010000
#define F_DUPFD_CLOEXEC 67
#define FD_CLOEXEC 1
@@ -903,6 +937,7 @@
#define MADV_FREE_REUSE 8
#define MADV_CAN_REUSE 9
#define MADV_PAGEOUT 10
#define MADV_ZERO 11
#define MINCORE_INCORE 0x1
#define MINCORE_REFERENCED 0x2
#define MINCORE_MODIFIED 0x4
@@ -1110,6 +1145,9 @@
#define DBG_MACH_IHDLR 0x10
#define DBG_MACH_IPC 0x20
#define DBG_MACH_RESOURCE 0x25
#define DBG_MACH_EXCLAVES 0x2A
#define DBG_MACH_EXCLAVES_SCHEDULER 0x2B
#define DBG_MACH_EPOCH_SYNC 0x2C
#define DBG_MACH_VM 0x30
#define DBG_MACH_LEAKS 0x31
#define DBG_MACH_WORKINGSET 0x32
@@ -1135,6 +1173,7 @@
#define DBG_MACH_KCOV 0xAD
#define DBG_MACH_MACHDEP_EXCP_SC_x86 0xAE
#define DBG_MACH_MACHDEP_EXCP_SC_ARM 0xAF
#define DBG_MACH_VM_RECLAIM 0xB0
#define DBC_MACH_IO_MMIO_READ 0x1
#define DBC_MACH_IO_MMIO_WRITE 0x2
#define DBC_MACH_IO_PHYS_READ 0x3
@@ -1176,7 +1215,6 @@
#define MACH_SCHED_MAINTENANCE 0x1f
#define MACH_DISPATCH 0x20
#define MACH_QUANTUM_HANDOFF 0x21
#define MACH_MULTIQ_DEQUEUE 0x22
#define MACH_SCHED_THREAD_SWITCH 0x23
#define MACH_SCHED_SMT_BALANCE 0x24
#define MACH_REMOTE_DEFERRED_AST 0x25
@@ -1228,6 +1266,7 @@
#define MACH_SCHED_WI_EXTERNAL_WAKEUP 0x61
#define MACH_SCHED_AST_CHECK 0x62
#define MACH_SCHED_PREEMPT_TIMER_ACTIVE 0x63
#define MACH_PROCESSOR_SHUTDOWN 0x64
#define MACH_SCHED_CLUTCH_ROOT_BUCKET_STATE 0x0
#define MACH_SCHED_CLUTCH_TG_BUCKET_STATE 0x1
#define MACH_SCHED_CLUTCH_THREAD_SELECT 0x2
@@ -1253,20 +1292,83 @@
#define WORKGROUP_INTERVAL_SET_WORKLOAD_ID_NAME 0x7
#define KCOV_STKSZ_THRESHOLD_ABOVE 0x0
#define KCOV_STKSZ_THRESHOLD_BELOW 0x1
#define MACH_MULTIQ_BOUND 1
#define MACH_MULTIQ_GROUP 2
#define MACH_MULTIQ_GLOBAL 3
#define DBG_ZERO_FILL_FAULT 1
#define DBG_PAGEIN_FAULT 2
#define DBG_COW_FAULT 3
#define DBG_CACHE_HIT_FAULT 4
#define DBG_NZF_PAGE_FAULT 5
#define DBG_GUARD_FAULT 6
#define DBG_PAGEINV_FAULT 7
#define DBG_PAGEIND_FAULT 8
#define DBG_COMPRESSOR_FAULT 9
#define DBG_COMPRESSOR_SWAPIN_FAULT 10
#define DBG_COR_FAULT 11
#define DBG_VM_VNODE_PAGEOUT 0x001
#define DBG_VM_FAULT_INTERNAL 0x002
#define DBG_VM_PURGEABLE_TOKEN_ADD 0x040
#define DBG_VM_PURGEABLE_TOKEN_DELETE 0x041
#define DBG_VM_PURGEABLE_TOKEN_RIPEN 0x042
#define DBG_VM_PURGEABLE_OBJECT_ADD 0x048
#define DBG_VM_PURGEABLE_OBJECT_REMOVE 0x049
#define DBG_VM_PURGEABLE_OBJECT_PURGE 0x04a
#define DBG_VM_PURGEABLE_OBJECT_PURGE_ALL 0x04b
#define DBG_VM_PURGEABLE_OBJECT_PURGE_ONE 0x04c
#define DBG_VM_PURGEABLE_OBJECT_PURGE_LOOP 0x04e
#define DBG_VM_MAP_PARTIAL_REAP 0x054
#define DBG_VM_MAP_WILLNEED 0x055
#define DBG_VM_FAULT_CHECK_ZFDELAY 0x100
#define DBG_VM_FAULT_COWDELAY 0x101
#define DBG_VM_FAULT_ZFDELAY 0x102
#define DBG_VM_FAULT_COMPRESSORDELAY 0x103
#define DBG_VM_PAGEOUT_SCAN 0x104
#define DBG_VM_PAGEOUT_BALANCE 0x105
#define DBG_VM_PAGEOUT_FREELIST 0x106
#define DBG_VM_PAGEOUT_PURGEONE 0x107
#define DBG_VM_PAGEOUT_CACHE_EVICT 0x108
#define DBG_VM_PAGEOUT_THREAD_BLOCK 0x109
#define DBG_VM_PAGEOUT_JETSAM 0x10A
#define DBG_VM_INFO1 0x10B
#define DBG_VM_INFO2 0x10C
#define DBG_VM_INFO3 0x10D
#define DBG_VM_INFO4 0x10E
#define DBG_VM_INFO5 0x10F
#define DBG_VM_INFO6 0x110
#define DBG_VM_INFO7 0x111
#define DBG_VM_INFO8 0x112
#define DBG_VM_INFO9 0x113
#define DBG_VM_INFO10 0x114
#define DBG_VM_UPL_PAGE_WAIT 0x120
#define DBG_VM_IOPL_PAGE_WAIT 0x121
#define DBG_VM_PAGE_WAIT_BLOCK 0x122
#define DBG_VM_PAGE_SLEEP 0x123
#define DBG_VM_PAGE_EXPEDITE 0x124
#define DBG_VM_PAGE_EXPEDITE_NO_MEMORY 0x125
#define DBG_VM_PAGE_GRAB 0x126
#define DBG_VM_PAGE_RELEASE 0x127
#define DBG_VM_COMPRESSOR_COMPACT_AND_SWAP 0x128
#define DBG_VM_COMPRESSOR_DELAYED_COMPACT 0x129
#define DBG_VM_OBJECT_SLEEP 0x12a
#define DBG_VM_PAGE_WAKEUP 0x12b
#define DBG_VM_PAGE_WAKEUP_DONE 0x12c
#define DBG_VM_PRESSURE_EVENT 0x130
#define DBG_VM_EXECVE 0x131
#define DBG_VM_WAKEUP_COMPACTOR_SWAPPER 0x132
#define DBG_VM_UPL_REQUEST 0x133
#define DBG_VM_IOPL_REQUEST 0x134
#define DBG_VM_KERN_REQUEST 0x135
#define DBG_VM_DATA_WRITE 0x140
#define DBG_VM_PRESSURE_LEVEL_CHANGE 0x141
#define DBG_VM_PHYS_WRITE_ACCT 0x142
#define DBG_VM_MAP_LOOKUP_ENTRY_FAILURE 0x143
#define VM_DISCONNECT_ALL_PAGE_MAPPINGS 0x00
#define VM_DISCONNECT_TASK_PAGE_MAPPINGS 0x01
#define VM_REAL_FAULT_ADDR_INTERNAL 0x02
#define VM_REAL_FAULT_ADDR_PURGABLE 0x03
#define VM_REAL_FAULT_ADDR_EXTERNAL 0x04
#define VM_REAL_FAULT_ADDR_SHAREDCACHE 0x05
#define VM_REAL_FAULT_FAST 0x06
#define VM_REAL_FAULT_SLOW 0x07
#define VM_MAP_LOOKUP_OBJECT 0x08
#define DBG_ZERO_FILL_FAULT 0x01
#define DBG_PAGEIN_FAULT 0x02
#define DBG_COW_FAULT 0x03
#define DBG_CACHE_HIT_FAULT 0x04
#define DBG_NZF_PAGE_FAULT 0x05
#define DBG_GUARD_FAULT 0x06
#define DBG_PAGEINV_FAULT 0x07
#define DBG_PAGEIND_FAULT 0x08
#define DBG_COMPRESSOR_FAULT 0x09
#define DBG_COMPRESSOR_SWAPIN_FAULT 0x0a
#define DBG_COR_FAULT 0x0b
#define MACH_TASK_SUSPEND 0x0
#define MACH_TASK_RESUME 0x1
#define MACH_THREAD_SET_VOUCHER 0x2
@@ -1281,6 +1383,31 @@
#define MACH_IPC_KMSG_LINK 0xb
#define MACH_IPC_PORT_ENTRY_MODIFY 0xc
#define MACH_IPC_DESTROY_GUARDED_DESC 0xd
#define MACH_THREAD_SUSPEND 0xe
#define MACH_THREAD_RESUME 0xf
#define MACH_EXCLAVES_SWITCH 0x0
#define MACH_EXCLAVES_XNUPROXY 0x1
#define MACH_EXCLAVES_RPC 0x2
#define MACH_EXCLAVES_UPCALL 0x3
#define MACH_EXCLAVES_BOOT_TASK 0x4
#define MACH_EXCLAVES_SCHEDULER_YIELD 0x0
#define MACH_EXCLAVES_SCHEDULER_SPAWNED 0x1
#define MACH_EXCLAVES_SCHEDULER_TERMINATED 0x2
#define MACH_EXCLAVES_SCHEDULER_WAIT 0x3
#define MACH_EXCLAVES_SCHEDULER_WAKE 0x4
#define MACH_EXCLAVES_SCHEDULER_SUSPENDED 0x5
#define MACH_EXCLAVES_SCHEDULER_RESUMED 0x6
#define MACH_EXCLAVES_SCHEDULER_INTERRUPTED 0x7
#define MACH_EXCLAVES_SCHEDULER_NOTHING_SCHEDULED 0x8
#define MACH_EXCLAVES_SCHEDULER_ALL_EXCLAVES_BOOTED 0x9
#define MACH_EXCLAVES_SCHEDULER_EARLY_ALLOC 0xa
#define MACH_EPOCH_SYNC_WAIT_STALE 0x0
#define MACH_EPOCH_SYNC_WAIT 0x1
#define MACH_EPOCH_SYNC_WAKE_NO_WAITERS 0x2
#define MACH_EPOCH_SYNC_WAKE_ONE 0x3
#define MACH_EPOCH_SYNC_WAKE_ALL 0x4
#define MACH_EPOCH_SYNC_WAKE_ONE_WITH_OWNER 0x5
#define MACH_EPOCH_SYNC_WAKE_THREAD 0x6
#define MACH_THREAD_GROUP_NEW 0x0
#define MACH_THREAD_GROUP_FREE 0x1
#define MACH_THREAD_GROUP_SET 0x2
@@ -1423,6 +1550,13 @@
#define HV_X86_VM_PROTECT_TRAP 0x2b
#define HV_X86_VM_UNMAP_TRAP 0x2c
#define HV_X86_TSC_OFFSET_SET 0x2d
#define VM_RECLAIM_UPDATE_ACCOUNTING 0x01
#define VM_RECLAIM_ENTRIES 0x02
#define VM_RECLAIM_CHUNK 0x03
#define VM_RECLAIM_ENTRY 0x04
#define VM_RECLAIM_ALL_MEMORY 0x05
#define VM_RECLAIM_ASYNC_MEMORY 0x06
#define VM_RECLAIM_INIT 0x07
#define DBG_NETIP 1
#define DBG_NETARP 2
#define DBG_NETUDP 3
@@ -2108,6 +2242,7 @@
#define XATTR_NOSECURITY 0x0008
#define XATTR_NODEFAULT 0x0010
#define XATTR_SHOWCOMPRESSION 0x0020
#define XATTR_NOFOLLOW_ANY 0x0040
#define XATTR_MAXNAMELEN 127
#define PR_SLOWHZ 2
#define PRC_IFDOWN 0
@@ -2141,6 +2276,7 @@
#define CTL_FLAG_REG_SOCK_STREAM 0x4
#define CTL_DATA_NOWAKEUP 0x1
#define CTL_DATA_EOR 0x2
#define __has_safe_buffers 0
#define __DARWIN_ONLY_64_BIT_INO_T 0
#define __DARWIN_ONLY_UNIX_CONFORMANCE 0
#define __DARWIN_ONLY_VERS_1050 0
@@ -2478,7 +2614,8 @@
#define VQ_NEARLOWDISK 0x2000
#define VQ_DESIRED_DISK 0x4000
#define VQ_FREE_SPACE_CHANGE 0x8000
#define VQ_FLAG10000 0x10000
#define VQ_PURGEABLE_SPACE_CHANGE 0x10000
#define VQ_FLAG20000 0x20000
#define VFS_IOATTR_FLAGS_FUA 0x00000001
#define VFS_IOATTR_FLAGS_UNMAP 0x00000002
#define VFS_IOATTR_FLAGS_SWAPPIN_SUPPORTED 0x00000010
@@ -2509,7 +2646,7 @@
#define NFSV4_MAX_FH_SIZE 128
#define NFSV3_MAX_FH_SIZE 64
#define NFSV2_MAX_FH_SIZE 32
#define CRYPTEX_AUTH_STRUCT_VERSION 1
#define CRYPTEX_AUTH_STRUCT_VERSION 2
#define EV_FD 1
#define EV_RE 1
#define EV_WR 2
@@ -2533,6 +2670,10 @@
#define KDEBUG_LEVEL_FULL 3
#define KDBG_FLAG_FILTERED 0x01
#define KDBG_FLAG_NOPROCFILT 0x02
#define __DARWIN_LITTLE_ENDIAN 1234
#define __DARWIN_BIG_ENDIAN 4321
#define __DARWIN_PDP_ENDIAN 3412
#define USE_CLANG_TYPES 0
#define __DARWIN_NULL 0
#define UBC_PUSHDIRTY 0x01
#define UBC_PUSHALL 0x02
@@ -3068,7 +3209,9 @@
#define SYS_mkfifoat 553 + 0x2000000
#define SYS_mknodat 554 + 0x2000000
#define SYS_ungraftdmg 555 + 0x2000000
#define SYS_MAXSYSCALL 556 + 0x2000000
#define SYS_coalition_policy_set 556 + 0x2000000
#define SYS_coalition_policy_get 557 + 0x2000000
#define SYS_MAXSYSCALL 558 + 0x2000000
#define SYS_invalid 63 + 0x2000000
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
@@ -3116,6 +3259,7 @@
#define SO_NET_SERVICE_TYPE 0x1116
#define SO_NETSVC_MARKING_LEVEL 0x1119
#define SO_RESOLVER_SIGNATURE 0x1131
#define SO_BINDTODEVICE 0x1134
#define NET_SERVICE_TYPE_BE 0
#define NET_SERVICE_TYPE_BK 1
#define NET_SERVICE_TYPE_SIG 2
@@ -0,0 +1,304 @@
#define __NR_io_setup 0
#define __NR_io_destroy 1
#define __NR_io_submit 2
#define __NR_io_cancel 3
#define __NR_io_getevents 4
#define __NR_setxattr 5
#define __NR_lsetxattr 6
#define __NR_fsetxattr 7
#define __NR_getxattr 8
#define __NR_lgetxattr 9
#define __NR_fgetxattr 10
#define __NR_listxattr 11
#define __NR_llistxattr 12
#define __NR_flistxattr 13
#define __NR_removexattr 14
#define __NR_lremovexattr 15
#define __NR_fremovexattr 16
#define __NR_getcwd 17
#define __NR_lookup_dcookie 18
#define __NR_eventfd2 19
#define __NR_epoll_create1 20
#define __NR_epoll_ctl 21
#define __NR_epoll_pwait 22
#define __NR_dup 23
#define __NR_dup3 24
#define __NR_fcntl 25
#define __NR_inotify_init1 26
#define __NR_inotify_add_watch 27
#define __NR_inotify_rm_watch 28
#define __NR_ioctl 29
#define __NR_ioprio_set 30
#define __NR_ioprio_get 31
#define __NR_flock 32
#define __NR_mknodat 33
#define __NR_mkdirat 34
#define __NR_unlinkat 35
#define __NR_symlinkat 36
#define __NR_linkat 37
#define __NR_umount2 39
#define __NR_mount 40
#define __NR_pivot_root 41
#define __NR_nfsservctl 42
#define __NR_statfs 43
#define __NR_fstatfs 44
#define __NR_truncate 45
#define __NR_ftruncate 46
#define __NR_fallocate 47
#define __NR_faccessat 48
#define __NR_chdir 49
#define __NR_fchdir 50
#define __NR_chroot 51
#define __NR_fchmod 52
#define __NR_fchmodat 53
#define __NR_fchownat 54
#define __NR_fchown 55
#define __NR_openat 56
#define __NR_close 57
#define __NR_vhangup 58
#define __NR_pipe2 59
#define __NR_quotactl 60
#define __NR_getdents64 61
#define __NR_lseek 62
#define __NR_read 63
#define __NR_write 64
#define __NR_readv 65
#define __NR_writev 66
#define __NR_pread64 67
#define __NR_pwrite64 68
#define __NR_preadv 69
#define __NR_pwritev 70
#define __NR_sendfile 71
#define __NR_pselect6 72
#define __NR_ppoll 73
#define __NR_signalfd4 74
#define __NR_vmsplice 75
#define __NR_splice 76
#define __NR_tee 77
#define __NR_readlinkat 78
#define __NR_newfstatat 79
#define __NR_fstat 80
#define __NR_sync 81
#define __NR_fsync 82
#define __NR_fdatasync 83
#define __NR_sync_file_range 84
#define __NR_timerfd_create 85
#define __NR_timerfd_settime 86
#define __NR_timerfd_gettime 87
#define __NR_utimensat 88
#define __NR_acct 89
#define __NR_capget 90
#define __NR_capset 91
#define __NR_personality 92
#define __NR_exit 93
#define __NR_exit_group 94
#define __NR_waitid 95
#define __NR_set_tid_address 96
#define __NR_unshare 97
#define __NR_futex 98
#define __NR_set_robust_list 99
#define __NR_get_robust_list 100
#define __NR_nanosleep 101
#define __NR_getitimer 102
#define __NR_setitimer 103
#define __NR_kexec_load 104
#define __NR_init_module 105
#define __NR_delete_module 106
#define __NR_timer_create 107
#define __NR_timer_gettime 108
#define __NR_timer_getoverrun 109
#define __NR_timer_settime 110
#define __NR_timer_delete 111
#define __NR_clock_settime 112
#define __NR_clock_gettime 113
#define __NR_clock_getres 114
#define __NR_clock_nanosleep 115
#define __NR_syslog 116
#define __NR_ptrace 117
#define __NR_sched_setparam 118
#define __NR_sched_setscheduler 119
#define __NR_sched_getscheduler 120
#define __NR_sched_getparam 121
#define __NR_sched_setaffinity 122
#define __NR_sched_getaffinity 123
#define __NR_sched_yield 124
#define __NR_sched_get_priority_max 125
#define __NR_sched_get_priority_min 126
#define __NR_sched_rr_get_interval 127
#define __NR_restart_syscall 128
#define __NR_kill 129
#define __NR_tkill 130
#define __NR_tgkill 131
#define __NR_sigaltstack 132
#define __NR_rt_sigsuspend 133
#define __NR_rt_sigaction 134
#define __NR_rt_sigprocmask 135
#define __NR_rt_sigpending 136
#define __NR_rt_sigtimedwait 137
#define __NR_rt_sigqueueinfo 138
#define __NR_rt_sigreturn 139
#define __NR_setpriority 140
#define __NR_getpriority 141
#define __NR_reboot 142
#define __NR_setregid 143
#define __NR_setgid 144
#define __NR_setreuid 145
#define __NR_setuid 146
#define __NR_setresuid 147
#define __NR_getresuid 148
#define __NR_setresgid 149
#define __NR_getresgid 150
#define __NR_setfsuid 151
#define __NR_setfsgid 152
#define __NR_times 153
#define __NR_setpgid 154
#define __NR_getpgid 155
#define __NR_getsid 156
#define __NR_setsid 157
#define __NR_getgroups 158
#define __NR_setgroups 159
#define __NR_uname 160
#define __NR_sethostname 161
#define __NR_setdomainname 162
#define __NR_getrlimit 163
#define __NR_setrlimit 164
#define __NR_getrusage 165
#define __NR_umask 166
#define __NR_prctl 167
#define __NR_getcpu 168
#define __NR_gettimeofday 169
#define __NR_settimeofday 170
#define __NR_adjtimex 171
#define __NR_getpid 172
#define __NR_getppid 173
#define __NR_getuid 174
#define __NR_geteuid 175
#define __NR_getgid 176
#define __NR_getegid 177
#define __NR_gettid 178
#define __NR_sysinfo 179
#define __NR_mq_open 180
#define __NR_mq_unlink 181
#define __NR_mq_timedsend 182
#define __NR_mq_timedreceive 183
#define __NR_mq_notify 184
#define __NR_mq_getsetattr 185
#define __NR_msgget 186
#define __NR_msgctl 187
#define __NR_msgrcv 188
#define __NR_msgsnd 189
#define __NR_semget 190
#define __NR_semctl 191
#define __NR_semtimedop 192
#define __NR_semop 193
#define __NR_shmget 194
#define __NR_shmctl 195
#define __NR_shmat 196
#define __NR_shmdt 197
#define __NR_socket 198
#define __NR_socketpair 199
#define __NR_bind 200
#define __NR_listen 201
#define __NR_accept 202
#define __NR_connect 203
#define __NR_getsockname 204
#define __NR_getpeername 205
#define __NR_sendto 206
#define __NR_recvfrom 207
#define __NR_setsockopt 208
#define __NR_getsockopt 209
#define __NR_shutdown 210
#define __NR_sendmsg 211
#define __NR_recvmsg 212
#define __NR_readahead 213
#define __NR_brk 214
#define __NR_munmap 215
#define __NR_mremap 216
#define __NR_add_key 217
#define __NR_request_key 218
#define __NR_keyctl 219
#define __NR_clone 220
#define __NR_execve 221
#define __NR_mmap 222
#define __NR_fadvise64 223
#define __NR_swapon 224
#define __NR_swapoff 225
#define __NR_mprotect 226
#define __NR_msync 227
#define __NR_mlock 228
#define __NR_munlock 229
#define __NR_mlockall 230
#define __NR_munlockall 231
#define __NR_mincore 232
#define __NR_madvise 233
#define __NR_remap_file_pages 234
#define __NR_mbind 235
#define __NR_get_mempolicy 236
#define __NR_set_mempolicy 237
#define __NR_migrate_pages 238
#define __NR_move_pages 239
#define __NR_rt_tgsigqueueinfo 240
#define __NR_perf_event_open 241
#define __NR_accept4 242
#define __NR_recvmmsg 243
#define __NR_arch_specific_syscall 244
#define __NR_wait4 260
#define __NR_prlimit64 261
#define __NR_fanotify_init 262
#define __NR_fanotify_mark 263
#define __NR_name_to_handle_at 264
#define __NR_open_by_handle_at 265
#define __NR_clock_adjtime 266
#define __NR_syncfs 267
#define __NR_setns 268
#define __NR_sendmmsg 269
#define __NR_process_vm_readv 270
#define __NR_process_vm_writev 271
#define __NR_kcmp 272
#define __NR_finit_module 273
#define __NR_sched_setattr 274
#define __NR_sched_getattr 275
#define __NR_renameat2 276
#define __NR_seccomp 277
#define __NR_getrandom 278
#define __NR_memfd_create 279
#define __NR_bpf 280
#define __NR_execveat 281
#define __NR_userfaultfd 282
#define __NR_membarrier 283
#define __NR_mlock2 284
#define __NR_copy_file_range 285
#define __NR_preadv2 286
#define __NR_pwritev2 287
#define __NR_pkey_mprotect 288
#define __NR_pkey_alloc 289
#define __NR_pkey_free 290
#define __NR_statx 291
#define __NR_io_pgetevents 292
#define __NR_rseq 293
#define __NR_kexec_file_load 294
#define __NR_pidfd_send_signal 424
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
#define __NR_open_tree 428
#define __NR_move_mount 429
#define __NR_fsopen 430
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define __NR_pidfd_open 434
#define __NR_clone3 435
#define __NR_close_range 436
#define __NR_openat2 437
#define __NR_pidfd_getfd 438
#define __NR_faccessat2 439
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
#define __NR_sysriscv __NR_arch_specific_syscall
#define __NR_riscv_flush_icache (__NR_sysriscv + 15)
@@ -0,0 +1,4 @@
// https://git.musl-libc.org/cgit/musl/plain/arch/riscv64/bits/syscall.h.in
#define __riscv64__
#include <riscv64/syscalls.h>
#include <common.h>
@@ -44,6 +44,7 @@
#define SYS_clone2 __NR_clone2
#define SYS_clone3 __NR_clone3
#define SYS_close __NR_close
#define SYS_close_range __NR_close_range
#define SYS_connect __NR_connect
#define SYS_copy_file_range __NR_copy_file_range
#define SYS_creat __NR_creat
@@ -58,6 +59,7 @@
#define SYS_epoll_ctl __NR_epoll_ctl
#define SYS_epoll_ctl_old __NR_epoll_ctl_old
#define SYS_epoll_pwait __NR_epoll_pwait
#define SYS_epoll_pwait2 __NR_epoll_pwait2
#define SYS_epoll_wait __NR_epoll_wait
#define SYS_epoll_wait_old __NR_epoll_wait_old
#define SYS_eventfd __NR_eventfd
@@ -69,6 +71,7 @@
#define SYS_exit __NR_exit
#define SYS_exit_group __NR_exit_group
#define SYS_faccessat __NR_faccessat
#define SYS_faccessat2 __NR_faccessat2
#define SYS_fadvise64 __NR_fadvise64
#define SYS_fadvise64_64 __NR_fadvise64_64
#define SYS_fallocate __NR_fallocate
@@ -191,6 +194,9 @@
#define SYS_kexec_load __NR_kexec_load
#define SYS_keyctl __NR_keyctl
#define SYS_kill __NR_kill
#define SYS_landlock_add_rule __NR_landlock_add_rule
#define SYS_landlock_create_ruleset __NR_landlock_create_ruleset
#define SYS_landlock_restrict_self __NR_landlock_restrict_self
#define SYS_lchown __NR_lchown
#define SYS_lchown32 __NR_lchown32
#define SYS_lgetxattr __NR_lgetxattr
@@ -228,6 +234,7 @@
#define SYS_mmap2 __NR_mmap2
#define SYS_modify_ldt __NR_modify_ldt
#define SYS_mount __NR_mount
#define SYS_mount_setattr __NR_mount_setattr
#define SYS_move_mount __NR_move_mount
#define SYS_move_pages __NR_move_pages
#define SYS_mprotect __NR_mprotect
@@ -402,6 +409,7 @@
#define SYS_preadv __NR_preadv
#define SYS_preadv2 __NR_preadv2
#define SYS_prlimit64 __NR_prlimit64
#define SYS_process_madvise __NR_process_madvise
#define SYS_process_vm_readv __NR_process_vm_readv
#define SYS_process_vm_writev __NR_process_vm_writev
#define SYS_prof __NR_prof
@@ -440,6 +448,7 @@
#define SYS_reserved221 __NR_reserved221
#define SYS_reserved82 __NR_reserved82
#define SYS_restart_syscall __NR_restart_syscall
#define SYS_riscv_flush_icache __NR_riscv_flush_icache
#define SYS_rmdir __NR_rmdir
#define SYS_rseq __NR_rseq
#define SYS_rtas __NR_rtas
@@ -572,6 +581,7 @@
#define SYS_sys_kexec_load __NR_sys_kexec_load
#define SYS_syslog __NR_syslog
#define SYS_sysmips __NR_sysmips
#define SYS_sysriscv __NR_sysriscv
#define SYS_sys_setaltroot __NR_sys_setaltroot
#define SYS_tee __NR_tee
#define SYS_tgkill __NR_tgkill
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -8,6 +8,6 @@ functions.py:
wget https://raw.githubusercontent.com/zachriggle/functions/master/functions.py
generate_darwin:
python generate_darwin.py "$(ROOT)"
python3 generate_darwin.py "$(ROOT)"
.phony: all
+3 -3
View File
@@ -1,16 +1,16 @@
# ./pwnlib/data/includes/darwin/aarch64.h
# ./pwnlib/constants/darwin/aarch64.py
# https://github.com/nullgemm/instant_macos_sdk (old sdk here, please use real macos device)
# https://github.com/joseluisq/macosx-sdks (old sdk here, please use real macos device)
# /Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/sys/
from pathlib import Path
import re
import sys
# In the future, you should change the version of `MacOSX14.sdk`
sdk_path = Path('/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/sys/')
# In the future, you should change the version of `MacOSX15.sdk`
sdk_path = Path('/Library/Developer/CommandLineTools/SDKs/MacOSX15.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/sys/')
if not sdk_path.exists():
print('missing MacOSX sdk')
exit(1)
+1 -1
View File
@@ -652,7 +652,7 @@ class DynELF(object):
break
if name:
self.status('Skipping %s' % name)
self.status('Skipping %r' % name)
cur = leak.field(cur, LinkMap.l_next)
else:
+25 -5
View File
@@ -238,8 +238,8 @@ class Corefile(ELF):
Registers can be accessed directly, e.g. via ``core_obj.eax`` and enumerated
via :data:`Corefile.registers`.
Memory can be accessed directly via :meth:`.read` or :meth:`.write`, and also
via :meth:`.pack` or :meth:`.unpack` or even :meth:`.string`.
Memory can be accessed directly via :meth:`pwnlib.elf.elf.ELF.read` or :meth:`pwnlib.elf.elf.ELF.write`, and also
via :meth:`pwnlib.elf.elf.ELF.pack` or :meth:`pwnlib.elf.elf.ELF.unpack` or even :meth:`.string`.
Arguments:
core: Path to the core file. Alternately, may be a :class:`.process` instance,
@@ -376,8 +376,8 @@ class Corefile(ELF):
>>> core.exe.data[0:4]
b'\x7fELF'
It also supports all of the features of :class:`ELF`, so you can :meth:`.read`
or :meth:`.write` or even the helpers like :meth:`.pack` or :meth:`.unpack`.
It also supports all of the features of :class:`ELF`, so you can :meth:`pwnlib.elf.elf.ELF.read`
or :meth:`pwnlib.elf.elf.ELF.write` or even the helpers like :meth:`pwnlib.elf.elf.ELF.pack` or :meth:`pwnlib.elf.elf.ELF.unpack`.
Don't forget to call :meth:`.ELF.save` to save the changes to disk.
@@ -555,6 +555,9 @@ class Corefile(ELF):
# Pointer to the entry point
self.at_entry = 0
# Pointer to the vdso
self.at_sysinfo_ehdr = None
try:
super(Corefile, self).__init__(*a, **kw)
except IOError:
@@ -611,6 +614,8 @@ class Corefile(ELF):
if not self.stack and self.mappings:
self.stack = self.mappings[-1].stop
if self.mappings[-1].start == 0xffffffffff600000 and len(self.mappings) > 1:
self.stack = self.mappings[-2].stop
if self.stack and self.mappings:
for mapping in self.mappings:
@@ -1329,6 +1334,10 @@ class CorefileFinder(object):
except Exception:
pass
# Convert bytes-like object to string
if isinstance(data, bytes):
data = data.decode('utf-8')
return data
def systemd_coredump_corefile(self):
@@ -1506,7 +1515,18 @@ class CorefileFinder(object):
# should be unique enough that we can just glob.
boot_id = read('/proc/sys/kernel/random/boot_id').strip().decode()
path = self.exe.replace('/', '_')
# Use the absolute path of the executable
# Apport uses the executable's path to determine the core dump filename
#
# Reference source:
# https://github.com/canonical/apport/blob/4bbb179b8f92989bf7c1ee3692074f35d70ef3e8/data/apport#L110
# https://github.com/canonical/apport/blob/4bbb179b8f92989bf7c1ee3692074f35d70ef3e8/apport/fileutils.py#L599
#
# Apport calls `get_core_path` with `options.executable_path`, which corresponds to
# the executable's pathname, as specified by the `%E` placeholder
# in the core pattern (see `man core` and `apport --help`).
path = os.path.abspath(self.exe).replace('/', '_').replace('.', '_')
# Format the name
corefile_name = 'core.{path}.{uid}.{boot_id}.{pid}.*'.format(
+135 -86
View File
@@ -52,6 +52,7 @@ from collections import namedtuple, defaultdict
from elftools.elf.constants import P_FLAGS
from elftools.elf.constants import SHN_INDICES
from elftools.elf.descriptions import describe_e_type
from elftools.elf.dynamic import DynamicSection
from elftools.elf.elffile import ELFFile
from elftools.elf.enums import ENUM_GNU_PROPERTY_X86_FEATURE_1_FLAGS
from elftools.elf.gnuversions import GNUVerDefSection
@@ -358,12 +359,21 @@ class ELF(ELFFile):
self._populate_functions()
self._populate_kernel_version()
self._print_checksec = checksec
if checksec:
self._describe()
self._libs = None
self._maps = None
def close(self):
"""close() -> None
Close the ELF file and release all resources associated with it.
"""
super(ELF, self).close()
self.file.close()
@staticmethod
@LocalContext
def from_assembly(assembly, *a, **kw):
@@ -705,29 +715,57 @@ class ELF(ELFFile):
@property
def libs(self):
"""Dictionary of {path: address} for every library loaded for this ELF."""
"""Dictionary of ``{path: address}`` for every library loaded for this ELF.
.. warning::
Getting this attribute actually runs the executable.
Make sure that you trust the binary you are exploiting.
If it adds itself as ``DT_NEEDED``, has overlapping segments,
ambiguous headers, or employs text relocations, it can run arbitrary
code even though you are just inspecting it.
Running is the only reliable way to ensure all the libraries are
loaded from the correct paths, because some of them may change
loading logic.
Exploitability first noticed at CWTE CTF 2025.
"""
if self._libs is None:
self._populate_libraries()
return self._libs
@property
def maps(self):
"""Dictionary of {name: address} for every mapping in this ELF's address space."""
"""Dictionary of ``{name: address}`` for every mapping in this ELF's address space.
.. warning::
Getting this attribute actually runs the executable.
Make sure that you trust the binary you are exploiting
(see :attr:`.ELF.libs`).
"""
if self._maps is None:
self._populate_libraries()
return self._maps
@property
def libc(self):
""":class:`.ELF`: If this :class:`.ELF` imports any libraries which contain ``'libc[.-]``,
""":class:`.ELF`: If this :class:`.ELF` imports any libraries which contain ``/libc[.-]``,
and we can determine the appropriate path to it on the local
system, returns a new :class:`.ELF` object pertaining to that library.
Prints the `checksec` output of the library if it was printed for the original ELF too.
If not found, the value will be :const:`None`.
.. warning::
Getting this attribute actually runs the executable.
Make sure that you trust the binary you are exploiting
(see :attr:`.ELF.libs`).
"""
for lib in self.libs:
if '/libc.' in lib or '/libc-' in lib:
return ELF(lib)
if ('/libc.' in lib or '/libc-' in lib) and lib != self.path:
return ELF(lib, self._print_checksec)
def _populate_libraries(self):
"""
@@ -841,6 +879,13 @@ class ELF(ELFFile):
log.warn_once("Injected /proc/self/maps code did not execute correctly")
return {}
# Sometimes the original binary already fail to run, for example, in case glibc mismatches.
try:
int(data.split('-', 1)[0], 16)
except ValueError:
log.warn_once("Cannot execute `%s` to get /proc/self/maps", self.path)
return {}
# Swap in the original ELF name
data = data.replace(path, self.path)
@@ -908,10 +953,9 @@ class ELF(ELFFile):
continue
for symbol in _iter_symbols(section):
value = symbol.entry.st_value
if not value:
if not symbol.name or symbol.entry.st_shndx == 'SHN_UNDEF':
continue
self.symbols[symbol.name] = value
self.symbols[symbol.name] = symbol.entry.st_value
def _populate_synthetic_symbols(self):
"""Adds symbols from the GOT and PLT to the symbols dictionary.
@@ -1597,7 +1641,7 @@ class ELF(ELFFile):
dt = None
dynamic = self.get_section_by_name('.dynamic')
if not dynamic:
if not dynamic or not isinstance(dynamic, DynamicSection):
return None
try:
@@ -1780,131 +1824,136 @@ class ELF(ELFFile):
\\* Hardware limitations are ignored.
If ``READ_IMPLIES_EXEC`` is set, then `all readable pages are executable`__.
.. __: https://github.com/torvalds/linux/blob/v6.3/fs/binfmt_elf.c#L1008-L1009
.. code-block:: c
if (elf_read_implies_exec(loc->elf_ex, executable_stack))
current->personality |= READ_IMPLIES_EXEC;
.. __: https://github.com/torvalds/linux/blob/v6.3/fs/binfmt_elf.c#L1008-L1009
.. code-block:: c
if (elf_read_implies_exec(loc->elf_ex, executable_stack))
current->personality |= READ_IMPLIES_EXEC;
.. [#x86_5.7]
`source <https://github.com/torvalds/linux/blob/v5.7/arch/x86/include/asm/elf.h#L285-L286>`__
.. code-block:: c
.. code-block:: c
#define elf_read_implies_exec(ex, executable_stack) \\
(executable_stack != EXSTACK_DISABLE_X)
#define elf_read_implies_exec(ex, executable_stack) \\
(executable_stack != EXSTACK_DISABLE_X)
.. [#x86_5.8]
`source <https://github.com/torvalds/linux/blob/v5.8/arch/x86/include/asm/elf.h#L305-L306>`__
.. code-block:: c
.. code-block:: c
#define elf_read_implies_exec(ex, executable_stack) \\
(mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
#define elf_read_implies_exec(ex, executable_stack) \\
(mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
`mmap_is_ia32()`__:
.. __: https://github.com/torvalds/linux/blob/v5.8/arch/x86/include/asm/elf.h#L318-L321
.. code-block:: c
`mmap_is_ia32()`__:
/*
* True on X86_32 or when emulating IA32 on X86_64
*/
static inline int mmap_is_ia32(void)
.. __: https://github.com/torvalds/linux/blob/v5.8/arch/x86/include/asm/elf.h#L318-L321
.. code-block:: c
/*
* True on X86_32 or when emulating IA32 on X86_64
*/
static inline int mmap_is_ia32(void)
.. [#arm_5.7]
`source <https://github.com/torvalds/linux/blob/v5.7/arch/arm/kernel/elf.c#L85-L92>`__
.. code-block:: c
.. code-block:: c
int arm_elf_read_implies_exec(int executable_stack)
{
if (executable_stack != EXSTACK_DISABLE_X)
return 1;
if (cpu_architecture() < CPU_ARCH_ARMv6)
return 1;
return 0;
}
int arm_elf_read_implies_exec(int executable_stack)
{
if (executable_stack != EXSTACK_DISABLE_X)
return 1;
if (cpu_architecture() < CPU_ARCH_ARMv6)
return 1;
return 0;
}
.. [#arm_5.8]
`source <https://github.com/torvalds/linux/blob/v5.8/arch/arm/kernel/elf.c#L104-L111>`__
.. code-block:: c
.. code-block:: c
int arm_elf_read_implies_exec(int executable_stack)
{
if (executable_stack == EXSTACK_DEFAULT)
return 1;
if (cpu_architecture() < CPU_ARCH_ARMv6)
return 1;
return 0;
}
int arm_elf_read_implies_exec(int executable_stack)
{
if (executable_stack == EXSTACK_DEFAULT)
return 1;
if (cpu_architecture() < CPU_ARCH_ARMv6)
return 1;
return 0;
}
.. [#mips_5.17]
`source <https://github.com/torvalds/linux/blob/v5.17/arch/mips/kernel/elf.c#L329-L342>`__
.. code-block:: c
.. code-block:: c
int mips_elf_read_implies_exec(void *elf_ex, int exstack)
{
if (exstack != EXSTACK_DISABLE_X) {
/* The binary doesn't request a non-executable stack */
return 1;
}
if (!cpu_has_rixi) {
/* The CPU doesn't support non-executable memory */
return 1;
}
return 0;
int mips_elf_read_implies_exec(void *elf_ex, int exstack)
{
if (exstack != EXSTACK_DISABLE_X) {
/* The binary doesn't request a non-executable stack */
return 1;
}
if (!cpu_has_rixi) {
/* The CPU doesn't support non-executable memory */
return 1;
}
return 0;
}
.. [#mips_5.18]
`source <https://github.com/torvalds/linux/blob/v5.18/arch/mips/kernel/elf.c#L329-L336>`__
.. code-block:: c
.. code-block:: c
int mips_elf_read_implies_exec(void *elf_ex, int exstack)
{
/*
* Set READ_IMPLIES_EXEC only on non-NX systems that
* do not request a specific state via PT_GNU_STACK.
*/
return (!cpu_has_rixi && exstack == EXSTACK_DEFAULT);
}
int mips_elf_read_implies_exec(void *elf_ex, int exstack)
{
/*
* Set READ_IMPLIES_EXEC only on non-NX systems that
* do not request a specific state via PT_GNU_STACK.
*/
return (!cpu_has_rixi && exstack == EXSTACK_DEFAULT);
}
.. [#powerpc]
`source <https://github.com/torvalds/linux/blob/v6.3/arch/powerpc/include/asm/elf.h#L82-L108>`__
.. code-block:: c
.. code-block:: c
#ifdef __powerpc64__
/* stripped */
# define elf_read_implies_exec(ex, exec_stk) (is_32bit_task() ? \\
(exec_stk == EXSTACK_DEFAULT) : 0)
#else
# define elf_read_implies_exec(ex, exec_stk) (exec_stk == EXSTACK_DEFAULT)
#endif /* __powerpc64__ */
#ifdef __powerpc64__
/* stripped */
# define elf_read_implies_exec(ex, exec_stk) (is_32bit_task() ? \\
(exec_stk == EXSTACK_DEFAULT) : 0)
#else
# define elf_read_implies_exec(ex, exec_stk) (exec_stk == EXSTACK_DEFAULT)
#endif /* __powerpc64__ */
.. [#ia64]
`source <https://github.com/torvalds/linux/blob/v6.3/arch/ia64/include/asm/elf.h#L203-L204>`__
.. code-block:: c
.. code-block:: c
#define elf_read_implies_exec(ex, executable_stack) \\
((executable_stack!=EXSTACK_DISABLE_X) && ((ex).e_flags & EF_IA_64_LINUX_EXECUTABLE_STACK) != 0)
#define elf_read_implies_exec(ex, executable_stack) \\
((executable_stack!=EXSTACK_DISABLE_X) && ((ex).e_flags & EF_IA_64_LINUX_EXECUTABLE_STACK) != 0)
EF_IA_64_LINUX_EXECUTABLE_STACK__:
.. __: https://github.com/torvalds/linux/blob/v6.3/arch/ia64/include/asm/elf.h#L33
EF_IA_64_LINUX_EXECUTABLE_STACK__:
.. code-block:: c
.. __: https://github.com/torvalds/linux/blob/v6.3/arch/ia64/include/asm/elf.h#L33
#define EF_IA_64_LINUX_EXECUTABLE_STACK 0x1 /* is stack (& heap) executable by default? */
.. code-block:: c
#define EF_IA_64_LINUX_EXECUTABLE_STACK 0x1 /* is stack (& heap) executable by default? */
.. [#the_rest]
`source <https://github.com/torvalds/linux/blob/v6.3/include/linux/elf.h#L13>`__
.. code-block:: c
.. code-block:: c
# define elf_read_implies_exec(ex, have_pt_gnu_stack) 0
# define elf_read_implies_exec(ex, have_pt_gnu_stack) 0
"""
if not self.executable:
return True
@@ -2074,7 +2123,7 @@ class ELF(ELFFile):
"NX:".ljust(12) + {
True: green("NX enabled"),
False: red("NX disabled"),
None: yellow("NX unknown - GNU_STACK missing"),
None: yellow("NX enabled on new kernels"),
}[self.nx],
"PIE:".ljust(12) + {
True: green("PIE enabled"),
@@ -2340,7 +2389,7 @@ class ELF(ELFFile):
@staticmethod
def set_runpath(exepath, runpath):
r"""set_runpath(str, str) -> ELF
r"""set_runpath(exepath, runpath) -> ELF
Patches the RUNPATH of the ELF to the given path using the `patchelf utility <https://github.com/NixOS/patchelf>`_.
@@ -2375,7 +2424,7 @@ class ELF(ELFFile):
@staticmethod
def set_interpreter(exepath, interpreter_path):
r"""set_interpreter(str, str) -> ELF
r"""set_interpreter(exepath, interpreter_path) -> ELF
Patches the interpreter of the ELF to the given binary using the `patchelf utility <https://github.com/NixOS/patchelf>`_.
@@ -2409,7 +2458,7 @@ class ELF(ELFFile):
@staticmethod
def patch_custom_libraries(exe_path, custom_library_path, create_copy=True, suffix='_remotelibc'):
r"""patch_custom_libraries(str, str, bool, str) -> ELF
r"""patch_custom_libraries(exe_path, custom_library_path, create_copy=True, suffix='_remotelibc') -> ELF
Looks for the interpreter binary in the given path and patches the binary to use
it if available. Also patches the RUNPATH to the given path using the `patchelf utility <https://github.com/NixOS/patchelf>`_.
+13 -3
View File
@@ -65,16 +65,26 @@ def __ensure_memory_to_run_unicorn():
from mmap import mmap, MAP_ANON, MAP_PRIVATE, PROT_EXEC, PROT_READ, PROT_WRITE
mm = mmap(
-1, 1024 * 1024 * 1024, MAP_PRIVATE | MAP_ANON, PROT_WRITE | PROT_READ | PROT_EXEC
-1, 1024 * 1024 * 1024, MAP_PRIVATE | MAP_ANON, PROT_WRITE | PROT_READ
)
mm.close()
except OSError:
raise OSError("Cannot allocate 1GB memory to run Unicorn Engine")
except ImportError:
# Can only mmap files on Windows, would need to use VirtualAlloc.
pass
def prepare_unicorn_and_context(elf, got, address, data):
import unicorn as U
if elf.arch in ('mips', 'mips64'):
# Unicorn 2.1.3 and 2.1.4 have a crashing bug when trying to emulate MIPS.
# https://github.com/unicorn-engine/unicorn/issues/2134
if U.UC_VERSION_MAJOR == 2 and U.UC_VERSION_MINOR == 1 and U.UC_VERSION_PATCH in (3, 4):
raise OSError("Unicorn Engine 2.1.3 and 2.1.4 have a crashing bug when emulating MIPS, please install an earlier or later version: https://github.com/unicorn-engine/unicorn/issues/2134")
__ensure_memory_to_run_unicorn()
# Instantiate the emulator with the correct arguments for the current
@@ -166,8 +176,8 @@ def emulate_plt_instructions_inner(uc, elf, got, pc, data):
return False
hooks = [
uc.hook_add(U.UC_HOOK_MEM_READ | U.UC_HOOK_MEM_READ_UNMAPPED,
hook_mem, stopped_addr),
uc.hook_add(U.UC_HOOK_MEM_READ, hook_mem, stopped_addr),
uc.hook_add(U.UC_HOOK_MEM_READ_UNMAPPED, hook_mem, stopped_addr),
]
# callback for tracing instructions
+4 -4
View File
@@ -132,7 +132,7 @@ class AsciiShellcodeEncoder(Encoder):
Examples:
>>> context.update(arch='i386', os='linux')
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
>>> encoders.i386.ascii_shellcode.encode._get_allocator(300, vocab)
bytearray(b'TX-!!!!-!_``-t~~~P\\%!!!!%@@@@')
"""
@@ -178,7 +178,7 @@ class AsciiShellcodeEncoder(Encoder):
Examples:
>>> context.update(arch='i386', os='linux')
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
>>> a, b = encoders.i386.ascii_shellcode.encode._find_negatives(vocab)
>>> a & b
0
@@ -212,7 +212,7 @@ class AsciiShellcodeEncoder(Encoder):
>>> context.update(arch='i386', os='linux')
>>> sc = bytearray(b'ABCDEFGHIGKLMNOPQRSTUVXYZ')
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
>>> encoders.i386.ascii_shellcode.encode._get_subtractions(sc, vocab)
bytearray(b'-(!!!-~NNNP-!=;:-f~~~-~~~~P-!!!!-edee-~~~~P-!!!!-eddd-~~~~P-!!!!-egdd-~~~~P-!!!!-eadd-~~~~P-!!!!-eddd-~~~~P')
"""
@@ -255,7 +255,7 @@ class AsciiShellcodeEncoder(Encoder):
Examples:
>>> context.update(arch='i386', os='linux')
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
>>> print(encoders.i386.ascii_shellcode.encode._calc_subtractions(bytearray(b'\x10'*4), bytearray(b'\x11'*4), vocab))
[bytearray(b'!!!!'), bytearray(b'`___'), bytearray(b'~~~~')]
>>> print(encoders.i386.ascii_shellcode.encode._calc_subtractions(bytearray(b'\x11\x12\x13\x14'), bytearray(b'\x15\x16\x17\x18'), vocab))
+2 -2
View File
@@ -41,7 +41,7 @@ decoders = {
b'\xff\xff\x08\x21', # addi t0,t0,-1
b'\xff\xff\x10\x05', # bltzal t0,14 <next>
b'\x82\x82\x08\x28', # slti t0,zero,-32126
b'\xe2\xff\xfd\x23', # addi sp,ra,-30
b'\xe0\xff\xfd\x23', # addi sp,ra,-32
b'\x27\x58\x60\x01', # nor t3,t3,zero
b'\x21\xc8\xeb\x03', # addu t9,ra,t3
b'\x82\x82\x17\x28', # slti s7,zero,-32126
@@ -72,7 +72,7 @@ decoders = {
b'\x21\x08\xff\xff', # addi t0,t0,-1
b'\x05\x10\xff\xff', # bltzal t0,14 <next>
b'\x28\x08\x82\x82', # slti t0,zero,-32126
b'\x23\xfd\xff\xe2', # addi sp,ra,-30
b'\x23\xfd\xff\xe0', # addi sp,ra,-32
b'\x01\x60\x58\x27', # nor t3,t3,zero
b'\x03\xeb\xc8\x21', # addu t9,ra,t3
b'\x28\x17\x82\x82', # slti s7,zero,-32126
+14 -2
View File
@@ -156,6 +156,18 @@ class FileStructure(object):
_wide_data: 0xdeadbeef
unknown2: 0x0
vtable: 0x0}
Bytes fields are padded to the correct field size.
For example, unknown2 is 56 bytes on i386, so a short value gets
zero-padded to 56, not to context.bytes (4):
>>> context.clear(arch='i386')
>>> fileStr2 = FileStructure(null=0)
>>> fileStr2.vtable = 0x561859f0
>>> old_len = len(bytes(fileStr2))
>>> fileStr2.unknown2 = b'AB'
>>> len(bytes(fileStr2)) == old_len
True
"""
vars_=[]
@@ -186,7 +198,7 @@ class FileStructure(object):
structure = b''
for val in self.vars_:
if isinstance(getattr(self, val), bytes):
structure += getattr(self, val).ljust(context.bytes, b'\x00')
structure += getattr(self, val).ljust(self.length[val], b'\x00')
else:
if self.length[val] > 0:
structure += pack(getattr(self, val), self.length[val]*8)
@@ -215,7 +227,7 @@ class FileStructure(object):
structure = b''
for val in self.vars_:
if isinstance(getattr(self, val), bytes):
structure += getattr(self, val).ljust(context.bytes, b'\x00')
structure += getattr(self, val).ljust(self.length[val], b'\x00')
else:
structure += pack(getattr(self, val), self.length[val]*8)
if val == v:
+15 -1
View File
@@ -841,6 +841,12 @@ def fmtstr_payload(offset, writes, numbwritten=0, write_size='byte', write_size_
The overflows argument is a format-string-length to output-amount tradeoff:
Larger values for ``overflows`` produce shorter format strings that generate more output at runtime.
The writes argument is a dictionary with address/value pairs like ``{addr: value, addr2: value2}``.
If the value is an ``int`` datatype, it will be automatically casted into a bytestring with the length of a ``long`` (8 bytes in 64-bit, 4 bytes in 32-bit).
If a specific number of bytes is intended to be written (such as only a single byte, single short, or single int and not an entire long),
then provide a bytestring like ``b'\x37\x13'`` or ``p16(0x1337)``.
Note that the ``write_size`` argument does not determine **total** bytes written, only the size of each consecutive write.
Arguments:
offset(int): the first formatter's offset you control
writes(dict): dict with addr, value ``{addr: value, addr2: value2}``
@@ -857,6 +863,8 @@ def fmtstr_payload(offset, writes, numbwritten=0, write_size='byte', write_size_
>>> context.clear(arch = 'amd64')
>>> fmtstr_payload(1, {0x0: 0x1337babe}, write_size='int')
b'%322419390c%4$llnaaaabaa\x00\x00\x00\x00\x00\x00\x00\x00'
>>> fmtstr_payload(1, {0x0: p32(0x1337babe)}, write_size='int')
b'%322419390c%3$na\x00\x00\x00\x00\x00\x00\x00\x00'
>>> fmtstr_payload(1, {0x0: 0x1337babe}, write_size='short')
b'%47806c%5$lln%22649c%6$hnaaaabaa\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00'
>>> fmtstr_payload(1, {0x0: 0x1337babe}, write_size='byte')
@@ -872,6 +880,8 @@ def fmtstr_payload(offset, writes, numbwritten=0, write_size='byte', write_size_
b'%19c%12$hhn%36c%13$hhn%131c%14$hhn%4c%15$hhn\x03\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00'
>>> fmtstr_payload(1, {0x0: 0x00000001}, write_size='byte')
b'c%3$naaa\x00\x00\x00\x00'
>>> fmtstr_payload(1, {0x0: b'\x01'}, write_size='byte')
b'c%3$hhna\x00\x00\x00\x00'
>>> fmtstr_payload(1, {0x0: b"\xff\xff\x04\x11\x00\x00\x00\x00"}, write_size='short')
b'%327679c%7$lln%18c%8$hhn\x00\x00\x00\x00\x03\x00\x00\x00'
>>> fmtstr_payload(10, {0x404048 : 0xbadc0ffe, 0x40403c : 0xdeadbeef}, no_dollars=True)
@@ -999,7 +1009,7 @@ class FmtStr(object):
Arguments:
addr(int): the address where you want to write
data(int): the data that you want to write ``addr``
data(int or bytes): the data that you want to write ``addr``
Returns:
None
@@ -1013,6 +1023,10 @@ class FmtStr(object):
>>> f.write(0x08040506, 0x1337babe)
>>> f.execute_writes()
b'%19c%16$hhn%36c%17$hhn%131c%18$hhn%4c%19$hhn\t\x05\x04\x08\x08\x05\x04\x08\x07\x05\x04\x08\x06\x05\x04\x08'
>>> f2 = FmtStr(send_fmt_payload, offset=5)
>>> f2.write(0x08040506, p16(0x1337))
>>> f2.execute_writes()
b'%19c%11$hhn%36c%12$hhnaa\x07\x05\x04\x08\x06\x05\x04\x08'
"""
self.writes[addr] = data
+135 -73
View File
@@ -143,7 +143,6 @@ from __future__ import division
import os
import platform
import psutil
import random
import re
import six
@@ -283,7 +282,7 @@ def _execve_script(argv, executable, env, ssh):
return tmp.name
def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None, python_wrapper_script=None):
def _gdbserver_args(pid=None, path=None, port=0, gdbserver_args=None, args=None, which=None, env=None, python_wrapper_script=None):
"""_gdbserver_args(pid=None, path=None, args=None, which=None, env=None) -> list
Sets up a listening gdbserver, to either connect to the specified
@@ -292,6 +291,8 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None, python
Arguments:
pid(int): Process ID to attach to
path(str): Process to launch
port(int): Port to use for gdbserver, default: random
gdbserver_args(list): List of additional arguments to pass to gdbserver
args(list): List of arguments to provide on the debugger command line
which(callaable): Function to find the path of a binary.
env(dict): Environment variables to pass to the program
@@ -300,6 +301,11 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None, python
Returns:
A list of arguments to invoke gdbserver.
"""
if gdbserver_args is None:
gdbserver_args = list()
elif not isinstance(gdbserver_args, (list, tuple)):
gdbserver_args = [gdbserver_args]
if [pid, path, args].count(None) != 2:
log.error("Must specify exactly one of pid, path, or args")
@@ -323,7 +329,7 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None, python
orig_args = args
gdbserver_args = [gdbserver, '--multi']
gdbserver_args = [gdbserver, '--multi'] + gdbserver_args
if context.aslr:
gdbserver_args += ['--no-disable-randomization']
else:
@@ -346,12 +352,8 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None, python
gdbserver_args += ['--wrapper', python_wrapper_script, '--']
elif env is not None:
gdbserver_args += ['--wrapper', which('env'), '-i'] + env_args + ['--']
# --no-startup-with-shell is required for forking shells like SHELL=/bin/fish
# https://github.com/Gallopsled/pwntools/issues/2377
else:
gdbserver_args += ['--no-startup-with-shell']
gdbserver_args += ['localhost:0']
gdbserver_args += ['localhost:%d' % port]
gdbserver_args += args
return gdbserver_args
@@ -416,7 +418,7 @@ def _get_runner(ssh=None):
else: return tubes.process.process
@LocalContext
def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api=False, **kwargs):
def debug(args, gdbscript=None, gdb_args=None, exe=None, ssh=None, env=None, port=0, gdbserver_args=None, sysroot=None, api=False, **kwargs):
r"""
Launch a GDB server with the specified command line,
and launches GDB to attach to it.
@@ -424,9 +426,12 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api=
Arguments:
args(list): Arguments to the process, similar to :class:`.process`.
gdbscript(str): GDB script to run.
gdb_args(list): List of additional arguments to pass to GDB.
exe(str): Path to the executable on disk
env(dict): Environment to start the binary in
ssh(:class:`.ssh`): Remote ssh session to use to launch the process.
port(int): Gdb port to use, default: random
gdbserver_args(list): List of additional arguments to pass to gdbserver
sysroot(str): Set an alternate system root. The system root is used to
load absolute shared library symbol files. This is useful to instruct
gdb to load a local version of binaries/libraries instead of downloading
@@ -534,35 +539,6 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api=
>>> os.remove("./local-libc.so") # cleanup
Using GDB Python API:
.. doctest::
:skipif: is_python2
Debug a new process
>>> io = gdb.debug(['echo', 'foo'], api=True)
Stop at 'write'
>>> bp = io.gdb.Breakpoint('write', temporary=True)
>>> io.gdb.continue_and_wait()
Dump 'count'
>>> count = io.gdb.parse_and_eval('$rdx')
>>> long = io.gdb.lookup_type('long')
>>> int(count.cast(long))
4
Resume the program
>>> io.gdb.continue_nowait()
>>> io.recvline()
b'foo\n'
>>> io.close()
Using SSH:
You can use :func:`debug` to spawn new processes on remote machines as well,
@@ -602,6 +578,52 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api=
>>> io.recvline()
b'$ \n'
>>> io.close()
Using GDB Python API:
.. doctest::
:skipif: is_python2
Debug a new process
>>> io = gdb.debug(['echo', 'foo'], api=True)
or using ssh
>>> shell = ssh('travis', 'example.pwnme', password='demopass')
>>> ssh_io = gdb.debug(['/bin/echo', 'foo'], ssh=shell, api=True)
Stop at 'write'
>>> bp = io.gdb.Breakpoint('write', temporary=True)
>>> io.gdb.continue_and_wait()
>>> ssh_bp = ssh_io.gdb.Breakpoint('write', temporary=True)
>>> ssh_io.gdb.continue_and_wait()
Dump 'count'
>>> count = io.gdb.parse_and_eval('$rdx')
>>> long = io.gdb.lookup_type('long')
>>> int(count.cast(long))
4
>>> count = ssh_io.gdb.parse_and_eval('$rdx')
>>> long = ssh_io.gdb.lookup_type('long')
>>> int(count.cast(long))
4
Resume the program
>>> io.gdb.continue_nowait()
>>> io.recvline()
b'foo\n'
>>> io.close()
>>> ssh_io.gdb.continue_nowait()
>>> ssh_io.recvline()
b'foo\n'
>>> ssh_io.close()
>>> shell.close()
"""
if isinstance(args, six.integer_types + (tubes.process.process, tubes.ssh.ssh_channel)):
log.error("Use gdb.attach() to debug a running process")
@@ -615,8 +637,8 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api=
which = _get_which(ssh)
gdbscript = gdbscript or ''
if api and runner is not tubes.process.process:
raise ValueError('GDB Python API is supported only for local processes')
if api and runner is not tubes.process.process and not ssh:
raise ValueError('GDB Python API is supported only for local and ssh processes')
args, env = misc.normalize_argv_env(args, env, log)
if env:
@@ -632,7 +654,7 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api=
if ssh or context.native or (context.os == 'android'):
if len(args) > 0 and which(packing._decode(args[0])) == packing._decode(exe):
args = _gdbserver_args(args=args, which=which, env=env)
args = _gdbserver_args(gdbserver_args=gdbserver_args, args=args, port=port, which=which, env=env)
else:
# GDBServer is limited in it's ability to manipulate argv[0]
@@ -640,9 +662,9 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api=
# ``execve`` calls.
# Therefore, we use a wrapper script to execute the target binary
script = _execve_script(args, executable=exe, env=env, ssh=ssh)
args = _gdbserver_args(args=args, which=which, env=env, python_wrapper_script=script)
args = _gdbserver_args(gdbserver_args=gdbserver_args, args=args, port=port, which=which, env=env, python_wrapper_script=script)
else:
qemu_port = random.randint(1024, 65535)
qemu_port = port if port != 0 else random.randint(1024, 65535)
qemu_user = qemu.user_path()
sysroot = sysroot or qemu.ld_prefix(env=env)
if not qemu_user:
@@ -671,9 +693,11 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api=
# Set the .executable on the process object.
gdbserver.executable = exe
# Find what port we need to connect to
if ssh or context.native or (context.os == 'android'):
port = _gdbserver_port(gdbserver, ssh)
gdb_port = _gdbserver_port(gdbserver, ssh)
if port != 0 and port != gdb_port:
log.error("gdbserver port (%d) doesn't equals set port (%d)" % (gdb_port, port))
port = gdb_port
else:
port = qemu_port
@@ -681,19 +705,20 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api=
if not ssh and context.os == 'android':
host = context.adb_host
tmp = attach((host, port), exe=exe, gdbscript=gdbscript, ssh=ssh, sysroot=sysroot, api=api)
tmp = attach((host, port), exe=exe, gdbscript=gdbscript, gdb_args=gdb_args, ssh=ssh, sysroot=sysroot, api=api)
if api:
_, gdb = tmp
gdbserver.gdb = gdb
# gdbserver outputs a message when a client connects
garbage = gdbserver.recvline(timeout=1)
# Some versions of gdbserver output an additional message
try:
garbage2 = gdbserver.recvline_startswith(b"Remote debugging from host ", timeout=2)
except EOFError:
pass
message = b"Remote debugging from host "
if not garbage.startswith(message):
try:
garbage2 = gdbserver.recvline_startswith(message, timeout=2)
except EOFError:
pass
return gdbserver
@@ -720,6 +745,12 @@ def binary():
>>> gdb.binary() # doctest: +SKIP
'/usr/bin/gdb'
"""
if context.gdb_binary:
gdb = misc.which(context.gdb_binary)
if not gdb:
log.warn_once('Path to gdb binary `{}` not found'.format(context.gdb_binary))
return gdb
gdb = misc.which('pwntools-gdb') or misc.which('gdb')
if not context.native:
@@ -920,6 +951,8 @@ def attach(target, gdbscript = '', exe = None, gdb_args = None, ssh = None, sysr
Process name. The youngest process is selected.
:obj:`tuple`
Host, port pair of a listening ``gdbserver``
Tries to look up the target exe from the ``gdbserver`` commandline,
requires explicit ``exe`` argument if the target exe is not in the commandline.
:class:`.process`
Process to connect to
:class:`.sock`
@@ -1004,6 +1037,30 @@ def attach(target, gdbscript = '', exe = None, gdb_args = None, ssh = None, sysr
>>> io.sendline(b'echo Hello from bash && exit')
>>> io.recvall()
b'Hello from bash\n'
>>> server.close()
Attach to a gdbserver / gdbstub running on the local machine
by specifying the host and port tuple it is listening on.
(gdbserver always listens on 0.0.0.0)
>>> gdbserver = process(['gdbserver', '1.2.3.4:12345', '/bin/bash'])
>>> gdbserver.recvline_contains(b'Listening on port', timeout=10)
b'Listening on port 12345'
>>> pid = gdb.attach(('0.0.0.0', 12345), gdbscript='''
... tbreak main
... commands
... call puts("Hello from gdbserver debugger!")
... continue
... end
... ''')
>>> gdbserver.recvline(timeout=10) # doctest: +ELLIPSIS
b'Remote debugging from host 127.0.0.1, ...\n'
>>> gdbserver.recvline(timeout=10)
b'Hello from gdbserver debugger!\n'
>>> gdbserver.sendline(b'echo Hello from bash && exit')
>>> gdbserver.recvline(timeout=10)
b'Hello from bash\n'
>>> gdbserver.close()
Attach to processes running on a remote machine via an SSH :class:`.ssh` process
@@ -1173,7 +1230,7 @@ def attach(target, gdbscript = '', exe = None, gdb_args = None, ssh = None, sysr
cmd += [exe]
if pid and not context.os == 'android':
cmd += [str(pid)]
cmd += ['-p', str(pid)]
if context.os == 'android' and pid:
runner = _get_runner()
@@ -1221,7 +1278,7 @@ def attach(target, gdbscript = '', exe = None, gdb_args = None, ssh = None, sysr
gdb_pid = misc.run_in_new_terminal(cmd, preexec_fn = preexec_fn)
if pid and context.native:
proc.wait_for_debugger(pid, gdb_pid)
gdb_pid = proc.wait_for_debugger(pid, gdb_pid)
if not api:
return gdb_pid
@@ -1245,7 +1302,7 @@ def attach(target, gdbscript = '', exe = None, gdb_args = None, ssh = None, sysr
else:
# Check to see if RPyC is installed at all in GDB
rpyc_check = [gdb_binary, '--nx', '-batch', '-ex',
'python import rpyc; import sys; sys.exit(123)']
'python import rpyc; import gdb; gdb.execute("quit 123")']
if 123 != tubes.process.process(rpyc_check).poll(block=True):
log.error('Failed to connect to GDB: rpyc is not installed')
@@ -1464,28 +1521,33 @@ def corefile(process):
'contain all of the data in the process.\n'
'Upgrade to GDB >= 7.11 for better core-dumps.' % binary())
# This is effectively the same as what the 'gcore' binary does
gdb_args = ['-batch',
'-q',
'-nx',
'-ex', 'set pagination off',
'-ex', 'set height 0',
'-ex', 'set width 0',
'-ex', 'set use-coredump-filter on',
'-ex', 'generate-core-file %s' % corefile_path,
'-ex', 'detach']
# This is effectively the same as what the 'gcore' binary does.
# Run GDB directly instead of going through attach(), which has to
# race GDB to observe the tracer before it already detached again.
cmd = [binary(),
'-batch',
'-q',
'-nx',
'-ex', 'set pagination off',
'-ex', 'set height 0',
'-ex', 'set width 0',
'-ex', 'set use-coredump-filter on',
'-ex', 'attach %d' % process.pid,
'-ex', 'generate-core-file %s' % corefile_path,
'-ex', 'detach']
with context.local(terminal = ['sh', '-c']):
with context.quiet:
pid = attach(process, gdb_args=gdb_args)
log.debug("Got GDB pid %d", pid)
try:
psutil.Process(pid).wait()
except psutil.Error:
pass
with context.quiet:
gdb = tubes.process.process(cmd, stdout=tubes.process.PIPE)
gdb.wait_for_close(timeout=60)
timed_out = gdb.poll() is None
output = gdb.recvallS(timeout=0)
if timed_out:
log.error("GDB did not finish dumping process %d within 60 seconds", process.pid)
if not os.path.exists(corefile_path):
log.error("Could not generate a corefile for process %d", process.pid)
log.error("Could not generate a corefile for process %d (maybe check /proc/sys/kernel/yama/ptrace_scope)\n%s",
process.pid, output)
return elf.corefile.Core(corefile_path)
+1 -1
View File
@@ -95,7 +95,7 @@ class PwntoolsLexer(RegexLexer):
'whitespace': [
(r'\n', Text),
(r'\s+', Text),
(r'/\*.*?\*/', Comment),
(r'(?ms)/\*.*?\*/', Comment),
(r';.*$', Comment)
],
'punctuation': [
+379 -109
View File
@@ -8,12 +8,15 @@ import os
import time
import six
import tempfile
import struct
import sys
from pwnlib.context import context
from pwnlib.elf import ELF
from pwnlib.filesystem.path import Path
from pwnlib.log import getLogger
from pwnlib.tubes.process import process
from pwnlib.util.fiddling import enhex
from pwnlib.util.fiddling import enhex, unhex
from pwnlib.util.hashes import sha1filehex, sha256filehex, md5filehex
from pwnlib.util.misc import read
from pwnlib.util.misc import which
@@ -22,13 +25,49 @@ from pwnlib.util.web import wget
log = getLogger(__name__)
HASHES = {
'build_id': lambda path: enhex(ELF(path, checksec=False).buildid or b''),
def _turbofast_extract_build_id(path):
"""
Elf_External_Note:
0x00 +--------+
| namesz | <- Size of entry's owner string
0x04 +--------+
| descsz | <- Size of the note descriptor
0x08 +--------+
| type | <- Interpretation of the descriptor
0x0c +--------+
| name | <- Start of the name+desc data
... +--------
| desc |
... +--------+
"""
data = read(path, 0x1000)
# search NT_GNU_BUILD_ID and b"GNU\x00" (type+name)
idx = data.find(unhex("03000000474e5500"))
if idx == -1:
return enhex(ELF(path, checksec=False).buildid or b'')
descsz, = struct.unpack("<L", data[idx-4: idx])
return enhex(data[idx+8: idx+8+descsz])
TYPES = {
'libs_id': None,
'build_id': _turbofast_extract_build_id,
'sha1': sha1filehex,
'sha256': sha256filehex,
'md5': md5filehex,
}
# mapping for search result (same as libc.rip)
MAP_TYPES = {
'libs_id': 'id',
'build_id': 'buildid'
}
DEBUGINFOD_SERVERS = [
'https://debuginfod.ubuntu.com/',
'https://debuginfod.debian.net/',
'https://debuginfod.elfutils.org/',
]
@@ -36,18 +75,25 @@ if 'DEBUGINFOD_URLS' in os.environ:
urls = os.environ['DEBUGINFOD_URLS'].split(' ')
DEBUGINFOD_SERVERS = urls + DEBUGINFOD_SERVERS
# Allow to override url with a caching proxy in CI
LIBC_RIP_URL = os.environ.get("PWN_LIBCRIP_URL", "https://libc.rip").rstrip("/")
GITLAB_LIBCDB_URL = os.environ.get("PWN_GITLAB_LIBCDB_URL", "https://gitlab.com").rstrip("/")
# Retry failed lookups after some time
NEGATIVE_CACHE_EXPIRY = 60 * 60 * 24 * 7 # 1 week
# https://gitlab.com/libcdb/libcdb wasn't updated after 2019,
# but still is a massive database of older libc binaries.
def provider_libcdb(hex_encoded_id, hash_type):
def provider_libcdb(hex_encoded_id, search_type):
if search_type == 'libs_id':
return None
# Deferred import because it's slow
import requests
from six.moves import urllib
# Build the URL using the requested hash type
url_base = "https://gitlab.com/libcdb/libcdb/raw/master/hashes/%s/" % hash_type
url_base = "{}/libcdb/libcdb/raw/master/hashes/{}/".format(GITLAB_LIBCDB_URL, search_type)
url = urllib.parse.urljoin(url_base, hex_encoded_id)
data = b""
@@ -57,7 +103,7 @@ def provider_libcdb(hex_encoded_id, hash_type):
data = wget(url, timeout=20)
if not data:
log.warn_once("Could not fetch libc for %s %s from libcdb", hash_type, hex_encoded_id)
log.warn_once("Could not fetch libc for %s %s from libcdb", search_type, hex_encoded_id)
break
# GitLab serves up symlinks with
@@ -65,36 +111,53 @@ def provider_libcdb(hex_encoded_id, hash_type):
url = os.path.dirname(url) + '/'
url = urllib.parse.urljoin(url.encode('utf-8'), data)
except requests.RequestException as e:
log.warn_once("Failed to fetch libc for %s %s from libcdb: %s", hash_type, hex_encoded_id, e)
log.warn_once("Failed to fetch libc for %s %s from libcdb: %s", search_type, hex_encoded_id, e)
return data
def query_libc_rip(params):
# Deferred import because it's slow
import requests
url = "https://libc.rip/api/find"
try:
result = requests.post(url, json=params, timeout=20)
result.raise_for_status()
if result.status_code != 200:
log.debug("Error: %s", result.text)
url = "{}/api/find".format(LIBC_RIP_URL)
# Handle pagination transparently and fetch all results
offset = 0
count = 1
results = []
while offset < count:
try:
pagination_params = {'offset': offset, 'limit': 100}
log.debug("Querying libc.rip at %s (pagination %s) with parameters: %s", url, pagination_params, params)
result = requests.post(url, params=pagination_params, json=params, timeout=20)
result.raise_for_status()
if result.status_code != 200:
log.debug("Error: %s", result.text)
return None
imm_results = result.json()
# non-paginated result. old libc-database API?
if not isinstance(imm_results, dict):
return imm_results
results.extend(imm_results.get('results', []))
count = imm_results.get('total', 0)
offset += imm_results['count']
if not imm_results['has_more']:
break
except requests.RequestException as e:
log.warn_once("Failed to fetch libc info from libc.rip: %s", e)
return None
return result.json()
except requests.RequestException as e:
log.warn_once("Failed to fetch libc info from libc.rip: %s", e)
return None
return results
# https://libc.rip/
def provider_libc_rip(hex_encoded_id, hash_type):
def provider_libc_rip(search_target, search_type):
# Build the request for the hash type
# https://github.com/niklasb/libc-database/blob/master/searchengine/api.yml
if hash_type == 'build_id':
hash_type = 'buildid'
params = {hash_type: hex_encoded_id}
if search_type in MAP_TYPES.keys():
search_type = MAP_TYPES[search_type]
params = {search_type: search_target}
libc_match = query_libc_rip(params)
if not libc_match:
log.warn_once("Could not find libc info for %s %s on libc.rip", hash_type, hex_encoded_id)
log.warn_once("Could not find libc info for %s %s on libc.rip", search_type, search_target)
return None
if len(libc_match) > 1:
@@ -103,16 +166,17 @@ def provider_libc_rip(hex_encoded_id, hash_type):
url = libc_match[0]['download_url']
log.debug("Downloading data from libc.rip: %s", url)
url = url.replace("https://libc.rip", LIBC_RIP_URL)
data = wget(url, timeout=20)
if not data:
log.warn_once("Could not fetch libc binary for %s %s from libc.rip", hash_type, hex_encoded_id)
log.warn_once("Could not fetch libc binary for %s %s from libc.rip", search_type, search_target)
return None
return data
# Check if the local system libc matches the requested hash.
def provider_local_system(hex_encoded_id, hash_type):
if hash_type == 'id':
def provider_local_system(hex_encoded_id, search_type):
if search_type == 'libs_id':
return None
shell_path = os.environ.get('SHELL', None) or '/bin/sh'
if not os.path.exists(shell_path):
@@ -122,32 +186,118 @@ def provider_local_system(hex_encoded_id, hash_type):
if not local_libc:
log.debug('Cannot lookup libc from shell %r. Skipping local system libc matching.', shell_path)
return None
if HASHES[hash_type](local_libc.path) == hex_encoded_id:
if TYPES[search_type](local_libc.path) == hex_encoded_id:
return local_libc.data
return None
PROVIDERS = [provider_local_system, provider_libcdb, provider_libc_rip]
# Offline search https://github.com/niklasb/libc-database for hash type
def provider_local_database(search_target, search_type):
if not context.local_libcdb:
return None
def search_by_hash(hex_encoded_id, hash_type='build_id', unstrip=True):
assert hash_type in HASHES, hash_type
localdb = Path(context.local_libcdb)
if not localdb.is_dir():
return None
# Handle the specific search type 'libs_id'
if search_type == 'libs_id':
libc_list = list(localdb.rglob("%s.so" % search_target))
if len(libc_list) == 0:
return None
return read(libc_list[0])
log.debug("Searching local libc database, %s: %s", search_type, search_target)
for libc_path in localdb.rglob("*.so"):
if search_target == TYPES[search_type](libc_path):
return read(libc_path)
return None
def query_local_database(params):
if not context.local_libcdb or not params.get("symbols"):
return None
localdb = Path(context.local_libcdb)
if not localdb.is_dir():
return None
res = []
query_syms = params["symbols"]
# Loop through each '.symbols' file in the local database
# Make sure `Path.rglod` order stable
for symbol_file in sorted(localdb.rglob("*.symbols"), key=lambda x: x.as_posix()):
libc_syms = _parse_libc_symbol(symbol_file)
matched = 0
for name, addr in query_syms.items():
if isinstance(addr, str):
addr = int(addr, 16)
# Compare last 12 bits
if libc_syms.get(name) and (libc_syms.get(name) & 0xfff) == (addr & 0xfff):
matched += 1
else:
# aborting this loop once there was a mismatch.
break
# Check if all symbols have been matched
if matched == len(query_syms):
libs_id = symbol_file.stem
libc_path = symbol_file.parent / ("%s.so" % libs_id)
libs_url = read(symbol_file.parent / ("%s.url" % libs_id)).decode().strip()
res.append(_pack_libs_info(libc_path, libs_id, libs_url, libc_syms))
return res
PROVIDERS = {
"offline": [provider_local_system, provider_local_database],
"online": [provider_libcdb, provider_libc_rip]
}
def search_by_hash(search_target, search_type='build_id', unstrip=True, offline_only=False):
"""search_by_hash(str, str, bool, bool) -> str
Arguments:
search_target(str):
Use for searching the libc. This could be a hex encoded ID (`hex_encoded_id`) or a library
name (`libs_id`). Depending on `search_type`, this can represent different types of encoded
values or names.
search_type(str):
The type of the search to be performed, it should be one of the keys in the `TYPES` dictionary.
unstrip(bool):
Try to fetch debug info for the libc and apply it to the downloaded file.
offline_only(bool):
If True, restricts the search to offline providers only (local database). If False, it will also
search online providers. Default is False.
Returns:
The path to the cached directory containing the downloaded libraries.
"""
assert search_type in TYPES, search_type
# Ensure that the libcdb cache directory exists
cache, cache_valid = _check_elf_cache('libcdb', hex_encoded_id, hash_type)
cache, cache_valid = _check_elf_cache('libcdb', search_target, search_type)
if cache_valid:
if unstrip:
unstrip_libc(cache)
return cache
# We searched for this buildid before, but didn't find anything.
if cache is None:
return None
providers = PROVIDERS["offline"]
if not offline_only:
providers += PROVIDERS["online"]
# Run through all available libc database providers to see if we have a match.
for provider in PROVIDERS:
data = provider(hex_encoded_id, hash_type)
for provider in providers:
data = provider(search_target, search_type)
if data and data.startswith(b'\x7FELF'):
break
if not data:
log.warn_once("Could not find libc for %s %s anywhere", hash_type, hex_encoded_id)
log.warn_once("Could not find libc for %s %s anywhere", search_type, search_target)
# Save whatever we got to the cache
write(cache, data or b'')
@@ -162,41 +312,7 @@ def search_by_hash(hex_encoded_id, hash_type='build_id', unstrip=True):
return cache
def _search_debuginfo_by_hash(base_url, hex_encoded_id):
# Deferred import because it's slow
import requests
from six.moves import urllib
# Check if we tried this buildid before.
cache, cache_valid = _check_elf_cache('libcdb_dbg', hex_encoded_id, 'build_id')
if cache_valid:
return cache
# We searched for this buildid before, but didn't find anything.
if cache is None:
return None
# Try to find separate debuginfo.
url = '/buildid/{}/debuginfo'.format(hex_encoded_id)
url = urllib.parse.urljoin(base_url, url)
data = b""
log.debug("Downloading data from debuginfod: %s", url)
try:
data = wget(url, timeout=20)
except requests.RequestException as e:
log.warn_once("Failed to fetch libc debuginfo for build_id %s from %s: %s", hex_encoded_id, base_url, e)
# Save whatever we got to the cache
write(cache, data or b'')
# Return ``None`` if we did not get a valid ELF file
if not data or not data.startswith(b'\x7FELF'):
log.warn_once("Could not fetch libc debuginfo for build_id %s from %s", hex_encoded_id, base_url)
return None
return cache
def _check_elf_cache(cache_type, hex_encoded_id, hash_type):
def _check_elf_cache(cache_type, search_target, search_type):
"""
Check if there already is an ELF file for this hash in the cache.
@@ -209,14 +325,14 @@ def _check_elf_cache(cache_type, hex_encoded_id, hash_type):
True
"""
# Ensure that the cache directory exists
cache_dir = os.path.join(context.cache_dir, cache_type, hash_type)
cache_dir = os.path.join(context.cache_dir, cache_type, search_type)
if not os.path.isdir(cache_dir):
os.makedirs(cache_dir)
# If we already downloaded the file, and it looks even passingly like
# a valid ELF file, return it.
cache = os.path.join(cache_dir, hex_encoded_id)
cache = os.path.join(cache_dir, search_target)
if not os.path.exists(cache):
return cache, False
@@ -228,7 +344,7 @@ def _check_elf_cache(cache_type, hex_encoded_id, hash_type):
# Retry failed lookups after some time
if time.time() > os.path.getmtime(cache) + NEGATIVE_CACHE_EXPIRY:
return cache, False
log.info_once("Skipping invalid cached ELF %s", hex_encoded_id)
log.info_once("Skipping invalid cached ELF %s", search_target)
return None, False
log.info_once("Using cached data from %r", cache)
@@ -254,15 +370,15 @@ def unstrip_libc(filename):
>>> libc = ELF(filename)
>>> 'main_arena' in libc.symbols
False
>>> unstrip_libc(filename)
>>> unstrip_libc(filename) # doctest: +SKIP
True
>>> libc = ELF(filename)
>>> hex(libc.symbols.main_arena)
>>> hex(libc.symbols.main_arena) # doctest: +SKIP
'0x219c80'
>>> unstrip_libc(pwnlib.data.elf.get('test-x86'))
False
>>> filename = search_by_build_id('d1704d25fbbb72fa95d517b883131828c0883fe9', unstrip=True)
>>> 'main_arena' in ELF(filename).symbols
>>> 'main_arena' in ELF(filename).symbols # doctest: +SKIP
True
"""
if not which('eu-unstrip'):
@@ -274,18 +390,51 @@ def unstrip_libc(filename):
log.warn_once('Given libc does not have a buildid. Cannot look for debuginfo to unstrip.')
return False
if libc.debuginfo:
log.debug('Given libc already contains debug information. Skipping unstrip.')
return True
log.debug('Trying debuginfod servers: %r', DEBUGINFOD_SERVERS)
for server_url in DEBUGINFOD_SERVERS:
libc_dbg = _search_debuginfo_by_hash(server_url, enhex(libc.buildid))
if libc_dbg:
break
else:
log.warn_once('Couldn\'t find debug info for libc with build_id %s on any debuginfod server.', enhex(libc.buildid))
return False
# Deferred import because it's slow
import requests
from six.moves import urllib
hex_encoded_id = enhex(libc.buildid)
# Check if we tried this buildid before.
cache, cache_valid = _check_elf_cache('libcdb_dbg', hex_encoded_id, 'build_id')
if not cache_valid:
# Cached negative result so we don't look for missing debug info everytime.
if cache is None:
return False
else:
for server_url in DEBUGINFOD_SERVERS:
# Try to find separate debuginfo.
url = '/buildid/{}/debuginfo'.format(hex_encoded_id)
url = urllib.parse.urljoin(server_url, url)
data = b""
log.debug("Downloading data from debuginfod: %s", url)
try:
data = wget(url, timeout=20)
# Try next server if we didn't get a valid ELF file
if not data or not data.startswith(b'\x7FELF'):
log.warn_once("Could not fetch libc debuginfo for build_id %s from %s", hex_encoded_id, server_url)
continue
break
except requests.RequestException as e:
log.warn_once("Failed to fetch libc debuginfo for build_id %s from %s: %s", hex_encoded_id, server_url, e)
else:
write(cache, data or b'')
log.warn_once('Couldn\'t find debug info for libc with build_id %s on any debuginfod server.', enhex(libc.buildid))
return False
# Save whatever we got to the cache
write(cache, data or b'')
# Add debug info to given libc binary inplace.
p = process(['eu-unstrip', '-o', filename, filename, libc_dbg])
p = process(['eu-unstrip', '-o', filename, filename, cache])
output = p.recvall()
p.close()
@@ -354,7 +503,7 @@ def _extract_tarfile(cache_dir, data_filename, tarball):
def _extract_debfile(cache_dir, package_filename, package):
# Extract data.tar in the .deb archive.
if six.PY2:
if sys.version_info < (3, 6):
if not which('ar'):
log.error('Missing command line tool "ar" to extract .deb archive. Please install "ar" first.')
@@ -401,7 +550,9 @@ def _find_libc_package_lib_url(libc):
libc_match = query_libc_rip({'buildid': enhex(libc.buildid)})
if libc_match is not None:
for match in libc_match:
yield match['libs_url']
# Allow to override url with a caching proxy in CI
ubuntu_archive_url = os.environ.get('PWN_UBUNTU_ARCHIVE_URL', 'http://archive.ubuntu.com').rstrip('/')
yield match['libs_url'].replace('http://archive.ubuntu.com', ubuntu_archive_url)
# Check launchpad.net if it's an Ubuntu libc
# GNU C Library (Ubuntu GLIBC 2.36-0ubuntu4)
@@ -518,7 +669,7 @@ def _handle_multiple_matching_libcs(matching_libcs):
selected_index = options("Select the libc version to use:", [libc['id'] for libc in matching_libcs])
return matching_libcs[selected_index]
def search_by_symbol_offsets(symbols, select_index=None, unstrip=True, return_as_list=False):
def search_by_symbol_offsets(symbols, select_index=None, unstrip=True, offline_only=False, search_type='build_id', return_as_list=False, return_raw=False):
"""
Lookup possible matching libc versions based on leaked function addresses.
@@ -537,9 +688,16 @@ def search_by_symbol_offsets(symbols, select_index=None, unstrip=True, return_as
The libc to select if there are multiple matches (starting at 1).
unstrip(bool):
Try to fetch debug info for the libc and apply it to the downloaded file.
offline_only(bool):
When pass `offline_only=True`, restricts search mode to offline sources only,
disable online lookup. Defaults to `False`, and enable both offline and online providers.
search_type(str):
An option to select searched hash.
return_as_list(bool):
Return a list of build ids of all matching libc versions
instead of a path to a downloaded file.
return_raw(bool):
Return raw list of matched libc.
Returns:
Path to the downloaded library on disk, or :const:`None`.
@@ -555,38 +713,94 @@ def search_by_symbol_offsets(symbols, select_index=None, unstrip=True, return_as
>>> matched_libcs = search_by_symbol_offsets({'__libc_start_main_ret': '7f89ad926550'}, return_as_list=True)
>>> len(matched_libcs) > 1
True
>>> for buildid in matched_libcs: # doctest +SKIP
... libc = ELF(search_by_build_id(buildid)) # doctest +SKIP
>>> for buildid in matched_libcs: # doctest: +SKIP
... libc = ELF(search_by_build_id(buildid)) # doctest: +SKIP
"""
assert search_type in TYPES, search_type
for symbol, address in symbols.items():
if isinstance(address, int):
symbols[symbol] = hex(address)
params = {'symbols': symbols}
log.debug('Request: %s', params)
matching_libcs = query_libc_rip(params)
log.debug('Result: %s', matching_libcs)
if matching_libcs is None or len(matching_libcs) == 0:
log.warn_once("No matching libc for symbols %r on libc.rip", symbols)
offline_matching = query_local_database(params)
online_matching = query_libc_rip(params) if not offline_only else None
if offline_matching is None:
offline_matching = []
if online_matching is None:
online_matching = []
# Aggregate and deduplicate matches from both sources
matching_libcs = {}
for libc in offline_matching + online_matching:
if libc['id'] not in matching_libcs:
matching_libcs[libc['id']] = libc
log.debug('Offline search result: %s', offline_matching)
if not offline_only:
log.debug('Online search result: %s', online_matching)
# Check if no matches are found
if len(matching_libcs) == 0:
log.warn_once("No matching libc for symbols %r", symbols)
return None
matching_list = list(matching_libcs.values())
if return_as_list:
return [libc['buildid'] for libc in matching_libcs]
return [libc['buildid'] for libc in matching_list]
if len(matching_libcs) == 1:
return search_by_build_id(matching_libcs[0]['buildid'], unstrip=unstrip)
if return_raw:
return matching_list
mapped_type = MAP_TYPES.get(search_type, search_type)
# If there's only one match, return it directly
if len(matching_list) == 1:
return search_by_hash(matching_list[0][mapped_type], search_type=search_type, unstrip=unstrip, offline_only=offline_only)
# If a specific index is provided, validate it and return the selected libc
if select_index is not None:
if select_index > 0 and select_index <= len(matching_libcs):
return search_by_build_id(matching_libcs[select_index - 1]['buildid'], unstrip=unstrip)
if select_index > 0 and select_index <= len(matching_list):
return search_by_hash(matching_list[select_index - 1][mapped_type], search_type=search_type, unstrip=unstrip, offline_only=offline_only)
else:
log.error('Invalid selected libc index. %d is not in the range of 1-%d.', select_index, len(matching_libcs))
log.error('Invalid selected libc index. %d is not in the range of 1-%d.', select_index, len(matching_list))
return None
selected_libc = _handle_multiple_matching_libcs(matching_libcs)
return search_by_build_id(selected_libc['buildid'], unstrip=unstrip)
# Handle multiple matches interactively if no index is specified
selected_libc = _handle_multiple_matching_libcs(matching_list)
return search_by_hash(selected_libc[mapped_type], search_type=search_type, unstrip=unstrip, offline_only=offline_only)
def search_by_build_id(hex_encoded_id, unstrip=True):
def search_by_libs_id(libs_id, unstrip=True, offline_only=False):
"""
Given a Libs ID, attempt to download a matching libc from libcdb.
Arguments:
libs_id(str):
Libs ID (e.g. ``'libc6_...'``) of the library
unstrip(bool):
Try to fetch debug info for the libc and apply it to the downloaded file.
offline_only(bool):
When pass ``offline_only=True``, restricts search mode to offline sources only,
disable online lookup. Defaults to :const:`False`, and enable both offline and online providers.
Returns:
Path to the downloaded library on disk, or :const:`None`.
Examples:
>>> None == search_by_libs_id('XX')
True
>>> filename = search_by_libs_id('libc6_2.31-3_amd64')
>>> hex(ELF(filename).symbols.read)
'0xeef40'
"""
return search_by_hash(libs_id, 'libs_id', unstrip, offline_only)
def search_by_build_id(hex_encoded_id, unstrip=True, offline_only=False):
"""
Given a hex-encoded Build ID, attempt to download a matching libc from libcdb.
@@ -595,6 +809,9 @@ def search_by_build_id(hex_encoded_id, unstrip=True):
Hex-encoded Build ID (e.g. 'ABCDEF...') of the library
unstrip(bool):
Try to fetch debug info for the libc and apply it to the downloaded file.
offline_only(bool):
When pass `offline_only=True`, restricts search mode to offline sources only,
disable online lookup. Defaults to `False`, and enable both offline and online providers.
Returns:
Path to the downloaded library on disk, or :const:`None`.
@@ -610,9 +827,9 @@ def search_by_build_id(hex_encoded_id, unstrip=True):
>>> hex(ELF(filename).symbols.read)
'0xeef40'
"""
return search_by_hash(hex_encoded_id, 'build_id', unstrip)
return search_by_hash(hex_encoded_id, 'build_id', unstrip, offline_only)
def search_by_md5(hex_encoded_id, unstrip=True):
def search_by_md5(hex_encoded_id, unstrip=True, offline_only=False):
"""
Given a hex-encoded md5sum, attempt to download a matching libc from libcdb.
@@ -621,6 +838,9 @@ def search_by_md5(hex_encoded_id, unstrip=True):
Hex-encoded md5sum (e.g. 'ABCDEF...') of the library
unstrip(bool):
Try to fetch debug info for the libc and apply it to the downloaded file.
offline_only(bool):
When pass `offline_only=True`, restricts search mode to offline sources only,
disable online lookup. Defaults to `False`, and enable both offline and online providers.
Returns:
Path to the downloaded library on disk, or :const:`None`.
@@ -636,9 +856,9 @@ def search_by_md5(hex_encoded_id, unstrip=True):
>>> hex(ELF(filename).symbols.read)
'0xeef40'
"""
return search_by_hash(hex_encoded_id, 'md5', unstrip)
return search_by_hash(hex_encoded_id, 'md5', unstrip, offline_only)
def search_by_sha1(hex_encoded_id, unstrip=True):
def search_by_sha1(hex_encoded_id, unstrip=True, offline_only=False):
"""
Given a hex-encoded sha1, attempt to download a matching libc from libcdb.
@@ -647,6 +867,9 @@ def search_by_sha1(hex_encoded_id, unstrip=True):
Hex-encoded sha1sum (e.g. 'ABCDEF...') of the library
unstrip(bool):
Try to fetch debug info for the libc and apply it to the downloaded file.
offline_only(bool):
When pass `offline_only=True`, restricts search mode to offline sources only,
disable online lookup. Defaults to `False`, and enable both offline and online providers.
Returns:
Path to the downloaded library on disk, or :const:`None`.
@@ -662,10 +885,9 @@ def search_by_sha1(hex_encoded_id, unstrip=True):
>>> hex(ELF(filename).symbols.read)
'0xeef40'
"""
return search_by_hash(hex_encoded_id, 'sha1', unstrip)
return search_by_hash(hex_encoded_id, 'sha1', unstrip, offline_only)
def search_by_sha256(hex_encoded_id, unstrip=True):
def search_by_sha256(hex_encoded_id, unstrip=True, offline_only=False):
"""
Given a hex-encoded sha256, attempt to download a matching libc from libcdb.
@@ -674,6 +896,9 @@ def search_by_sha256(hex_encoded_id, unstrip=True):
Hex-encoded sha256sum (e.g. 'ABCDEF...') of the library
unstrip(bool):
Try to fetch debug info for the libc and apply it to the downloaded file.
offline_only(bool):
When pass `offline_only=True`, restricts search mode to offline sources only,
disable online lookup. Defaults to `False`, and enable both offline and online providers.
Returns:
Path to the downloaded library on disk, or :const:`None`.
@@ -689,9 +914,54 @@ def search_by_sha256(hex_encoded_id, unstrip=True):
>>> hex(ELF(filename).symbols.read)
'0xeef40'
"""
return search_by_hash(hex_encoded_id, 'sha256', unstrip)
return search_by_hash(hex_encoded_id, 'sha256', unstrip, offline_only)
def _parse_libc_symbol(path):
"""
Parse symbols file to `dict`, the format is same as https://github.com/niklasb/libc-database/
"""
syms = {}
with open(path, "r") as fd:
for x in fd:
name, addr = x.split(" ")
syms[name] = int(addr, 16)
return syms
def _pack_libs_info(path, libs_id, libs_url, syms):
"""
The JSON format is the same as libc.rip, and the "download_url" field is by default an empty string,
as it's not required in offline mode.
"""
info = {}
info["id"] = libs_id
info["libs_url"] = libs_url
info["download_url"] = ""
for search_type, hash_func in TYPES.items():
# pass libs_id
if search_type == 'libs_id':
continue
# replace search_type
if search_type in MAP_TYPES.keys():
search_type = MAP_TYPES[search_type]
info[search_type] = hash_func(path)
default_symbol_list = [
"__libc_start_main_ret", "dup2", "printf", "puts", "read", "system", "str_bin_sh"
]
info["symbols"] = {}
for name in default_symbol_list:
info["symbols"][name] = hex(syms[name])
return info
def get_build_id_offsets():
@@ -746,4 +1016,4 @@ def get_build_id_offsets():
}.get(context.arch, [])
__all__ = ['get_build_id_offsets', 'search_by_build_id', 'search_by_sha1', 'search_by_sha256', 'search_by_md5', 'unstrip_libc', 'search_by_symbol_offsets', 'download_libraries']
__all__ = ['get_build_id_offsets', 'search_by_build_id', 'search_by_sha1', 'search_by_sha256', 'search_by_md5', 'search_by_libs_id', 'unstrip_libc', 'search_by_symbol_offsets', 'download_libraries']
+2 -1
View File
@@ -546,7 +546,8 @@ class Handler(logging.StreamHandler):
# if the record originates from a `Progress` object and term handling
# is enabled we can have animated spinners! so check that
if progress is None or not term.term_mode:
# Don't show spinners if the output is being redirected
if progress is None or not term.term_mode or not os.path.sameopenfile(context.log_console.fileno(), term.term.fd.fileno()):
super(Handler, self).emit(record)
return
+2 -1
View File
@@ -105,6 +105,7 @@ def archname():
('powerpc64', 'little'): 'ppc64le',
('thumb', 'little'): 'arm',
('thumb', 'big'): 'armeb',
('aarch64', 'big'): 'aarch64_be',
}.get((context.arch, context.endian), context.arch)
@LocalContext
@@ -139,7 +140,7 @@ def user_path():
def ld_prefix(path=None, env=None):
"""Returns the linker prefix for the selected qemu-user binary
>>> pwnlib.qemu.ld_prefix(arch='arm')
>>> pwnlib.qemu.ld_prefix(arch='arm') # doctest: +SKIP
'/etc/qemu-binfmt/arm'
"""
if context.os == 'baremetal':
+51 -16
View File
@@ -15,7 +15,7 @@ from pwnlib.log import getLogger
log = getLogger(__name__)
def check_cycle(reg, assignments):
def check_cycle(reg, assignments, mapping=None):
"""Walk down the assignment list of a register,
return the path walked if it is encountered again.
@@ -37,31 +37,38 @@ def check_cycle(reg, assignments):
>>> check_cycle('a', {'a': 'b', 'b': 'c', 'c': 'd', 'd': 'a'})
['a', 'b', 'c', 'd']
"""
return check_cycle_(reg, assignments, [])
if mapping is None:
mapping = {}
return check_cycle_(reg, assignments, [], mapping)
def check_cycle_(reg, assignments, path):
target = assignments[reg]
def check_cycle_(reg, assignments, path, mapping):
target = assignments.get(reg)
if target is None:
real_reg = mapping.get(reg, reg)
reg, target = next((k, v) for k,v in assignments.items() if mapping.get(k, k) == real_reg)
path.append(reg)
real_target = mapping.get(target, target)
# No cycle, some other value (e.g. 1)
if target not in assignments:
if all(real_target != mapping.get(k, k) for k in assignments):
return []
# Found a cycle
if target in path:
if any(real_target == mapping.get(k, k) for k in path):
# Does the cycle *start* with target?
# This determines whether the original register is
# in the cycle, or just depends on registers in one.
if target == path[0]:
if real_target == mapping.get(path[0], path[0]):
return path
# Just depends on one.
return []
# Recurse
return check_cycle_(target, assignments, path)
return check_cycle_(target, assignments, path, mapping)
def extract_dependencies(reg, assignments):
def extract_dependencies(reg, assignments, mapping=None):
"""Return a list of all registers which directly
depend on the specified register.
@@ -77,7 +84,9 @@ def extract_dependencies(reg, assignments):
['b', 'c']
"""
# sorted() is only for determinism
return sorted([k for k,v in assignments.items() if v == reg])
if mapping is None:
mapping = {}
return sorted([k for k,v in assignments.items() if mapping.get(v, v) == mapping.get(reg, reg)])
def resolve_order(reg, deps):
@@ -110,7 +119,7 @@ def depends_on_cycle(reg, assignments, in_cycles):
reg = assignments.get(reg, None)
return False
def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
def regsort(in_out, all_regs, mapping = None, tmp = None, xchg = True, randomize = None):
"""
Sorts register dependencies.
@@ -181,6 +190,15 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
>>> regsort({'a': 1, 'b': 2}, R)
[('mov', 'a', 1), ('mov', 'b', 2)]
>>> M = {'ax': 'eax', 'eax': 'eax', 'ebx': 'ebx'}
Registers which are assigned one of their own aliases
are dropped, like same-name self-assignments.
>>> regsort({'ax': 'eax'}, M)
[]
>>> regsort({'ax': 'eax'}, M, xchg=False)
[]
>>> regsort({'a': 'b', 'b': 'a'}, R)
[('xchg', 'a', 'b')]
>>> regsort({'a': 'b', 'b': 'a'}, R, tmp='X') #doctest: +NORMALIZE_WHITESPACE
@@ -233,16 +251,24 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
if randomize is None:
randomize = context.randomize
if mapping is None:
if hasattr(all_regs, 'keys'):
mapping = all_regs
else:
mapping = {}
sentinel = object()
# Drop all registers which will be set to themselves.
#
# For example, {'eax': 'eax'}
in_out = {k:v for k,v in in_out.items() if k != v}
# This must go through the mapping, so that {'ax': 'eax'} is
# recognized as a self-assignment as well.
in_out = {k:v for k,v in in_out.items() if mapping.get(k, k) != mapping.get(v, v)}
# Collapse constant values
#
# For eaxmple, {'eax': 0, 'ebx': 0} => {'eax': 0, 'ebx': 'eax'}
# For example, {'eax': 0, 'ebx': 0} => {'eax': 0, 'ebx': 'eax'}
v_k = defaultdict(list)
for k,v in sorted(in_out.items()):
if v not in all_regs and v != 0:
@@ -263,7 +289,9 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
# which are also 'outputs'.
#
# For example, {'eax': 1, 'ebx': 2, 'ecx': 'edx'}
if not any(v in in_out for k,v in in_out.items()):
inps = {mapping.get(k, k) for k in in_out}
outs = {mapping.get(v, v) for v in in_out.values()}
if not inps & outs:
result = [('mov', k,in_out[k]) for k in sorted(in_out)]
if randomize:
@@ -280,7 +308,7 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
# Output: {'A': [], 'B': ['A', 'C'], 'C': []}
#
# In this case, both A and C must be set before B.
deps = {r: extract_dependencies(r, in_out) for r in in_out}
deps = {r: extract_dependencies(r, in_out, mapping) for r in in_out}
# Final result which will be returned
result = []
@@ -299,7 +327,7 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
while cycle_candidates:
reg = cycle_candidates[0]
cycle = check_cycle(reg, in_out)
cycle = check_cycle(reg, in_out, mapping)
if cycle:
if randomize:
@@ -395,6 +423,10 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
if tmp:
for cycle in cycles:
if len(cycle) == 1:
[reg] = cycle
result.append(('mov', reg, in_out[reg]))
continue
first = cycle[0]
last = cycle[-1]
@@ -411,6 +443,9 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
else:
for cycle in cycles:
size = len(cycle)
if size == 1:
[reg] = cycle
result.append(('mov', reg, in_out[reg]))
for i in range(size-1):
result.append(('xchg', cycle[i], cycle[(i+1) % size]))
+19 -4
View File
@@ -219,11 +219,24 @@ class Ret2dlresolvePayload(object):
elf (ELF): Binary to search
symbol (str): Function to search for
args (list): List of arguments to pass to the function
data_addr (int|None): The address where the payload will
be written to. If not provided, a suitable address will
be chosen automatically (recommended).
resolution_addr (int|None): The address where the location
of the resolved symbol will be written to. If not provided
will be equal to data_addr.
Returns:
A ``Ret2dlresolvePayload`` object which can be passed to ``rop.ret2dlresolve``
A ``Ret2dlresolvePayload`` object. It can be passed to ``rop.ret2dlresolve``
for automatic exploitation.
If that is not suitable the object generates useful values (.reloc_index
and .payload) which can be used to aid manual exploitation. In this case
it is recommended to set .resolution_addr to the GOT address of an easily
callable function (do not set it when passing the object to
rop.ret2dlresolve).
"""
def __init__(self, elf, symbol, args, data_addr=None):
def __init__(self, elf, symbol, args, data_addr=None, resolution_addr=None):
self.elf = elf
self.elf_load_address_fixup = self.elf.address - self.elf.load_addr
self.strtab = elf.dynamic_value_by_tag("DT_STRTAB") + self.elf_load_address_fixup
@@ -236,6 +249,7 @@ class Ret2dlresolvePayload(object):
self.unreliable = False
self.data_addr = data_addr if data_addr is not None else self._get_recommended_address()
self.resolution_addr = resolution_addr if resolution_addr is not None else self.data_addr
# Will be set when built
self.reloc_index = -1
@@ -302,11 +316,11 @@ class Ret2dlresolvePayload(object):
# ElfRel
rel_addr = self.jmprel + self.reloc_index * ElfRel.size
rel_type = 7
rel = ElfRel(r_offset=self.data_addr, r_info=(index<<ELF_R_SYM_SHIFT)+rel_type)
rel = ElfRel(r_offset=self.resolution_addr, r_info=(index<<ELF_R_SYM_SHIFT)+rel_type)
# When a program's PIE is enabled, r_offset should be the relative address, not the absolute address
if self.elf.pie:
rel = ElfRel(r_offset=self.data_addr - (self.elf.load_addr + self.elf_load_address_fixup), r_info=(index<<ELF_R_SYM_SHIFT)+rel_type)
rel = ElfRel(r_offset=self.resolution_addr - (self.elf.load_addr + self.elf_load_address_fixup), r_info=(index<<ELF_R_SYM_SHIFT)+rel_type)
self.payload = fit({
symbol_name_addr - self.data_addr: symbol_name,
@@ -325,6 +339,7 @@ class Ret2dlresolvePayload(object):
log.debug("Symbol name addr: %s", hex(symbol_name_addr))
log.debug("Version index addr: %s", hex(ver_addr))
log.debug("Data addr: %s", hex(self.data_addr))
log.debug("Resolution addr: %s", hex(self.resolution_addr))
if not self.elf.memory[ver_addr]:
log.warn("Ret2dlresolve is likely impossible in this ELF "
"(too big gap between text and writable sections).\n"
+13 -7
View File
@@ -390,6 +390,7 @@ from pwnlib.rop.call import Unresolved
from pwnlib.rop.gadgets import Gadget
from pwnlib.util import lists
from pwnlib.util import packing
from pwnlib.util import safeeval
from pwnlib.util.cyclic import cyclic
from pwnlib.util.packing import pack
from pwnlib.util.misc import python_2_bytes_compatible
@@ -841,7 +842,7 @@ class ROP(object):
"""
if isinstance(object, enums):
return str(object)
if isinstance(object, six.integer_types):
if isinstance(object, six.integer_types) and object:
return self.unresolve(object)
if isinstance(object, (bytes, six.text_type)):
return repr(object)
@@ -1272,7 +1273,7 @@ class ROP(object):
filename = self.__get_cachefile_name(elf)
if filename is None or not os.path.exists(filename):
return None
gadgets = eval(open(filename).read())
gadgets = safeeval.const(open(filename).read())
gadgets = {k - elf.load_addr + elf.address:v for k, v in gadgets.items()}
log.info_once('Loaded %s cached gadgets for %r', len(gadgets), elf.file.name)
return gadgets
@@ -1391,6 +1392,8 @@ class ROP(object):
if pop.match(insn):
regs.append(pop.match(insn).group(1))
sp_move += context.bytes
if 'sp' in insn:
sp_move += 9999999
elif add.match(insn):
arg = int(add.match(insn).group(1), 16)
sp_move += arg
@@ -1418,7 +1421,7 @@ class ROP(object):
if not set(['rsp', 'esp']) & set(regs):
self.pivots[sp_move] = addr
leave = self.search(regs=frame_regs, order='regs')
leave = self.search(regs=frame_regs, order='leav')
if leave and leave.regs != frame_regs:
leave = None
self.leave = leave
@@ -1451,7 +1454,7 @@ class ROP(object):
pointer is adjusted.
regs(list): Minimum list of registers which are popped off the
stack.
order(str): Either the string 'size' or 'regs'. Decides how to
order(str): Either the string 'size', 'leav' or 'regs'. Decides how to
order multiple gadgets the fulfill the requirements.
The search will try to minimize the number of bytes popped more than
@@ -1459,7 +1462,9 @@ class ROP(object):
the address.
If ``order == 'size'``, then gadgets are compared lexicographically
by ``(total_moves, total_regs, addr)``, otherwise by ``(total_regs, total_moves, addr)``.
by ``(total_moves, total_regs, addr)``, if ``order == 'regs'``,
then by ``(total_regs, total_moves, addr)``. ``order == 'leav'``
is specifically for ``leave`` insn.
Returns:
A :class:`.Gadget` object
@@ -1471,8 +1476,9 @@ class ROP(object):
# Search for an exact match, save the closest match
key = {
'size': lambda g: (g.move, len(g.regs), g.address),
'regs': lambda g: (len(g.regs), g.move, g.address)
}[order]
'regs': lambda g: (len(g.regs), g.move, g.address),
'leav': lambda g: ('leave' not in g.insns, len(g.regs), g.address)
}[order] # False is prior than True
try:
result = min(matches, key=key)
+5 -5
View File
@@ -185,7 +185,7 @@ registers = {
80: 'r13', 88: 'r14', 96: 'r15', 104: 'rdi', 112: 'rsi', 120: 'rbp', 128: 'rbx',
136: 'rdx', 144: 'rax', 152: 'rcx', 160: 'rsp', 168: 'rip', 176: 'eflags',
184: 'csgsfs', 192: 'err', 200: 'trapno', 208: 'oldmask', 216: 'cr2',
224: '&fpstate', 232: '__reserved', 240: 'sigmask'},
224: '&fpstate', 232: '__reserved', 296: 'sigmask'},
# Reference : http://lxr.free-electrons.com/source/arch/arm/include/uapi/asm/sigcontext.h#L15
'arm' : {0: 'uc_flags', 4: 'uc_link', 8: 'uc_stack.ss_sp', 12: 'uc_stack.ss_flags',
16: 'uc_stack.ss_size', 20: 'trap_no', 24: 'error_code', 28: 'oldmask', 32: 'r0',
@@ -270,15 +270,15 @@ class SigreturnFrame(dict):
>>> context.clear(arch='amd64')
>>> s = SigreturnFrame()
>>> unpack_many(bytes(s))
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0]
>>> assert len(s) == 248
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> assert len(s) == 304
>>> s.rax = 0xa
>>> s.rdi = 0x00601000
>>> s.rsi = 0x1000
>>> s.rdx = 0x7
>>> assert len(bytes(s)) == 248
>>> assert len(bytes(s)) == 304
>>> unpack_many(bytes(s))
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6295552, 4096, 0, 0, 7, 10, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6295552, 4096, 0, 0, 7, 10, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Crafting a SigreturnFrame that calls mprotect on i386
+39 -13
View File
@@ -170,21 +170,47 @@ tether = sys.modules[__name__]
# Create the module structure
shellcraft = module(__name__, '')
class LazyImporter:
def find_module(self, fullname, path=None):
if not fullname.startswith('pwnlib.shellcraft.'):
return None
parts = fullname.split('.')[2:]
cur = shellcraft
for part in parts:
cur = getattr(cur, part, None)
if not isinstance(cur, ModuleType):
if sys.version_info >= (3, 4):
import importlib.abc
import importlib.util
class LazyImporter(importlib.abc.MetaPathFinder, importlib.abc.Loader):
def find_spec(self, fullname, path=None, target=None):
if not fullname.startswith('pwnlib.shellcraft.'):
return None
return self
parts = fullname.split('.')[2:]
cur = shellcraft
for part in parts:
cur = getattr(cur, part, None)
if not isinstance(cur, ModuleType):
return None
def load_module(self, fullname):
return sys.modules[fullname]
return importlib.util.spec_from_loader(fullname, self)
def create_module(self, spec):
# The submodule was already built and registered in sys.modules by
# the getattr walk in find_spec, so hand that object back instead
# of letting the import system make a fresh empty module.
return sys.modules.get(spec.name)
def exec_module(self, module):
pass
else:
class LazyImporter:
def find_module(self, fullname, path=None):
if not fullname.startswith('pwnlib.shellcraft.'):
return None
parts = fullname.split('.')[2:]
cur = shellcraft
for part in parts:
cur = getattr(cur, part, None)
if not isinstance(cur, ModuleType):
return None
return self
def load_module(self, fullname):
return sys.modules[fullname]
sys.meta_path.append(LazyImporter())
+42 -5
View File
@@ -73,7 +73,42 @@ sparc += list(map('i{}'.format, range(5)))
sparc += ["pc", "sp", "fp", "psr" ]
sparc = list(map('%{}'.format, sparc))
riscv = {
'x0' : 0, 'zero': 0,
'x1' : 1, 'ra': 1,
'x2' : 2, 'sp': 2,
'x3' : 3, 'gp': 3,
'x4' : 4, 'tp': 4,
'x5' : 5, 't0': 5,
'x6' : 6, 't1': 6,
'x7' : 7, 't2': 7,
'x8' : 8, 's0': 8, 'fp': 8,
'x9' : 9, 's1': 9,
'x10': 10, 'a0': 10,
'x11': 11, 'a1': 11,
'x12': 12, 'a2': 12,
'x13': 13, 'a3': 13,
'x14': 14, 'a4': 14,
'x15': 15, 'a5': 15,
'x16': 16, 'a6': 16,
'x17': 17, 'a7': 17,
'x18': 18, 's2': 18,
'x19': 19, 's3': 19,
'x20': 20, 's4': 20,
'x21': 21, 's5': 21,
'x22': 22, 's6': 22,
'x23': 23, 's7': 23,
'x24': 24, 's8': 24,
'x25': 25, 's9': 25,
'x26': 26, 's10': 26,
'x27': 27, 's11': 27,
'x28': 28, 't3': 28,
'x29': 29, 't4': 29,
'x30': 30, 't5': 30,
'x31': 31, 't6': 31,
}
riscv_list = list(riscv)
# x86/amd64 registers in decreasing size
i386_ordered = [
@@ -81,10 +116,10 @@ i386_ordered = [
['rbx', 'ebx', 'bx', 'bl'],
['rcx', 'ecx', 'cx', 'cl'],
['rdx', 'edx', 'dx', 'dl'],
['rdi', 'edi', 'di'],
['rsi', 'esi', 'si'],
['rbp', 'ebp', 'bp'],
['rsp', 'esp', 'sp'],
['rdi', 'edi', 'di', 'dil'],
['rsi', 'esi', 'si', 'sil'],
['rbp', 'ebp', 'bp', 'bpl'],
['rsp', 'esp', 'sp', 'spl'],
['r8', 'r8d', 'r8w', 'r8b'],
['r9', 'r9d', 'r9w', 'r9b'],
['r10', 'r10d', 'r10w', 'r10b'],
@@ -215,7 +250,9 @@ def current():
'thumb': arm,
'aarch64': aarch64,
'mips': mips_list,
'powerpc': powerpc
'powerpc': powerpc,
'riscv32': riscv,
'riscv64': riscv,
}[context.arch]
# def is_register(sz):
@@ -6,7 +6,10 @@
Creates a new socket
</%docstring>
<%
sockaddr, length, address_family = sockaddr('127.0.0.1', 1, network)
if network == 'ipv4':
sockaddr, length, address_family = sockaddr('127.0.0.1', 1, network)
elif network == 'ipv6':
sockaddr, length, address_family = sockaddr('::1', 1, network)
socktype = {
'tcp': SOCK_STREAM,
'udp': SOCK_DGRAM
@@ -16,4 +16,4 @@ ${memcpy_loop}:
ldrb w3, [x1], #1
strb w3, [x0], #1
subs x2, x2, #1
bge ${memcpy_loop}
bgt ${memcpy_loop}
@@ -6,7 +6,10 @@
Creates a new socket
</%docstring>
<%
sockaddr, length, address_family = sockaddr('127.0.0.1', 1, network)
if network == 'ipv4':
sockaddr, length, address_family = sockaddr('127.0.0.1', 1, network)
elif network == 'ipv6':
sockaddr, length, address_family = sockaddr('::1', 1, network)
socktype = {
'tcp': SOCK_STREAM,
'udp': SOCK_DGRAM
+2 -2
View File
@@ -51,8 +51,8 @@ Example:
xor eax, eax
mov ax, 0xc0c0
>>> print(shellcraft.amd64.mov('rdi', 0xff).rstrip())
mov edi, 0x1010101 /* 255 == 0xff */
xor edi, 0x10101fe
xor edi, edi
mov dil, 0xff
>>> print(shellcraft.amd64.mov('rax', 0xdead00ff).rstrip())
mov eax, 0x1010101 /* 3735879935 == 0xdead00ff */
xor eax, 0xdfac01fe
@@ -55,7 +55,7 @@ if isinstance(eax, six.integer_types) and isinstance(edx, six.integer_types) and
cdq = True
reg_context.pop('rdx')
sorted_regs = regsort(reg_context, registers.amd64)
sorted_regs = regsort(reg_context, registers.amd64, registers.native64)
%>
% if not sorted_regs:
/* setregs noop */
@@ -1,24 +1,30 @@
<%
from pwnlib.shellcraft import amd64, pretty
from pwnlib.shellcraft import amd64, common, pretty
from pwnlib.util.packing import u64, _need_bytes
%>
<%docstring>Find the address of an exported function in a dll
by manually iterating through the PE export table.
The dll must be `b'kernel32.dll'` or `b'ntdll.dll'` at the moment.
Behavior is undefined if the function is not found.
Args:
function_name (str): The name of the function to find.
dll(str): The name of the DLL to find the function in.
function_name (bytes): The name of the function to find.
dll(bytes): The name of the DLL to find the function in.
dest (str): The register to load the function address into.
</%docstring>
<%page args="function_name,dll='kernel32.dll',dest='rax'"/>
<%page args="function_name,dll=b'kernel32.dll',dest='rax'"/>
<%
function_name = _need_bytes(function_name)
dll = _need_bytes(dll)
if len(function_name) > 8:
raise ValueError('function_name must be <= 8 bytes')
assert dll == b'kernel32.dll'
assert dll in (b'kernel32.dll', b'ntdll.dll')
find_function_loop = common.label('find_function').strip()
%>
% if dll == b'kernel32.dll':
${amd64.windows.kernel32base('rbx')} /* rbx = kernel32.dll PE base */
% elif dll == b'ntdll.dll':
${amd64.windows.ntdllbase('rbx')} /* rbx = ntdll.dll PE base */
% endif
mov r8d, [rbx + 0x3c]
mov rdx, r8
add rdx, rbx
@@ -26,25 +32,42 @@ assert dll == b'kernel32.dll'
add rdx, r9
mov r8d, [rdx]
add r8, rbx /* r8 = export table */
mov esi, [r8 + 0x20]
add rsi, rbx /* rsi = names table */
xor rcx, rcx
mov edx, [r8 + 0x20]
add rdx, rbx /* rdx = names table */
% if len(function_name) <= 8:
mov r9, ${pretty(u64(function_name.ljust(8, b'\x00')))}
% else:
${amd64.pushstr(function_name)}
mov r9, rsp
% endif
push r8
xor r8, r8
/* Loop through the names table */
FindFunction:
inc rcx
mov eax, [rsi + rcx * 4]
${find_function_loop}:
inc r8
mov eax, [rdx + r8 * 4]
add rax, rbx
## TODO: implement strcmp properly for function names > 8 bytes
## strcmp
% if len(function_name) <= 8:
cmp qword ptr [rax], r9
jnz FindFunction
% else:
${amd64.setregs({
'rdi': 'rax',
'rsi': 'r9',
'rcx': len(function_name),
})}
repe cmpsb
movzx rax, byte ptr [rsi-1]
movzx rcx, byte ptr [rdi-1]
sub rax, rcx
% endif
jnz ${find_function_loop}
## Assume we find the function, we'll crash walking past the
## end of the names table otherwise.
mov rcx, r8
pop r8
mov esi, [r8 + 0x24]
add rsi, rbx /* rsi = ordinals table */
mov cx, [rsi + rcx * 2]
@@ -52,4 +75,4 @@ assert dll == b'kernel32.dll'
add rsi, rbx /* rsi = address table */
mov eax, [rsi + rcx * 4]
add rax, rbx /* rax = function address */
mov ${dest}, rax
${amd64.mov(dest, 'rax')}
@@ -11,7 +11,7 @@ Args:
dll(str): The name of the DLL to find the function in.
dest (str): The register to load the function address into.
</%docstring>
<%page args="function_name,dll='kernel32.dll',dest='rax'"/>
<%page args="function_name,dll=b'kernel32.dll',dest='rax'"/>
<%
function_name = _need_bytes(function_name)
dll = _need_bytes(dll)
@@ -25,4 +25,4 @@ assert dll == b'kernel32.dll'
sub rsp, 0x30
call rdi
add rsp, ${pretty(0x30+align(8, len(function_name)))}
mov ${dest}, rax
${amd64.mov(dest, 'rax')}
+1 -1
View File
@@ -16,4 +16,4 @@ ${memcpy_loop}:
ldrb r3, [r1], #1
strb r3, [r0], #1
subs r2, r2, #1
bge ${memcpy_loop}
bgt ${memcpy_loop}
@@ -0,0 +1,101 @@
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>close_range(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
Invokes the syscall close_range.
See 'man 2 close_range' for more information.
Arguments:
vararg(int): vararg
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = []
can_pushstr_array = []
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_close_range']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* close_range(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}
@@ -0,0 +1,101 @@
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>epoll_pwait2(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
Invokes the syscall epoll_pwait2.
See 'man 2 epoll_pwait2' for more information.
Arguments:
vararg(int): vararg
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = []
can_pushstr_array = []
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_epoll_pwait2']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* epoll_pwait2(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}
@@ -0,0 +1,101 @@
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>faccessat2(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
Invokes the syscall faccessat2.
See 'man 2 faccessat2' for more information.
Arguments:
vararg(int): vararg
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = []
can_pushstr_array = []
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_faccessat2']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* faccessat2(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}
@@ -0,0 +1,101 @@
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>landlock_add_rule(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
Invokes the syscall landlock_add_rule.
See 'man 2 landlock_add_rule' for more information.
Arguments:
vararg(int): vararg
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = []
can_pushstr_array = []
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_landlock_add_rule']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* landlock_add_rule(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}
@@ -0,0 +1,101 @@
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>landlock_create_ruleset(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
Invokes the syscall landlock_create_ruleset.
See 'man 2 landlock_create_ruleset' for more information.
Arguments:
vararg(int): vararg
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = []
can_pushstr_array = []
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_landlock_create_ruleset']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* landlock_create_ruleset(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}
@@ -0,0 +1,101 @@
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>landlock_restrict_self(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
Invokes the syscall landlock_restrict_self.
See 'man 2 landlock_restrict_self' for more information.
Arguments:
vararg(int): vararg
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = []
can_pushstr_array = []
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_landlock_restrict_self']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* landlock_restrict_self(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}
@@ -0,0 +1,101 @@
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>mount_setattr(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
Invokes the syscall mount_setattr.
See 'man 2 mount_setattr' for more information.
Arguments:
vararg(int): vararg
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = []
can_pushstr_array = []
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_mount_setattr']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* mount_setattr(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}
@@ -0,0 +1,101 @@
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>process_madvise(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
Invokes the syscall process_madvise.
See 'man 2 process_madvise' for more information.
Arguments:
vararg(int): vararg
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = []
can_pushstr_array = []
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_process_madvise']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* process_madvise(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}
@@ -0,0 +1,101 @@
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>riscv_flush_icache(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
Invokes the syscall riscv_flush_icache.
See 'man 2 riscv_flush_icache' for more information.
Arguments:
vararg(int): vararg
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = []
can_pushstr_array = []
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_riscv_flush_icache']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* riscv_flush_icache(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}
@@ -0,0 +1,101 @@
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>sysriscv(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
Invokes the syscall sysriscv.
See 'man 2 sysriscv' for more information.
Arguments:
vararg(int): vararg
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = []
can_pushstr_array = []
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_sysriscv']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* sysriscv(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}
Loaded 100 of 141 files, more files were not shown because too many files have changed in this diff. Show more