-1

I am currently looking for a fuzzer for Python dictionaries. I am already aware of some fuzzing tools such as:

However, they seem a bit broader of what I am looking for. Actually, my goal is to provide a Python dictionary to a given tool and obtain a new dictionary very similar to the input one but with some values changed.

For instance, providing

{k1: "aaa", k2: "bbb", k3: "ccc"}

I intend to obtain the following new dictionaries:

{k1: "aaj", k2: "bbb", k3: "ccc"}
{k1: "aaa", k2: "bbr", k3: "ccc"}
{k1: "aaa", k2: "bbb", k3: "ccp"}
...

Are you aware of this kind of tools? Any suggestion will be welcomed.

In the best of the scenarios I would like this to be an open source tool.

EDIT1: I post the code I tryed up to the moment:

  def change_randomly(self, v):
    from random import randint
    import string

    new_v = list(v)
    pos_value = randint(0, len(v)-1)
    random_char = string.letters[randint(0, len(string.letters)-1)]

    new_v[pos_value] = str(random_char)
    return ''.join(new_v)

For sure, it may be improved, so I look forward for any thought regarding it.

Thanks!

pafede2
  • 1,626
  • 4
  • 23
  • 40
  • What's the size of your dictionaries and what do you mean by "some values"? Why not just randomly change some of the values? – Abdul Fatir Jun 14 '16 at 11:39
  • Please note that requests tor tools/libraries are explicitly off-topic. – jonrsharpe Jun 14 '16 at 11:45
  • Requesting help to finish a piece of code to accomplish this simple task is usually welcome here ;-) Would that be ok, that you sketch some code, and others help you where you are stuck? And as @AbdulFatir suggests/asks: Is there some reason, why in the sample only the third chacter of the value strings is changed and only exclusively? – Dilettant Jun 14 '16 at 11:49
  • 1
    The size of the dictionaries is between 10 and 25 keys, usually there is only one level, I mean the values more often than never are string of characters. I did not choose to generate them completely random because I want to be them to be pretty similar to the previous values. However, I will try to randomize the postfix of the values and so reaching my goal. Thanks for the insight. – pafede2 Jun 14 '16 at 11:50
  • @Dilettant that's: 1. also not quite true (if they've made an effort and got stuck then OK, but not if they just haven't tried that part yet); and 2. not what the OP has asked. – jonrsharpe Jun 14 '16 at 11:51
  • 1
    @Dilettant: it is not mandatory to change only the last position. As far as I understand the fuzzer tools use a kind of seed for choosing where and how to modify an input randomly. May be I can do it for myself. As soon as I have the time I will code it. – pafede2 Jun 14 '16 at 11:52
  • 2
    [Hypothesis](http://hypothesis.readthedocs.io/en/latest/) is a library which creates random input data to test functions. I don't think it can generate data by fuzzing but you could implement a strategy for it, see also [here](http://hypothesis.readthedocs.io/en/latest/examples.html#fuzzing-an-http-api). It's not what you were looking for but maybe it's interesting to you anyway. – syntonym Jun 14 '16 at 12:07
  • Please cf. my answer and thanks for the code - happy to find out again, that people not showing code upfront, have other reasons thatn not even trying, but are not sure if it is ok to show, etc. I hope my solution fits, helps you understand and decide. In production of course ready made libraries - as @syntonym suggests - are important to consider, but we're all coders here ... – Dilettant Jun 14 '16 at 12:23

1 Answers1

0

Based on the comments to the question, why not simply writing a fixed length template based fuzzer like this:

#! /usr/bin/env python
"""Minimal template based dict string value fuzzer."""
from __future__ import print_function

import random
import string


def random_string(rng, length, chars=string.printable):
    """A random string with given length."""
    return ''.join(rng.choice(chars) for _ in range(length))


def dict_string_template_fuzz_gen(rng, dict_in):
    """Given a random number generator rng, and starting from
    template dict_in expected to have only strings as values,
    this generator function yields derived dicts with random
    variations in the string values keeping the length of
    those identical."""

    while True:
        yield dict((k, random_string(rng, len(v))) for k, v in dict_in.items())


def main():
    """Drive a test run of minimal template fuzz."""

    k1, k2, k3 = 'ka', 'kb', 'kc'
    template = {k1: "aaa", k2: "bbb", k3: "ccc"}

    print("# Input(template):")
    print(template)

    rng = random.SystemRandom()
    print("# Output(fuzz):")
    for n, fuzz in enumerate(dict_string_template_fuzz_gen(rng,
                             template), start=0):
        print(fuzz)
        if n > 3:
            break

if __name__ == '__main__':
    main()

On the use case input it might yield this:

# Input(template):
{'kc': 'ccc', 'kb': 'bbb', 'ka': 'aaa'}
# Output(fuzz):
{'kc': '6HZ', 'kb': 'zoD', 'ka': '5>b'}
{'kc': '%<\r', 'kb': 'g>v', 'ka': 'Mo0'}
{'kc': 'Y $', 'kb': '4z.', 'ka': '0".'}
{'kc': '^M.', 'kb': 'QY1', 'ka': 'P0)'}
{'kc': 'FK4', 'kb': 'oZW', 'ka': 'G1q'}

So this should give the OP something to start as it might be a bootstrapping problem, where Python knowledge is only starting ...

I just hacked it in - PEP8 compliant though - and it should work no matter if Python v2 or v3.

Many open ends to work on ... but should get one going to evaluate, if a library or some simple enhanced coding might suffice. Only the OP will know but is welcome to comment on this answer proposal or update the question.

Hints: I nearly always use SystemRandom so you can parallelize more robustly. There may be faster ways, but performance was not visible to me in the specification. The print's are of course sprankled in as this is educational at best. HTH

Update: Having read the OP comment on changing only part of the strings to preserve some similarity, one could exchange above fuzzer function by e.g.:

def dict_string_template_fuzz_len_gen(rng, dict_in, f_len=1):
    """Given a random number generator rng, and starting from
    template dict_in expected to have only strings as values,
    this generator function yields derived dicts with random
    variations in the string values keeping the length of
    those identical.
    Added as hack the f_len parameter that counts the
    characters open to be fuzzed from the end of the string."""

    r_s = random_string  # shorten for line readability below
    while True:
        yield dict(
            (k, v[:f_len + 1] + r_s(rng, f_len)) for k, v in dict_in.items())

and then have as sample output:

# Input(template):
{'kc': 'ccc', 'kb': 'bbb', 'ka': 'aaa'}
# Output(fuzz):
{'kc': 'cc\t', 'kb': 'bbd', 'ka': 'aa\\'}
{'kc': 'cc&', 'kb': 'bbt', 'ka': 'aa\\'}
{'kc': 'ccg', 'kb': 'bb_', 'ka': 'aaJ'}
{'kc': 'ccc', 'kb': 'bbv', 'ka': 'aau'}
{'kc': 'ccw', 'kb': 'bbs', 'ka': "aa'"}

When calling this function instead of the other.

Dilettant
  • 3,267
  • 3
  • 29
  • 29