pwnlib.util.fiddling
— Utilities bit fiddling
- pwnlib.util.fiddling.b64d(s) str [source]
Base64 decodes a string
Example
>>> b64d('dGVzdA==') b'test'
- pwnlib.util.fiddling.b64e(s) str [source]
Base64 encodes a string
Example
>>> b64e(b"test") 'dGVzdA=='
- pwnlib.util.fiddling.bits(s, endian='big', zero=0, one=1) list [source]
Converts the argument into a list of bits.
- Parameters
s – A string or number to be converted into bits.
endian (str) – The binary endian, default ‘big’.
zero – The representing a 0-bit.
one – The representing a 1-bit.
- Returns
A list consisting of the values specified in zero and one.
Examples
>>> bits(511, zero = "+", one = "-") ['+', '+', '+', '+', '+', '+', '+', '-', '-', '-', '-', '-', '-', '-', '-', '-'] >>> sum(bits(b"test")) 17 >>> bits(0) [0, 0, 0, 0, 0, 0, 0, 0]
- pwnlib.util.fiddling.bits_str(s, endian='big', zero='0', one='1') str [source]
A wrapper around
bits()
, which converts the output into a string.Examples
>>> bits_str(511) '0000000111111111' >>> bits_str(b"bits_str", endian = "little") '0100011010010110001011101100111011111010110011100010111001001110'
- pwnlib.util.fiddling.bitswap(s) str [source]
Reverses the bits in every byte of a given string.
Example
>>> bitswap(b"1234") b'\x8cL\xcc,'
- pwnlib.util.fiddling.bitswap_int(n) int [source]
Reverses the bits of a numbers and returns the result as a new number.
Examples
>>> hex(bitswap_int(0x1234, 8)) '0x2c' >>> hex(bitswap_int(0x1234, 16)) '0x2c48' >>> hex(bitswap_int(0x1234, 24)) '0x2c4800' >>> hex(bitswap_int(0x1234, 25)) '0x589000'
- pwnlib.util.fiddling.enhex(x) str [source]
Hex-encodes a string.
Example
>>> enhex(b"test") '74657374'
- pwnlib.util.fiddling.hexdump(s, width=16, skip=True, hexii=False, begin=0, style=None, highlight=None, cyclic=False, groupsize=4, total=True)[source]
- hexdump(s, width = 16, skip = True, hexii = False, begin = 0, style = None,
highlight = None, cyclic = False, groupsize=4, total = True) -> str
Return a hexdump-dump of a string.
- Parameters
s (bytes) – The data to hexdump.
width (int) – The number of characters per line
groupsize (int) – The number of characters per group
skip (bool) – Set to True, if repeated lines should be replaced by a “*”
hexii (bool) – Set to True, if a hexii-dump should be returned instead of a hexdump.
begin (int) – Offset of the first byte to print in the left column
style (dict) – Color scheme to use.
highlight (iterable) – Byte values to highlight.
cyclic (bool) – Attempt to skip consecutive, unmodified cyclic lines
total (bool) – Set to True, if total bytes should be printed
- Returns
A hexdump-dump in the form of a string.
Examples
>>> print(hexdump(b"abc")) 00000000 61 62 63 │abc│ 00000003
>>> print(hexdump(b'A'*32)) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│ * 00000020
>>> print(hexdump(b'A'*32, width=8)) 00000000 41 41 41 41 41 41 41 41 │AAAA│AAAA│ * 00000020
>>> print(hexdump(cyclic(32), width=8, begin=0xdead0000, hexii=True)) dead0000 .a .a .a .a .b .a .a .a │ dead0008 .c .a .a .a .d .a .a .a │ dead0010 .e .a .a .a .f .a .a .a │ dead0018 .g .a .a .a .h .a .a .a │ dead0020
>>> print(hexdump(bytearray(range(256)))) 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f │····│····│····│····│ 00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f │····│····│····│····│ 00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f │ !"#│$%&'│()*+│,-./│ 00000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f │0123│4567│89:;│<=>?│ 00000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f │@ABC│DEFG│HIJK│LMNO│ 00000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f │PQRS│TUVW│XYZ[│\]^_│ 00000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f │`abc│defg│hijk│lmno│ 00000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f │pqrs│tuvw│xyz{│|}~·│ 00000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f │····│····│····│····│ 00000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f │····│····│····│····│ 000000a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af │····│····│····│····│ 000000b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf │····│····│····│····│ 000000c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf │····│····│····│····│ 000000d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df │····│····│····│····│ 000000e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef │····│····│····│····│ 000000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff │····│····│····│····│ 00000100
>>> print(hexdump(bytearray(range(256)), hexii=True)) 00000000 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f │ 00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f │ 00000020 20 .! ." .# .$ .% .& .' .( .) .* .+ ., .- .. ./ │ 00000030 .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .: .; .< .= .> .? │ 00000040 .@ .A .B .C .D .E .F .G .H .I .J .K .L .M .N .O │ 00000050 .P .Q .R .S .T .U .V .W .X .Y .Z .[ .\ .] .^ ._ │ 00000060 .` .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o │ 00000070 .p .q .r .s .t .u .v .w .x .y .z .{ .| .} .~ 7f │ 00000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f │ 00000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f │ 000000a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af │ 000000b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf │ 000000c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf │ 000000d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df │ 000000e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef │ 000000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ## │ 00000100
>>> print(hexdump(b'X' * 64)) 00000000 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ * 00000040
>>> print(hexdump(b'X' * 64, skip=False)) 00000000 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ 00000010 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ 00000020 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ 00000030 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ 00000040
>>> print(hexdump(fit({0x10: b'X'*0x20, 0x50-1: b'\xff'*20}, length=0xc0) + b'\x00'*32)) 00000000 61 61 61 61 62 61 61 61 63 61 61 61 64 61 61 61 │aaaa│baaa│caaa│daaa│ 00000010 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ * 00000030 6d 61 61 61 6e 61 61 61 6f 61 61 61 70 61 61 61 │maaa│naaa│oaaa│paaa│ 00000040 71 61 61 61 72 61 61 61 73 61 61 61 74 61 61 ff │qaaa│raaa│saaa│taa·│ 00000050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff │····│····│····│····│ 00000060 ff ff ff 61 7a 61 61 62 62 61 61 62 63 61 61 62 │···a│zaab│baab│caab│ 00000070 64 61 61 62 65 61 61 62 66 61 61 62 67 61 61 62 │daab│eaab│faab│gaab│ 00000080 68 61 61 62 69 61 61 62 6a 61 61 62 6b 61 61 62 │haab│iaab│jaab│kaab│ 00000090 6c 61 61 62 6d 61 61 62 6e 61 61 62 6f 61 61 62 │laab│maab│naab│oaab│ 000000a0 70 61 61 62 71 61 61 62 72 61 61 62 73 61 61 62 │paab│qaab│raab│saab│ 000000b0 74 61 61 62 75 61 61 62 76 61 61 62 77 61 61 62 │taab│uaab│vaab│waab│ 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│ * 000000e0
>>> print(hexdump(fit({0x10: b'X'*0x20, 0x50-1: b'\xff'*20}, length=0xc0) + b'\x00'*32, cyclic=1)) 00000000 61 61 61 61 62 61 61 61 63 61 61 61 64 61 61 61 │aaaa│baaa│caaa│daaa│ 00000010 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ * 00000030 6d 61 61 61 6e 61 61 61 6f 61 61 61 70 61 61 61 │maaa│naaa│oaaa│paaa│ 00000040 71 61 61 61 72 61 61 61 73 61 61 61 74 61 61 ff │qaaa│raaa│saaa│taa·│ 00000050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff │····│····│····│····│ 00000060 ff ff ff 61 7a 61 61 62 62 61 61 62 63 61 61 62 │···a│zaab│baab│caab│ 00000070 64 61 61 62 65 61 61 62 66 61 61 62 67 61 61 62 │daab│eaab│faab│gaab│ * 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│ * 000000e0
>>> print(hexdump(fit({0x10: b'X'*0x20, 0x50-1: b'\xff'*20}, length=0xc0) + b'\x00'*32, cyclic=1, hexii=1)) 00000000 .a .a .a .a .b .a .a .a .c .a .a .a .d .a .a .a │ 00000010 .X .X .X .X .X .X .X .X .X .X .X .X .X .X .X .X │ * 00000030 .m .a .a .a .n .a .a .a .o .a .a .a .p .a .a .a │ 00000040 .q .a .a .a .r .a .a .a .s .a .a .a .t .a .a ## │ 00000050 ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## │ 00000060 ## ## ## .a .z .a .a .b .b .a .a .b .c .a .a .b │ 00000070 .d .a .a .b .e .a .a .b .f .a .a .b .g .a .a .b │ * 000000c0 │ * 000000e0
>>> print(hexdump(b'A'*16, width=9)) 00000000 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│A│ 00000009 41 41 41 41 41 41 41 │AAAA│AAA│ 00000010 >>> print(hexdump(b'A'*16, width=10)) 00000000 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AA│ 0000000a 41 41 41 41 41 41 │AAAA│AA│ 00000010 >>> print(hexdump(b'A'*16, width=11)) 00000000 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAA│ 0000000b 41 41 41 41 41 │AAAA│A│ 00000010 >>> print(hexdump(b'A'*16, width=12)) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│ 0000000c 41 41 41 41 │AAAA│ 00000010 >>> print(hexdump(b'A'*16, width=13)) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│A│ 0000000d 41 41 41 │AAA│ 00000010 >>> print(hexdump(b'A'*16, width=14)) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AA│ 0000000e 41 41 │AA│ 00000010 >>> print(hexdump(b'A'*16, width=15)) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAA│ 0000000f 41 │A│ 00000010
>>> print(hexdump(b'A'*24, width=16, groupsize=8)) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAAAAAA│AAAAAAAA│ 00000010 41 41 41 41 41 41 41 41 │AAAAAAAA│ 00000018 >>> print(hexdump(b'A'*24, width=16, groupsize=-1)) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAAAAAAAAAAAAAA│ 00000010 41 41 41 41 41 41 41 41 │AAAAAAAA│ 00000018
>>> print(hexdump(b'A'*24, width=16, total=False)) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│ 00000010 41 41 41 41 41 41 41 41 │AAAA│AAAA│ >>> print(hexdump(b'A'*24, width=16, groupsize=8, total=False)) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAAAAAA│AAAAAAAA│ 00000010 41 41 41 41 41 41 41 41 │AAAAAAAA│
- pwnlib.util.fiddling.hexdump_iter(fd, width=16, skip=True, hexii=False, begin=0, style=None, highlight=None, cyclic=False, groupsize=4, total=True)[source]
- hexdump_iter(s, width = 16, skip = True, hexii = False, begin = 0, style = None,
highlight = None, cyclic = False, groupsize=4, total = True) -> str generator
Return a hexdump-dump of a string as a generator of lines. Unless you have massive amounts of data you probably want to use
hexdump()
.- Parameters
fd (file) – File object to dump. Use
StringIO.StringIO()
orhexdump()
to dump a string.width (int) – The number of characters per line
groupsize (int) – The number of characters per group
skip (bool) – Set to True, if repeated lines should be replaced by a “*”
hexii (bool) – Set to True, if a hexii-dump should be returned instead of a hexdump.
begin (int) – Offset of the first byte to print in the left column
style (dict) – Color scheme to use.
highlight (iterable) – Byte values to highlight.
cyclic (bool) – Attempt to skip consecutive, unmodified cyclic lines
total (bool) – Set to True, if total bytes should be printed
- Returns
A generator producing the hexdump-dump one line at a time.
Example
>>> tmp = tempfile.NamedTemporaryFile() >>> _ = tmp.write(b'XXXXHELLO, WORLD') >>> tmp.flush() >>> _ = tmp.seek(4) >>> print('\n'.join(hexdump_iter(tmp))) 00000000 48 45 4c 4c 4f 2c 20 57 4f 52 4c 44 │HELL│O, W│ORLD│ 0000000c
>>> t = tube() >>> t.unrecv(b'I know kung fu') >>> print('\n'.join(hexdump_iter(t))) 00000000 49 20 6b 6e 6f 77 20 6b 75 6e 67 20 66 75 │I kn│ow k│ung │fu│ 0000000e
- pwnlib.util.fiddling.js_escape(data, padding=context.cyclic_alphabet[0:1], endian = None, **kwargs) str [source]
Pack data as an escaped Unicode string for use in JavaScript’s unescape() function
- Parameters
- Returns
A string representation of the packed data
>>> js_escape(b'\xde\xad\xbe\xef') '%uadde%uefbe'
>>> js_escape(b'\xde\xad\xbe\xef', endian='big') '%udead%ubeef'
>>> js_escape(b'\xde\xad\xbe') '%uadde%u61be'
>>> js_escape(b'aaaa') '%u6161%u6161'
- pwnlib.util.fiddling.js_unescape(s, endian=None, **kwargs) bytes [source]
Unpack an escaped Unicode string from JavaScript’s escape() function
- Parameters
- Returns
A bytes representation of the unpacked data
>>> js_unescape('%uadde%uefbe') b'\xde\xad\xbe\xef'
>>> js_unescape('%udead%ubeef', endian='big') b'\xde\xad\xbe\xef'
>>> js_unescape('abc%u4141123') b'a\x00b\x00c\x00AA1\x002\x003\x00'
>>> data = b'abcdABCD1234!@#$\x00\x01\x02\x03\x80\x81\x82\x83' >>> js_unescape(js_escape(data)) == data True
>>> js_unescape('%u4141%u42') Traceback (most recent call last): ValueError: Incomplete Unicode token: %u42
>>> js_unescape('%u4141%uwoot%4141') Traceback (most recent call last): ValueError: Failed to decode token: %uwoot
>>> js_unescape('%u4141%E4%F6%FC%u4141') Traceback (most recent call last): NotImplementedError: Non-Unicode % tokens are not supported: %E4
>>> js_unescape('%u4141%zz%u4141') Traceback (most recent call last): ValueError: Bad % token: %zz
- pwnlib.util.fiddling.naf(int) int generator [source]
Returns a generator for the non-adjacent form (NAF[1]) of a number, n. If naf(n) generates z_0, z_1, …, then n == z_0 + z_1 * 2 + z_2 * 2**2, ….
[1] https://en.wikipedia.org/wiki/Non-adjacent_form
Example
>>> n = 45 >>> m = 0 >>> x = 1 >>> for z in naf(n): ... m += x * z ... x *= 2 >>> n == m True
- pwnlib.util.fiddling.randoms(count, alphabet=string.ascii_lowercase) str [source]
Returns a random string of a given length using only the specified alphabet.
- Parameters
count (int) – The length of the desired string.
alphabet – The alphabet of allowed characters. Defaults to all lowercase characters.
- Returns
A random string.
Example
>>> randoms(10) 'evafjilupm'
- pwnlib.util.fiddling.rol(n, k, word_size=None)[source]
Returns a rotation by k of n.
When n is a number, then means
((n << k) | (n >> (word_size - k)))
truncated to word_size bits.When n is a list, tuple or string, this is
n[k % len(n):] + n[:k % len(n)]
.- Parameters
Example
>>> rol('abcdefg', 2) 'cdefgab' >>> rol('abcdefg', -2) 'fgabcde' >>> hex(rol(0x86, 3, 8)) '0x34' >>> hex(rol(0x86, -3, 8)) '0xd0'
- pwnlib.util.fiddling.ror(n, k, word_size=None)[source]
A simple wrapper around
rol()
, which negates the values of k.
- pwnlib.util.fiddling.tty_escape(s, lnext=b'\x16', dangerous=bytes(bytearray(range(0x20)))) bytes [source]
Escape data for terminal output. This is useful when sending data to a terminal that may interpret certain bytes as control characters.
Check
stty --all
for the current settings on your terminal.- Parameters
- Returns
The escaped data.
>>> tty_escape(b'abc\x04d\x18e\x16f') b'abc\x16\x04d\x16\x18e\x16\x16f'
- pwnlib.util.fiddling.unbits(s, endian='big') str [source]
Converts an iterable of bits into a string.
- Parameters
s – Iterable of bits
endian (str) – The string “little” or “big”, which specifies the bits endianness.
- Returns
A string of the decoded bits.
Example
>>> unbits([1]) b'\x80' >>> unbits([1], endian = 'little') b'\x01' >>> unbits(bits(b'hello'), endian = 'little') b'\x16\xa666\xf6'
- pwnlib.util.fiddling.unhex(s) str [source]
Hex-decodes a string.
Example
>>> unhex("74657374") b'test' >>> unhex("F\n") b'\x0f' >>> unhex(bytearray(b" F ")) b'\x0f'
- pwnlib.util.fiddling.urldecode(s, ignore_invalid=False) str [source]
URL-decodes a string.
Example
>>> urldecode("test%20%41") 'test A' >>> urldecode("%qq") Traceback (most recent call last): ... ValueError: Invalid input to urldecode >>> urldecode("%qq", ignore_invalid = True) '%qq'
- pwnlib.util.fiddling.urlencode(s) str [source]
URL-encodes a string.
Example
>>> urlencode("test") '%74%65%73%74'
- pwnlib.util.fiddling.xor(*args, cut='max') str [source]
Flattens its arguments using
pwnlib.util.packing.flat()
and then xors them together. If the end of a string is reached, it wraps around in the string.- Parameters
args – The arguments to be xor’ed together.
cut – How long a string should be returned. Can be either ‘min’/’max’/’left’/’right’ or a number.
- Returns
The string of the arguments xor’ed together.
Example
>>> xor(b'lol', b'hello', 42) b'. ***' >>> xor(cut = 'min', other = '') Traceback (most recent call last): ... TypeError: xor() got an unexpected keyword argument 'other'
- pwnlib.util.fiddling.xor_key(data, size=None, avoid='\x00\n')[source]
Finds a
size
-width value that can be XORed with a string to producedata
, while neither the XOR value or XOR string contain any bytes inavoid
.- Parameters
- Returns
A tuple containing two strings; the XOR key and the XOR string. If no such pair exists, None is returned.
Example
>>> xor_key(b"Hello, world") (b'\x01\x01\x01\x01', b'Idmmn-!vnsme')
- pwnlib.util.fiddling.xor_pair(data, avoid='\x00\n')[source]
Finds two strings that will xor into a given string, while only using a given alphabet.
- Parameters
data (str) – The desired string.
avoid – The list of disallowed characters. Defaults to nulls and newlines.
- Returns
Two strings which will xor to the given string. If no such two strings exist, then None is returned.
Example
>>> xor_pair(b"test") (b'\x01\x01\x01\x01', b'udru')