pwnlib.util.cyclic — Generation of unique sequences

pwnlib.util.cyclic.cyclic(length = None, alphabet = None, n = None) → list/str[source]

A simple wrapper over de_bruijn(). This function returns at most length elements.

If the given alphabet is a string, a string is returned from this function. Otherwise a list is returned.

Parameters:
  • length – The desired length of the list or None if the entire sequence is desired.
  • alphabet – List or string to generate the sequence over.
  • n (int) – The length of subsequences that should be unique.

Notes

The maximum length is len(alphabet)**n.

The default values for alphabet and n restrict the total space to ~446KB.

If you need to generate a longer cyclic pattern, provide a longer alphabet, or if possible a larger n.

Example

Cyclic patterns are usually generated by providing a specific length.

>>> cyclic(20)
'aaaabaaacaaadaaaeaaa'
>>> cyclic(32)
'aaaabaaacaaadaaaeaaafaaagaaahaaa'

The alphabet and n arguments will control the actual output of the pattern

>>> cyclic(20, alphabet=string.ascii_uppercase)
'AAAABAAACAAADAAAEAAA'
>>> cyclic(20, n=8)
'aaaaaaaabaaaaaaacaaa'
>>> cyclic(20, n=2)
'aabacadaeafagahaiaja'

The size of n and alphabet limit the maximum length that can be generated. Without providing length, the entire possible cyclic space is generated.

>>> cyclic(alphabet = "ABC", n = 3)
'AAABAACABBABCACBACCBBBCBCCC'
>>> cyclic(length=512, alphabet = "ABC", n = 3)
Traceback (most recent call last):
...
PwnlibException: Can't create a pattern length=512 with len(alphabet)==3 and n==3

The alphabet can be set in context, which is useful for circumstances when certain characters are not allowed. See context.cyclic_alphabet.

>>> context.cyclic_alphabet = "ABC"
>>> cyclic(10)
'AAAABAAACA'

The original values can always be restored with:

>>> context.clear()

The following just a test to make sure the length is correct.

>>> alphabet, n = range(30), 3
>>> len(alphabet)**n, len(cyclic(alphabet = alphabet, n = n))
(27000, 27000)
pwnlib.util.cyclic.cyclic_find(subseq, alphabet = None, n = None) → int[source]

Calculates the position of a substring into a De Bruijn sequence.

Parameters:
  • subseq – The subsequence to look for. This can be a string, a list or an integer. If an integer is provided it will be packed as a little endian integer.
  • alphabet – List or string to generate the sequence over. By default, uses context.cyclic_alphabet.
  • n (int) – The length of subsequences that should be unique. By default, uses context.cyclic_size.

Examples

Let’s generate an example cyclic pattern.

>>> cyclic(16)
'aaaabaaacaaadaaa'

Note that ‘baaa’ starts at offset 4. The cyclic_find routine shows us this:

>>> cyclic_find('baaa')
4

The default length of a subsequence generated by cyclic is 4. If a longer value is submitted, it is automatically truncated to four bytes.

>>> cyclic_find('baaacaaa')
4

If you provided e.g. n=8 to cyclic to generate larger subsequences, you must explicitly provide that argument.

>>> cyclic_find('baaacaaa', n=8)
3515208

We can generate a large cyclic pattern, and grab a subset of it to check a deeper offset.

>>> cyclic_find(cyclic(1000)[514:518])
514

Instead of passing in the byte representation of the pattern, you can also pass in the integer value. Note that this is sensitive to the selected endianness via context.endian.

>>> cyclic_find(0x61616162)
4
>>> cyclic_find(0x61616162, endian='big')
1

You can use anything for the cyclic pattern, including non-printable characters.

>>> cyclic_find(0x00000000, alphabet=unhex('DEADBEEF00'))
621
pwnlib.util.cyclic.cyclic_metasploit(length = None, sets = [ string.ascii_uppercase, string.ascii_lowercase, string.digits ]) → str[source]

A simple wrapper over metasploit_pattern(). This function returns a string of length length.

Parameters:
  • length – The desired length of the string or None if the entire sequence is desired.
  • sets – List of strings to generate the sequence over.

Example

>>> cyclic_metasploit(32)
'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab'
>>> cyclic_metasploit(sets = ["AB","ab","12"])
'Aa1Aa2Ab1Ab2Ba1Ba2Bb1Bb2'
>>> cyclic_metasploit()[1337:1341]
'5Bs6'
>>> len(cyclic_metasploit())
20280
pwnlib.util.cyclic.cyclic_metasploit_find(subseq, sets = [ string.ascii_uppercase, string.ascii_lowercase, string.digits ]) → int[source]

Calculates the position of a substring into a Metasploit Pattern sequence.

Parameters:
  • subseq – The subsequence to look for. This can be a string or an integer. If an integer is provided it will be packed as a little endian integer.
  • sets – List of strings to generate the sequence over.

Examples

>>> cyclic_metasploit_find(cyclic_metasploit(1000)[514:518])
514
>>> cyclic_metasploit_find(0x61413161)
4
pwnlib.util.cyclic.de_bruijn(alphabet = None, n = None) → generator[source]

Generator for a sequence of unique substrings of length n. This is implemented using a De Bruijn Sequence over the given alphabet.

The returned generator will yield up to len(alphabet)**n elements.

Parameters:
  • alphabet – List or string to generate the sequence over.
  • n (int) – The length of subsequences that should be unique.
pwnlib.util.cyclic.metasploit_pattern(sets = [ string.ascii_uppercase, string.ascii_lowercase, string.digits ]) → generator[source]

Generator for a sequence of characters as per Metasploit Framework’s Rex::Text.pattern_create (aka pattern_create.rb).

The returned generator will yield up to len(sets) * reduce(lambda x,y: x*y, map(len, sets)) elements.

Parameters:sets – List of strings to generate the sequence over.