pwnlib.util.fiddling
— Utilities bit fiddling¶
-
pwnlib.util.fiddling.
b64d
(s) → str[source]¶ Base64 decodes a string
Example
>>> b64d('dGVzdA==') 'test'
-
pwnlib.util.fiddling.
b64e
(s) → str[source]¶ Base64 encodes a string
Example
>>> b64e("test") 'dGVzdA=='
-
pwnlib.util.fiddling.
bits
(s, endian = 'big', zero = 0, one = 1) → list[source]¶ Converts the argument 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("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("bits_str", endian = "little") '0100011010010110001011101100111011111010110011100010111001001110'
-
pwnlib.util.fiddling.
bitswap
(s) → str[source]¶ Reverses the bits in every byte of a given string.
Example
>>> bitswap("1234") '\x8cL\xcc,'
-
pwnlib.util.fiddling.
bitswap_int
(n) → int[source]¶ Reverses the bits of a numbers and returns the result as a new number.
Parameters: 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("test") '74657374'
-
pwnlib.util.fiddling.
hexdump
(s, width=16, skip=True, hexii=False, begin=0, style=None, highlight=None, cyclic=False, groupsize=4)[source]¶ - hexdump(s, width = 16, skip = True, hexii = False, begin = 0,
- style = None, highlight = None, cyclic = False, groupsize=4) -> str generator
Return a hexdump-dump of a string.
Parameters: - s (str) – 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
Returns: A hexdump-dump in the form of a string.
Examples
>>> print hexdump("abc") 00000000 61 62 63 │abc│ 00000003
>>> print hexdump('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('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(list(map(chr, 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(list(map(chr, 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('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('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: 'X'*0x20, 0x50-1: '\xff'*20}, length=0xc0) + '\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: 'X'*0x20, 0x50-1: '\xff'*20}, length=0xc0) + '\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: 'X'*0x20, 0x50-1: '\xff'*20}, length=0xc0) + '\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('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('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('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('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('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('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('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('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('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
-
pwnlib.util.fiddling.
hexdump_iter
(fd, width=16, skip=True, hexii=False, begin=0, style=None, highlight=None, cyclic=False, groupsize=4)[source]¶ - hexdump_iter(s, width = 16, skip = True, hexii = False, begin = 0,
- style = None, highlight = None, cyclic = False, groupsize=4) -> 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
Returns: A generator producing the hexdump-dump one line at a time.
Example
>>> tmp = tempfile.NamedTemporaryFile() >>> tmp.write('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('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.
hexii
(s, width = 16, skip = True) → str[source]¶ Return a HEXII-dump of a string.
Parameters: Returns: A HEXII-dump in the form of a string.
-
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.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.
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]) '\x80' >>> unbits([1], endian = 'little') '\x01' >>> unbits(bits('hello'), endian = 'little') '\x16\xa666\xf6'
-
pwnlib.util.fiddling.
unhex
(s) → str[source]¶ Hex-decodes a string.
Example
>>> unhex("74657374") 'test' >>> unhex("F\n") '\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('lol', 'hello', 42) '. ***'
-
pwnlib.util.fiddling.
xor_key
(data, size=None, avoid='x00n') -> None or (int, str)[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("Hello, world") ('\x01\x01\x01\x01', 'Idmmn-!vnsme')
-
pwnlib.util.fiddling.
xor_pair
(data, avoid = 'x00n') -> None or (str, str)[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("test") ('\x01\x01\x01\x01', 'udru')