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.

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(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() or hexdump() 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.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.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:
  • data (bytes) – Bytes to pack

  • padding (bytes) – A single byte to use as padding if data is of uneven length

  • endian (str) – Endianness with which to pack the string (“little”/”big”)

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:
  • s (str) – Escaped string to unpack

  • endian (str) – Endianness with which to unpack the string (“little”/”big”)

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

Returns the two’s complement of ‘value’.

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:
  • 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.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:
  • s (bytes) – The data to escape

  • lnext (bytes) – The byte to prepend to escape the next character. Defaults to ^V.

  • dangerous (bytes) – The bytes to escape

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 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(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')