Skip to content

Commit 78e1b76

Browse files
authored
Merge branch 'dev' into add_ko_file_search_support
2 parents aa35829 + 7741a18 commit 78e1b76

20 files changed

+255
-109
lines changed

.github/workflows/pylint.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ jobs:
2626
set -x
2727
pip install pylint
2828
pip install --upgrade -e .
29-
pylint --exit-zero --errors-only pwnlib -f parseable | cut -d ' ' -f2- > current.txt
29+
run_pylint() { pylint --exit-zero --errors-only pwnlib -f parseable | cut -d ' ' -f2- | sed 's/line [0-9]\+/line XXXX/g'; }
30+
run_pylint > current.txt
3031
git fetch origin
3132
git checkout origin/"$GITHUB_BASE_REF"
32-
pylint --exit-zero --errors-only pwnlib -f parseable | cut -d ' ' -f2- > base.txt
33+
run_pylint > base.txt
3334
if diff base.txt current.txt | grep '>'; then
3435
false
3536
fi

CHANGELOG.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ The table below shows which release corresponds to each branch, and what date th
7272
| [2.2.0](#220) | | Jan 5, 2015
7373

7474
## 4.15.0 (`dev`)
75-
75+
- [#2508][2508] Ignore a warning when compiling with asm
7676
- [#2471][2471] Properly close spawned kitty window
7777
- [#2358][2358] Cache output of `asm()`
7878
- [#2457][2457] Catch exception of non-ELF files in checksec.
@@ -86,8 +86,12 @@ The table below shows which release corresponds to each branch, and what date th
8686
- [#2484][2484] Allow to disable caching
8787
- [#2291][2291] Fix attaching to a gdbserver with tuple `gdb.attach(('0.0.0.0',12345))`
8888
- [#2410][2410] Add `tube.upload_manually` to upload files in chunks
89+
- [#2502][2502] Fix loading ELF files without valid .dynamic section
90+
- [#2476][2476] Deprecate 'keepends' argument in favor of 'drop' in `tube.recvline*`
91+
- [#2364][2364] Deprecate direct commandline scripts invocation and exclude nonsense ones
8992
- [#2496][2496] Add linux ko file search support
9093

94+
[2508]: https://github.com/Gallopsled/pwntools/pull/2508
9195
[2471]: https://github.com/Gallopsled/pwntools/pull/2471
9296
[2358]: https://github.com/Gallopsled/pwntools/pull/2358
9397
[2457]: https://github.com/Gallopsled/pwntools/pull/2457
@@ -101,6 +105,9 @@ The table below shows which release corresponds to each branch, and what date th
101105
[2484]: https://github.com/Gallopsled/pwntools/pull/2484
102106
[2291]: https://github.com/Gallopsled/pwntools/pull/2291
103107
[2410]: https://github.com/Gallopsled/pwntools/pull/2410
108+
[2502]: https://github.com/Gallopsled/pwntools/pull/2502
109+
[2476]: https://github.com/Gallopsled/pwntools/pull/2476
110+
[2364]: https://github.com/Gallopsled/pwntools/pull/2364
104111
[2496]: https://github.com/Gallopsled/pwntools/pull/2496
105112

106113
## 4.14.0 (`beta`)
@@ -147,6 +154,12 @@ The table below shows which release corresponds to each branch, and what date th
147154
[2435]: https://github.com/Gallopsled/pwntools/pull/2435
148155
[2437]: https://github.com/Gallopsled/pwntools/pull/2437
149156

157+
## 4.13.2
158+
159+
- [#2497][2497] Fix remote.fromsocket() to handle AF_INET6 socket
160+
161+
[2497]: https://github.com/Gallopsled/pwntools/pull/2497
162+
150163
## 4.13.1 (`stable`)
151164

152165
- [#2445][2445] Fix parsing the PLT on Windows

docs/requirements.txt

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ capstone
22
coverage[toml]
33
python-dateutil
44
doc2dash
5-
docutils<0.18
5+
docutils<0.18; python_version<'3'
6+
docutils>=0.18; python_version>='3'
67
intervaltree
78
isort
89
mako>=1.0.0
@@ -18,6 +19,6 @@ psutil
1819
requests>=2.5.1
1920
ropgadget>=5.3
2021
sphinx==1.8.6; python_version<'3'
21-
sphinx>=4.5.0; python_version>='3'
22+
sphinx>=7.0.0; python_version>='3'
2223
sphinx_rtd_theme
2324
sphinxcontrib-autoprogram<=0.1.5

docs/source/conf.py

+3
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,9 @@ def linkcode_resolve(domain, info):
360360
else:
361361
filename = info['module'].replace('.', '/') + '.py'
362362

363+
if isinstance(val, property):
364+
val = val.fget
365+
363366
if isinstance(val, (types.ModuleType, types.MethodType, types.FunctionType, types.TracebackType, types.FrameType, types.CodeType) + six.class_types):
364367
try:
365368
lines, first = inspect.getsourcelines(val)

docs/source/protocols.rst

+9
Original file line numberDiff line numberDiff line change
@@ -1 +1,10 @@
1+
.. testsetup:: *
12

3+
from pwn import *
4+
5+
6+
:mod:`pwnlib.protocols.adb` --- Protocol implementations
7+
========================================================
8+
9+
.. automodule:: pwnlib.protocols.adb
10+
:members:

docs/source/shellcraft/riscv64.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
context.clear(arch='riscv64')
55

66
:mod:`pwnlib.shellcraft.riscv64` --- Shellcode for RISCV64
7-
===========================================================
7+
==========================================================
88

99
:mod:`pwnlib.shellcraft.riscv64`
10-
-------------------------------
10+
--------------------------------
1111

1212
.. automodule:: pwnlib.shellcraft.riscv64
1313
:members:
1414

1515
:mod:`pwnlib.shellcraft.riscv64.linux`
16-
---------------------------------------
16+
--------------------------------------
1717

1818
.. automodule:: pwnlib.shellcraft.riscv64.linux
1919
:members:

docs/source/windbg.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from pwn import *
44

55
:mod:`pwnlib.windbg` --- Working with WinDbg
6-
======================================
6+
============================================
77

88
.. automodule:: pwnlib.windbg
99
:members:

pwnlib/asm.py

+1
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ def cpp(shellcode):
471471
code = _include_header() + shellcode
472472
cmd = [
473473
cpp,
474+
'-Wno-unused-command-line-argument',
474475
'-C',
475476
'-nostdinc',
476477
'-undef',

pwnlib/commandline/common.py

+7
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ def main(file=sys.argv[0], command_main=None):
3333
sys.argv.insert(1, name)
3434
entrypoint({name: command_main})
3535

36+
def deprecated_main():
37+
file=sys.argv[0]
38+
name = os.path.splitext(os.path.basename(file))[0]
39+
import warnings
40+
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)
41+
main(file)
42+
3643
def entrypoint(commands):
3744
if len(sys.argv) < 2:
3845
parser.print_usage()

pwnlib/context/__init__.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -594,9 +594,9 @@ def quiet(self, function=None):
594594
... log.debug("DEBUG")
595595
... log.info("INFO")
596596
... log.warn("WARN")
597-
[DEBUG] DEBUG
598-
[*] INFO
599-
[!] WARN
597+
[...] DEBUG
598+
[...] INFO
599+
[...] WARN
600600
"""
601601
level = 'error'
602602
if context.log_level <= logging.DEBUG:
@@ -664,7 +664,7 @@ def verbose(self):
664664
information is printed.
665665
666666
>>> with context.verbose: func()
667-
[DEBUG] Hello
667+
[...] Hello
668668
669669
"""
670670
return self.local(log_level='debug')

pwnlib/elf/corefile.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@ class Corefile(ELF):
238238
Registers can be accessed directly, e.g. via ``core_obj.eax`` and enumerated
239239
via :data:`Corefile.registers`.
240240
241-
Memory can be accessed directly via :meth:`.read` or :meth:`.write`, and also
242-
via :meth:`.pack` or :meth:`.unpack` or even :meth:`.string`.
241+
Memory can be accessed directly via :meth:`pwnlib.elf.elf.ELF.read` or :meth:`pwnlib.elf.elf.ELF.write`, and also
242+
via :meth:`pwnlib.elf.elf.ELF.pack` or :meth:`pwnlib.elf.elf.ELF.unpack` or even :meth:`.string`.
243243
244244
Arguments:
245245
core: Path to the core file. Alternately, may be a :class:`.process` instance,
@@ -376,8 +376,8 @@ class Corefile(ELF):
376376
>>> core.exe.data[0:4]
377377
b'\x7fELF'
378378
379-
It also supports all of the features of :class:`ELF`, so you can :meth:`.read`
380-
or :meth:`.write` or even the helpers like :meth:`.pack` or :meth:`.unpack`.
379+
It also supports all of the features of :class:`ELF`, so you can :meth:`pwnlib.elf.elf.ELF.read`
380+
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`.
381381
382382
Don't forget to call :meth:`.ELF.save` to save the changes to disk.
383383

pwnlib/elf/elf.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
from elftools.elf.constants import P_FLAGS
5353
from elftools.elf.constants import SHN_INDICES
5454
from elftools.elf.descriptions import describe_e_type
55+
from elftools.elf.dynamic import DynamicSection
5556
from elftools.elf.elffile import ELFFile, PAGESIZE
5657
from elftools.elf.enums import ENUM_GNU_PROPERTY_X86_FEATURE_1_FLAGS
5758
from elftools.elf.gnuversions import GNUVerDefSection
@@ -1649,7 +1650,7 @@ def dynamic_by_tag(self, tag):
16491650
dt = None
16501651
dynamic = self.get_section_by_name('.dynamic')
16511652

1652-
if not dynamic:
1653+
if not dynamic or not isinstance(dynamic, DynamicSection):
16531654
return None
16541655

16551656
try:
@@ -2392,7 +2393,7 @@ def disable_nx(self):
23922393

23932394
@staticmethod
23942395
def set_runpath(exepath, runpath):
2395-
r"""set_runpath(str, str) -> ELF
2396+
r"""set_runpath(exepath, runpath) -> ELF
23962397
23972398
Patches the RUNPATH of the ELF to the given path using the `patchelf utility <https://github.com/NixOS/patchelf>`_.
23982399
@@ -2427,7 +2428,7 @@ def set_runpath(exepath, runpath):
24272428

24282429
@staticmethod
24292430
def set_interpreter(exepath, interpreter_path):
2430-
r"""set_interpreter(str, str) -> ELF
2431+
r"""set_interpreter(exepath, interpreter_path) -> ELF
24312432
24322433
Patches the interpreter of the ELF to the given binary using the `patchelf utility <https://github.com/NixOS/patchelf>`_.
24332434
@@ -2461,7 +2462,7 @@ def set_interpreter(exepath, interpreter_path):
24612462

24622463
@staticmethod
24632464
def patch_custom_libraries(exe_path, custom_library_path, create_copy=True, suffix='_remotelibc'):
2464-
r"""patch_custom_libraries(str, str, bool, str) -> ELF
2465+
r"""patch_custom_libraries(exe_path, custom_library_path, create_copy=True, suffix='_remotelibc') -> ELF
24652466
24662467
Looks for the interpreter binary in the given path and patches the binary to use
24672468
it if available. Also patches the RUNPATH to the given path using the `patchelf utility <https://github.com/NixOS/patchelf>`_.

pwnlib/fmtstr.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,12 @@ def fmtstr_payload(offset, writes, numbwritten=0, write_size='byte', write_size_
841841
The overflows argument is a format-string-length to output-amount tradeoff:
842842
Larger values for ``overflows`` produce shorter format strings that generate more output at runtime.
843843
844+
The writes argument is a dictionary with address/value pairs like ``{addr: value, addr2: value2}``.
845+
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).
846+
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),
847+
then provide a bytestring like ``b'\x37\x13'`` or ``p16(0x1337)``.
848+
Note that the ``write_size`` argument does not determine **total** bytes written, only the size of each consecutive write.
849+
844850
Arguments:
845851
offset(int): the first formatter's offset you control
846852
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_
857863
>>> context.clear(arch = 'amd64')
858864
>>> fmtstr_payload(1, {0x0: 0x1337babe}, write_size='int')
859865
b'%322419390c%4$llnaaaabaa\x00\x00\x00\x00\x00\x00\x00\x00'
866+
>>> fmtstr_payload(1, {0x0: p32(0x1337babe)}, write_size='int')
867+
b'%322419390c%3$na\x00\x00\x00\x00\x00\x00\x00\x00'
860868
>>> fmtstr_payload(1, {0x0: 0x1337babe}, write_size='short')
861869
b'%47806c%5$lln%22649c%6$hnaaaabaa\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00'
862870
>>> fmtstr_payload(1, {0x0: 0x1337babe}, write_size='byte')
@@ -872,6 +880,8 @@ def fmtstr_payload(offset, writes, numbwritten=0, write_size='byte', write_size_
872880
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'
873881
>>> fmtstr_payload(1, {0x0: 0x00000001}, write_size='byte')
874882
b'c%3$naaa\x00\x00\x00\x00'
883+
>>> fmtstr_payload(1, {0x0: b'\x01'}, write_size='byte')
884+
b'c%3$hhna\x00\x00\x00\x00'
875885
>>> fmtstr_payload(1, {0x0: b"\xff\xff\x04\x11\x00\x00\x00\x00"}, write_size='short')
876886
b'%327679c%7$lln%18c%8$hhn\x00\x00\x00\x00\x03\x00\x00\x00'
877887
>>> fmtstr_payload(10, {0x404048 : 0xbadc0ffe, 0x40403c : 0xdeadbeef}, no_dollars=True)
@@ -999,7 +1009,7 @@ def write(self, addr, data):
9991009
10001010
Arguments:
10011011
addr(int): the address where you want to write
1002-
data(int): the data that you want to write ``addr``
1012+
data(int or bytes): the data that you want to write ``addr``
10031013
10041014
Returns:
10051015
None
@@ -1013,6 +1023,10 @@ def write(self, addr, data):
10131023
>>> f.write(0x08040506, 0x1337babe)
10141024
>>> f.execute_writes()
10151025
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'
1026+
>>> f2 = FmtStr(send_fmt_payload, offset=5)
1027+
>>> f2.write(0x08040506, p16(0x1337))
1028+
>>> f2.execute_writes()
1029+
b'%19c%11$hhn%36c%12$hhnaa\x07\x05\x04\x08\x06\x05\x04\x08'
10161030
10171031
"""
10181032
self.writes[addr] = data

0 commit comments

Comments
 (0)