Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

packing: Do use extra arguments in p* and u* #2526

Merged
merged 3 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,12 @@ The table below shows which release corresponds to each branch, and what date th
- [#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
- [#2524][2524] Raise EOFError during `process.recv` when stdout closes on Windows
- [#2526][2526] Properly make use of extra arguments in `packing` utilities. `sign` parameter requires keyword syntax to specify it.

[2507]: https://github.com/Gallopsled/pwntools/pull/2507
[2522]: https://github.com/Gallopsled/pwntools/pull/2522
[2524]: https://github.com/Gallopsled/pwntools/pull/2524
[2526]: https://github.com/Gallopsled/pwntools/pull/2526

## 4.15.0 (`beta`)
- [#2508][2508] Ignore a warning when compiling with asm on nix
Expand Down
63 changes: 42 additions & 21 deletions pwnlib/util/packing.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ def routine(data, stacklevel=None):
#
# Make normal user-oriented packers, e.g. p8
#
def _do_packing(op, size, number):
def _do_packing(op, size, number, endianness=None):

name = "%s%s" % (op,size)
mod = sys.modules[__name__]
Expand All @@ -342,15 +342,15 @@ def _do_packing(op, size, number):
bs = getattr(mod, "_%sbs" % (name))
bu = getattr(mod, "_%sbu" % (name))

endian = context.endian
endian = endianness or context.endian
signed = context.signed
return {("little", True ): ls,
("little", False): lu,
("big", True ): bs,
("big", False): bu}[endian, signed](number, 3)

@LocalNoarchContext
def p8(number, endianness = None, sign = None, **kwargs):
def p8(number, endianness = None, **kwargs):
"""p8(number, endianness, sign, ...) -> bytes

Packs an 8-bit integer
Expand All @@ -365,10 +365,10 @@ def p8(number, endianness = None, sign = None, **kwargs):
Returns:
The packed number as a byte string
"""
return _do_packing('p', 8, number)
return _do_packing('p', 8, number, endianness)

@LocalNoarchContext
def p16(number, endianness = None, sign = None, **kwargs):
def p16(number, endianness = None, **kwargs):
"""p16(number, endianness, sign, ...) -> bytes

Packs an 16-bit integer
Expand All @@ -382,11 +382,18 @@ def p16(number, endianness = None, sign = None, **kwargs):

Returns:
The packed number as a byte string

Examples:

>>> p16(0x4142, 'big')
b'AB'
>>> p16(0x4142, endianness='big')
b'AB'
"""
return _do_packing('p', 16, number)
return _do_packing('p', 16, number, endianness)

@LocalNoarchContext
def p32(number, endianness = None, sign = None, **kwargs):
def p32(number, endianness = None, **kwargs):
"""p32(number, endianness, sign, ...) -> bytes

Packs an 32-bit integer
Expand All @@ -400,11 +407,18 @@ def p32(number, endianness = None, sign = None, **kwargs):

Returns:
The packed number as a byte string

Examples:

>>> p32(0x41424344, 'big')
b'ABCD'
>>> p32(0x41424344, endianness='big')
b'ABCD'
"""
return _do_packing('p', 32, number)
return _do_packing('p', 32, number, endianness)

@LocalNoarchContext
def p64(number, endianness = None, sign = None, **kwargs):
def p64(number, endianness = None, **kwargs):
"""p64(number, endianness, sign, ...) -> bytes

Packs an 64-bit integer
Expand All @@ -418,11 +432,18 @@ def p64(number, endianness = None, sign = None, **kwargs):

Returns:
The packed number as a byte string

Examples:

>>> p64(0x4142434445464748, 'big')
b'ABCDEFGH'
>>> p64(0x4142434445464748, endianness='big')
b'ABCDEFGH'
"""
return _do_packing('p', 64, number)
return _do_packing('p', 64, number, endianness)

@LocalNoarchContext
def u8(data, endianness = None, sign = None, **kwargs):
def u8(data, endianness = None, **kwargs):
"""u8(data, endianness, sign, ...) -> int

Unpacks an 8-bit integer
Expand All @@ -437,10 +458,10 @@ def u8(data, endianness = None, sign = None, **kwargs):
Returns:
The unpacked number
"""
return _do_packing('u', 8, data)
return _do_packing('u', 8, data, endianness)

@LocalNoarchContext
def u16(data, endianness = None, sign = None, **kwargs):
def u16(data, endianness = None, **kwargs):
"""u16(data, endianness, sign, ...) -> int

Unpacks an 16-bit integer
Expand All @@ -455,10 +476,10 @@ def u16(data, endianness = None, sign = None, **kwargs):
Returns:
The unpacked number
"""
return _do_packing('u', 16, data)
return _do_packing('u', 16, data, endianness)

@LocalNoarchContext
def u32(data, endianness = None, sign = None, **kwargs):
def u32(data, endianness = None, **kwargs):
"""u32(data, endianness, sign, ...) -> int

Unpacks an 32-bit integer
Expand All @@ -473,10 +494,10 @@ def u32(data, endianness = None, sign = None, **kwargs):
Returns:
The unpacked number
"""
return _do_packing('u', 32, data)
return _do_packing('u', 32, data, endianness)

@LocalNoarchContext
def u64(data, endianness = None, sign = None, **kwargs):
def u64(data, endianness = None, **kwargs):
"""u64(data, endianness, sign, ...) -> int

Unpacks an 64-bit integer
Expand All @@ -491,7 +512,7 @@ def u64(data, endianness = None, sign = None, **kwargs):
Returns:
The unpacked number
"""
return _do_packing('u', 64, data)
return _do_packing('u', 64, data, endianness)

def make_packer(word_size = None, sign = None, **kwargs):
"""make_packer(word_size = None, endianness = None, sign = None) -> number → str
Expand Down Expand Up @@ -775,7 +796,7 @@ def flat(*args, **kwargs):
Examples:

(Test setup, please ignore)

>>> context.clear()

Basic usage of :meth:`flat` works similar to the pack() routines.
Expand Down Expand Up @@ -822,7 +843,7 @@ def flat(*args, **kwargs):

Dictionary usage permits directly using values derived from :func:`.cyclic`.
See :func:`.cyclic`, :function:`pwnlib.context.context.cyclic_alphabet`, and :data:`.context.cyclic_size`
for more options.
for more options.

The cyclic pattern can be provided as either the text or hexadecimal offset.

Expand Down Expand Up @@ -873,7 +894,7 @@ def flat(*args, **kwargs):

Negative indices are also supported, though this only works for integer
keys.

>>> flat({-4: b'x', -1: b'A', 0: b'0', 4: b'y'})
b'xaaA0aaay'
"""
Expand Down
Loading