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:
  • n (int) – The number to swap.
  • width (int) – The width of the integer

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.bnot(value, width=None)[source]

Returns the binary inverse of ‘value’.

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)[source]
hexdump(s, width = 16, skip = True, hexii = False, begin = 0,
style = None, highlight = None, cyclic = False) -> str generator

Return a hexdump-dump of a string.

Parameters:
  • s (str) – The data to hexdump.
  • width (int) – The number of characters per line
  • 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  [email protected]  .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
pwnlib.util.fiddling.hexdump_iter(fd, width=16, skip=True, hexii=False, begin=0, style=None, highlight=None, cyclic=False)[source]
hexdump_iter(s, width = 16, skip = True, hexii = False, begin = 0,
style = None, highlight = None, cyclic = False) -> 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() or hexdump() to dump a string.
  • width (int) – The number of characters per line
  • 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:
  • s (str) – The string to dump
  • width (int) – The number of characters per line
  • skip (bool) – Should repeated lines be replaced by a “*”
Returns:

A HEXII-dump in the form of a string.

pwnlib.util.fiddling.isprint(c) → bool[source]

Return True if a character is printable

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.negate(value, width=None)[source]

Returns the two’s complement of ‘value’.

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:
  • n – The value to rotate.
  • k (int) – The rotation amount. Can be a positive or negative number.
  • word_size (int) – If n is a number, then this is the assumed bitsize of n. Defaults to pwnlib.context.word_size if None .

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 produce data, while neither the XOR value or XOR string contain any bytes in avoid.

Parameters:
  • data (str) – The desired string.
  • avoid – The list of disallowed characters. Defaults to nulls and newlines.
  • size (int) – Size of the desired output value, default is word size.
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')