def __init__(self, name, min_length=0, max_length=10000, max_count=1, bytes_set=ASCII0): BytesGenerator.__init__(self, min_length, max_length, bytes_set) EnvironmentVariable.__init__(self, name, max_count)
def __init__(self, name, min_length=0, max_length=2000, characters=None, max_count=1): if not characters: characters = set('A') BytesGenerator.__init__(self, min_length, max_length, characters) EnvironmentVariable.__init__(self, name, max_count)
class FuzzyFunctionC(FunctionC): def __init__(self, name, arguments=None, type="void", random_bytes=400): FunctionC.__init__(self, name, arguments, type) self.bytes_generator = BytesGenerator(random_bytes, random_bytes) self.buffer_count = 0 self.special_int32 = (0x8000, 0xffff, 0x80000000) def createInt32(self): state = randint(1, 3) if state == 1: return choice(self.special_int32) elif state == 2: return (0xffffff00 | randint(0, 255)) else: return randint(MIN_INT32, MAX_INT32) def createInt(self): return self.createInt32() def createRandomBytes(self): self.buffer_count += 1 name = "buffer%s" % self.buffer_count value = self.bytes_generator.createValue() size = len(value) value = ', '.join("0x%02x" % ord(item) for item in value) self.variables.append("const char %s[] = {%s}" % (name, value)) return (name, size)
class MyProcess(ProjectProcess): def __init__(self, project, arguments, **kw): ProjectProcess.__init__(self, project, arguments, **kw) self.options = 'Vqfldbv' VALUE_SET = DECIMAL_DIGITS | set('.:-/ ') self.stdin_generator = BytesGenerator(1, 5000) self.value_generator = BytesGenerator(1, 30, VALUE_SET) self.queue_generator = BytesGenerator(1, 1, ASCII0) self.filename_generator = UnixPathGenerator(100) self.min_opt = 0 self.max_opt = 2 def createOption(self): option = choice(self.options) arg = '-' + option if option == 'q': return [arg, self.queue_generator.createValue()] elif option == 'f': return [arg, self.filename_generator.createValue()] else: return [arg] def createStdin(self): data = self.stdin_generator.createValue() filename = self.project().session.directory.uniqueFilename('stdin') open(filename, 'w').write(data) self.popen_args['stdin'] = open(filename, 'r') def createArguments(self): self.createStdin() arguments = self.cmdline.create() nb_opt = randint(self.min_opt, self.max_opt) for index in xrange(1, nb_opt+1): arg = self.createOption() arguments.extend(arg) timestamp = self.value_generator.createValue() arguments.append(timestamp) self.error("Arguments = %r" % arguments) return arguments def on_process_done(self, agent, status): system(self, r""" bash -c 'atq|awk "{print \$1}"|xargs -r atrm'""")
def __init__(self, filename, module, module_name): self.simple_argument_generators = ( self.genNone, self.genBool, self.genSmallUint, self.genInt, self.genLetterDigit, self.genString, self.genUnicode, self.genUnixPath, self.genFloat, self.genExistingFilename, self.genUserObject, self.genUserClass, # self.genOpenFile, # self.genException, ) self.complex_argument_generators = self.simple_argument_generators + ( self.genList, self.genTuple, self.genDict, ) self.indent = ' ' * 4 self.filename = filename self.base_level = 0 self.smallint_generator = UnsignedGenerator(3) self.int_generator = IntegerGenerator(20) self.str_generator = BytesGenerator(0, 20) self.unix_path_generator = UnixPathGenerator(100) self.letters_generator = BytesGenerator(1, 8, LETTERS | DECIMAL_DIGITS) self.float_int_generator = IntegerGenerator(3) self.float_float_generator = UnsignedGenerator(3) self.module = module self.module_name = module_name self.functions, self.classes = self.getFunctions() if not self.functions and not self.classes: raise PythonFuzzerError("Module %s has no function and no class!" % self.module_name)
class AcpidSocket(UnixSocketClient): def __init__(self, project, *args): UnixSocketClient.__init__(self, project, *args) max_size = 100 self.data_gen = BytesGenerator(1, max_size) self.max_tx_bytes = max_size * 20 self.max_rx_bytes = max_size * 20 def live(self): if (self.max_tx_bytes < self.tx_bytes) \ or (self.max_rx_bytes < self.rx_bytes): self.error("MAX! (RX=%s TX=%s)" % ( self.rx_bytes, self.tx_bytes)) self.send('session_stop') self.socket = None return if not self.socket: return action = randint(0, 2) if action == 0: self.actionSend() elif action == 1: self.actionReceive() else: self.actionSend() if not self.socket: return self.actionReceive() def actionSend(self): data = self.data_gen.createValue() self.warning("Send %s bytes: %r" % (len(data), data)) self.sendBytes(data) def actionReceive(self): data = self.recvBytes(timeout=0) if data is not None: self.warning("Receive %s bytes: %r" % (len(data), data)) else: self.warning("Receive nothing") def on_session_done(self, score): self.error("Done: RX=%s TX=%s" % ( self.rx_bytes, self.tx_bytes)) def getScore(self): if self.rx_bytes: return 1.0 else: return None
def __init__(self, project, arguments, **kw): ProjectProcess.__init__(self, project, arguments, **kw) self.options = 'Vqfldbv' VALUE_SET = DECIMAL_DIGITS | set('.:-/ ') self.stdin_generator = BytesGenerator(1, 5000) self.value_generator = BytesGenerator(1, 30, VALUE_SET) self.queue_generator = BytesGenerator(1, 1, ASCII0) self.filename_generator = UnixPathGenerator(100) self.min_opt = 0 self.max_opt = 2
class AttackProc(ProjectAgent): def __init__(self, project): ProjectAgent.__init__(self, project, "proc") self.generator = BytesGenerator(1, 256) def init(self): self.proc_keys = [ 'attr/current', 'attr/exec', 'attr/fscreate', 'attr/keycreate', 'attr/sockcreate', 'clear_refs', 'seccomp', # Strange keys #'mem', #'oom_adj', ] self.proc_path = None def on_process_create(self, agent): self.proc_path = "/proc/%s/" % agent.process.pid def live(self): if not self.proc_path: return self.info("Proc path: %s" % self.proc_path) key = choice(self.proc_keys) filename = path_join(self.proc_path, key) data = self.generator.createValue() self.info("Write data in %s: (len=%s) %r" % (filename, len(data), data)) try: output = open(filename, 'w') output.write(data) output.close() except IOError, err: if err.errno in (EINVAL, EPERM): pass elif err.errno in (ENOENT, EACCES): self.error("Unable to write %s: %s" % (filename, err)) self.removeKey(key) else: raise
class EchoProcess(CreateProcess): OPTIONS = ("-e", "-E", "-n") def __init__(self, project): CreateProcess.__init__(self, project, ["echo"]) self.datagen = BytesGenerator(1, 10, ASCII0) def createCmdline(self): arguments = ['echo'] for index in xrange(randint(3, 6)): if randint(1, 5) == 1: option = choice(self.OPTIONS) arguments.append(option) else: data = self.datagen.createValue() arguments.append(data) return arguments def on_session_start(self): self.cmdline.arguments = self.createCmdline() self.createProcess()
def fuzzit(pd, pck): #print "Start Fuzzing" s_len = pd.len s_info = pd.info datagen = BytesGenerator(800, 1100, PRINTABLE_ASCII) # heavy packets gen_and_send(pd, pck, datagen, 0) datagen = BytesGenerator(800, 1100, ASCII0) # heavy packets gen_and_send(pd, pck, datagen, 0) datagen = BytesGenerator(1, 255, PRINTABLE_ASCII) # regular checks gen_and_send(pd, pck, datagen, 0) datagen = BytesGenerator(1, 255, ASCII0) # regular checks gen_and_send(pd, pck, datagen, 0) datagen = BytesGenerator(1, 255, PRINTABLE_ASCII) gen_and_send(pd, pck, datagen, 1) # malformed packets datagen = BytesGenerator(1, 255, ASCII0) gen_and_send(pd, pck, datagen, 1) # malformed packets pd.len = s_len pd.info = s_info
def __init__(self, max_length=4000): BytesGenerator.__init__(self, 0, max_length, bytes_set=set('A'))
def __init__(self, name, arguments=None, type="void", random_bytes=400): FunctionC.__init__(self, name, arguments, type) self.bytes_generator = BytesGenerator(random_bytes, random_bytes) self.buffer_count = 0 self.special_int32 = (0x8000, 0xffff, 0x80000000)
def __init__(self, project, name): ProjectAgent.__init__(self, project, name) self.smart_string_generator = BytesGenerator(0, 10, LETTERS | DECIMAL_DIGITS | set(' ')) self.string_generator = BytesGenerator(0, 40, LETTERS | DECIMAL_DIGITS | PUNCTUATION) self.random_string_generator = BytesGenerator(0, 200) self.character_generator = BytesGenerator(1, 1) self.digit_generator = BytesGenerator(1, 30, DECIMAL_DIGITS) self.integer_generator = IntegerGenerator(11) self.printf_set = list(LETTERS | set('%')) self.long_string = LengthGenerator(10000) self.functions = list(set(( # Tests 'COALESCE', 'GREATEST', 'ISNULL', 'INTERVAL', 'LEAST', 'IF', 'IFNULL', 'NULLIF', 'STRCMP', # Math 'ABS', 'ACOS', 'ASIN', 'ATAN', 'ATAN2', 'CEILING', 'CEIL', 'COS', 'COT', 'CRC32', 'DEGREES', 'EXP', 'FLOOR', 'LN', 'LOG', 'LOG2', 'LOG10', 'MOD', 'PI', 'POW', 'POWER', 'RADIANS', 'RAND', 'ROUND', 'SIGN', 'SQRT', 'TAN', 'TRUNCATE', # String 'ASCII', 'BIN', 'BIT_LENGTH', 'CHAR', 'CHAR_LENGTH', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONV', 'ELT', 'EXPORT_SET', 'FIELD', 'FIND_IN_SET', 'HEX', 'INSERT', 'INSTR', 'LCASE', 'LEFT', 'LENGTH', 'LOAD_FILE', 'LOCATE', 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MID', 'OCTET_LENGTH', 'ORD', 'QUOTE', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'RPAD', 'RTRIM', 'SOUNDEX', 'SPACE', 'SUBSTRING', 'SUBSTRING_INDEX', 'TRIM', 'UCASE', 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UPPER', # Date 'ADDDATE', 'ADDTIME', 'CURDATE', 'CURRENT_DATE', 'CURTIME', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'DATE', 'DATEDIFF', 'DATE_FORMAT', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', 'EXTRACT', 'FROM_DAYS', 'FROM_UNIXTIME', 'GET_FORMAT', 'HOUR', 'LAST_DAY', 'LOCALTIME', 'LOCALTIMESTAMP', 'MAKEDATE', 'MAKETIME', 'MICROSECOND', 'MINUTE', 'MONTH', 'MONTHNAME', 'NOW', 'PERIOD_ADD', 'PERIOD_DIFF', 'QUARTER', 'SECOND', 'SEC_TO_TIME', 'STR_TO_DATE', 'SUBDATE', 'SUBTIME', 'SYSDATE', 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', 'UNIX_TIMESTAMP', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK', # Encryption 'AES_DECRYPT', 'AES_ENCRYPT', 'DECODE', 'ENCODE', 'DES_DECRYPT', 'DES_ENCRYPT', 'ENCRYPT', 'MD5', 'OLD_PASSWORD', 'PASSWORD', 'SHA', 'SHA1', # Information 'BENCHMARK', 'CHARSET', 'COERCIBILITY', 'COLLATION', 'CONNECTION_ID', 'CURRENT_USER', 'DATABASE', 'FOUND_ROWS', 'LAST_INSERT_ID', 'SESSION_USER', 'SYSTEM_USER', 'USER', 'VERSION', # Autres 'BIT_COUNT', 'FORMAT', 'GET_LOCK', 'INET_ATON', 'INET_NTOA', 'IS_FREE_LOCK', 'IS_USED_LOCK', 'MASTER_POS_WAIT', 'RELEASE_LOCK', 'UUID', ))) self.min_nb_arg = 0 self.max_nb_arg = 4 self.min_nb_instr = 1 self.max_nb_instr = 3 self.booleans = ('true', 'false') self.create_value = ( self.createCharacter, self.createString, self.createSmartString, self.createRandomString, self.createInteger, self.createFloat, self.createNull, self.createBoolean, self.createPrintf, # self.createLength, )
def createValue(self): value = BytesGenerator.createValue(self) return '"%s"' % value
def __init__(self, project): ProjectAgent.__init__(self, project, "proc") self.generator = BytesGenerator(1, 256)
class GenerateSQL(ProjectAgent): def __init__(self, project, name): ProjectAgent.__init__(self, project, name) self.smart_string_generator = BytesGenerator(0, 10, LETTERS | DECIMAL_DIGITS | set(' ')) self.string_generator = BytesGenerator(0, 40, LETTERS | DECIMAL_DIGITS | PUNCTUATION) self.random_string_generator = BytesGenerator(0, 200) self.character_generator = BytesGenerator(1, 1) self.digit_generator = BytesGenerator(1, 30, DECIMAL_DIGITS) self.integer_generator = IntegerGenerator(11) self.printf_set = list(LETTERS | set('%')) self.long_string = LengthGenerator(10000) self.functions = list(set(( # Tests 'COALESCE', 'GREATEST', 'ISNULL', 'INTERVAL', 'LEAST', 'IF', 'IFNULL', 'NULLIF', 'STRCMP', # Math 'ABS', 'ACOS', 'ASIN', 'ATAN', 'ATAN2', 'CEILING', 'CEIL', 'COS', 'COT', 'CRC32', 'DEGREES', 'EXP', 'FLOOR', 'LN', 'LOG', 'LOG2', 'LOG10', 'MOD', 'PI', 'POW', 'POWER', 'RADIANS', 'RAND', 'ROUND', 'SIGN', 'SQRT', 'TAN', 'TRUNCATE', # String 'ASCII', 'BIN', 'BIT_LENGTH', 'CHAR', 'CHAR_LENGTH', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONV', 'ELT', 'EXPORT_SET', 'FIELD', 'FIND_IN_SET', 'HEX', 'INSERT', 'INSTR', 'LCASE', 'LEFT', 'LENGTH', 'LOAD_FILE', 'LOCATE', 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MID', 'OCTET_LENGTH', 'ORD', 'QUOTE', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'RPAD', 'RTRIM', 'SOUNDEX', 'SPACE', 'SUBSTRING', 'SUBSTRING_INDEX', 'TRIM', 'UCASE', 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UPPER', # Date 'ADDDATE', 'ADDTIME', 'CURDATE', 'CURRENT_DATE', 'CURTIME', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'DATE', 'DATEDIFF', 'DATE_FORMAT', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', 'EXTRACT', 'FROM_DAYS', 'FROM_UNIXTIME', 'GET_FORMAT', 'HOUR', 'LAST_DAY', 'LOCALTIME', 'LOCALTIMESTAMP', 'MAKEDATE', 'MAKETIME', 'MICROSECOND', 'MINUTE', 'MONTH', 'MONTHNAME', 'NOW', 'PERIOD_ADD', 'PERIOD_DIFF', 'QUARTER', 'SECOND', 'SEC_TO_TIME', 'STR_TO_DATE', 'SUBDATE', 'SUBTIME', 'SYSDATE', 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', 'UNIX_TIMESTAMP', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK', # Encryption 'AES_DECRYPT', 'AES_ENCRYPT', 'DECODE', 'ENCODE', 'DES_DECRYPT', 'DES_ENCRYPT', 'ENCRYPT', 'MD5', 'OLD_PASSWORD', 'PASSWORD', 'SHA', 'SHA1', # Information 'BENCHMARK', 'CHARSET', 'COERCIBILITY', 'COLLATION', 'CONNECTION_ID', 'CURRENT_USER', 'DATABASE', 'FOUND_ROWS', 'LAST_INSERT_ID', 'SESSION_USER', 'SYSTEM_USER', 'USER', 'VERSION', # Autres 'BIT_COUNT', 'FORMAT', 'GET_LOCK', 'INET_ATON', 'INET_NTOA', 'IS_FREE_LOCK', 'IS_USED_LOCK', 'MASTER_POS_WAIT', 'RELEASE_LOCK', 'UUID', ))) self.min_nb_arg = 0 self.max_nb_arg = 4 self.min_nb_instr = 1 self.max_nb_instr = 3 self.booleans = ('true', 'false') self.create_value = ( self.createCharacter, self.createString, self.createSmartString, self.createRandomString, self.createInteger, self.createFloat, self.createNull, self.createBoolean, self.createPrintf, # self.createLength, ) def createPrintf(self): count = randint(1, 20) format = ('%' + choice(self.printf_set) for index in xrange(count)) value = ''.join(format) return quoteString(value) def createString(self): value = self.string_generator.createValue() return quoteString(value) def createSmartString(self): value = self.smart_string_generator.createValue() return quoteString(value) def createRandomString(self): value = self.random_string_generator.createValue() return quoteString(value) def createCharacter(self): value = self.character_generator.createValue() return quoteString(value) def createInteger(self): return self.integer_generator.createValue() def createFloat(self): return self.createInteger() + '.' + self.digit_generator.createValue() def createBoolean(self): return choice(self.booleans) def createNull(self): return 'NULL' def createValue(self): func = choice(self.create_value) return func() def createLength(self): return quoteString(self.long_string.createValue()) def createFunction(self): function = choice(self.functions) sql = [function, '('] nb_arg = randint(self.min_nb_arg, self.max_nb_arg) for index in xrange(1, nb_arg+1): if 1 < index: sql.append(', ') value = self.createValue() sql.append(value) sql.append(')') return ''.join(sql) def createInstr(self): return 'SELECT %s;' % self.createFunction() def createSQL(self): sql = [] nb_instr = randint(self.min_nb_instr, self.max_nb_instr) for index in xrange(nb_instr): sql.append(self.createInstr()) sql.append('') return sql def on_session_start(self): sql = '\n'.join(self.createSQL()) self.send('mysql_sql', sql)
class WritePythonCode: def __init__(self, filename, module, module_name): self.simple_argument_generators = ( self.genNone, self.genBool, self.genSmallUint, self.genInt, self.genLetterDigit, self.genString, self.genUnicode, self.genUnixPath, self.genFloat, self.genExistingFilename, self.genUserObject, self.genUserClass, # self.genOpenFile, # self.genException, ) self.complex_argument_generators = self.simple_argument_generators + ( self.genList, self.genTuple, self.genDict, ) self.indent = ' ' * 4 self.filename = filename self.base_level = 0 self.smallint_generator = UnsignedGenerator(3) self.int_generator = IntegerGenerator(20) self.str_generator = BytesGenerator(0, 20) self.unix_path_generator = UnixPathGenerator(100) self.letters_generator = BytesGenerator(1, 8, LETTERS | DECIMAL_DIGITS) self.float_int_generator = IntegerGenerator(3) self.float_float_generator = UnsignedGenerator(3) self.module = module self.module_name = module_name self.functions, self.classes = self.getFunctions() if not self.functions and not self.classes: raise PythonFuzzerError("Module %s has no function and no class!" % self.module_name) def writeSource(self): self.output = open(self.filename, "w") self.write(0, "from sys import stderr") self.write(0, 'print "import %s"' % self.module_name) self.write(0, "import %s" % self.module_name) self.emptyLine() self.write(0, "class %s:" % USER_CLASS) self.write(1, "def __init__(self, x):") self.write(2, "self.x = x") self.emptyLine() self.write(1, "def test(self):") self.write(2, "print self.x") self.emptyLine() self.write(0, "%s = %s(42)" % (USER_OBJECT, USER_CLASS)) self.emptyLine() self.writeCode(self.module_name, self.module, self.functions, self.classes, 1, NB_CALL) self.output.close() def getFunctions(self): classes = [] functions = [] try: blacklist = BLACKLIST[self.module_name] except KeyError: blacklist = set() for name in dir(self.module): attr = getattr(self.module, name) if name in blacklist: continue if isinstance(attr, (FunctionType, BuiltinFunctionType)): functions.append(name) elif isinstance(attr, type): classes.append(name) return functions, classes def getMethods(self, object, class_name): try: key = "%s:%s" % (self.module_name, class_name) blacklist = BLACKLIST[key] except KeyError: blacklist = set() methods = [] for name in dir(object): if name in blacklist: continue if SKIP_PRIVATE and name.startswith("__"): continue attr = getattr(object, name) if not ismethoddescriptor(attr): continue methods.append(name) return methods def createComplexArgument(self): callback = choice(self.complex_argument_generators) return callback() def createArgument(self): callback = choice(self.simple_argument_generators) return callback() def getNbArg(self, func, func_name, min_arg): try: # Known method of arguments? value = METHODS_NB_ARG[func_name] if isinstance(value, tuple): min_arg, max_arg = value else: min_arg = max_arg = value return min_arg, max_arg except KeyError: pass if PARSE_PROTOTYPE: # Try using the documentation args = parseDocumentation(func.__doc__, MAX_VAR_ARG) if args: return args return min_arg, MAX_ARG def callFunction(self, func_index, context, func_name, func, min_arg): name = func_name func_name = "%s.%s" % (context, func_name) self.write(0, 'print "Call %s/%s: %s()"' % ( 1+func_index, self.nb_function, func_name)) self.write(0, 'try:') self.write(1, '%s(' % func_name) min_arg, max_arg = self.getNbArg(func, name, min_arg) nb_arg = randint(min_arg, max_arg) self.base_level += 1 for index in xrange(nb_arg): self.write(1, '# argument %s/%s' % (1+index, nb_arg)) self.writeArgument(1) self.base_level -= 1 self.write(1, ')') self.exceptBlock(0) self.emptyLine() def exceptBlock(self, level): self.write(level, 'except Exception, err:') self.write(level+1, 'print >>stderr, "ERROR: %s" % err') def writeArgument(self, level): lines = self.createComplexArgument() lines[-1] += ',' for line in lines: self.write(level, line) def write(self, level, text): indent = self.indent * (self.base_level + level) print >>self.output, indent + text def emptyLine(self): print >>self.output def useClass(self, cls_index, context, cls, class_name): methods = self.getMethods(cls, class_name) class_name = "%s.%s" % (context, class_name) self.write(0, 'print "Class %s/%s: %s"' % ( 1 + cls_index, self.nb_class, class_name)) obj_name = 'obj' self.write(0, 'try:') self.write(1, '%s = %s(' % (obj_name, class_name)) nb_arg = randint(1, MAX_ARG) for index in xrange(nb_arg): self.write(2, '# argument %s/%s' % (1+index, nb_arg)) self.writeArgument(2) self.write(1, ')') self.exceptBlock(0) self.write(0, 'else:') if methods: self.base_level += 1 self.writeCode(obj_name, cls, methods, tuple(), 0, NB_METHOD) self.base_level -= 1 self.write(1, 'del %s' % obj_name) self.emptyLine() def writeCode(self, context, object, functions, classes, func_min_arg, nb_call): if functions: self.nb_function = nb_call for index in xrange(self.nb_function): func_name = choice(functions) func = getattr(object, func_name) self.callFunction(index, context, func_name, func, func_min_arg) if classes: self.nb_class = NB_CLASS for index in xrange(self.nb_class): class_name = choice(classes) cls = getattr(object, class_name) self.useClass(index, context, cls, class_name) def genNone(self): return ['None'] def genBool(self): if randint(0, 1) == 1: return ['True'] else: return ['False'] def genSmallUint(self): return [self.smallint_generator.createValue()] def genInt(self): return [self.int_generator.createValue()] def genString(self): bytes = self.str_generator.createValue() return ['"' + ''.join( r"\x%02X" % ord(byte) for byte in bytes) + '"'] def genUnixPath(self): path = self.unix_path_generator.createValue() return ['"%s"' % path] def genLetterDigit(self): text = self.letters_generator.createValue() return ['"%s"' % text] def genUnicode(self): length = randint(0, 20) return ['u"' + ''.join( r"\u%04X" % randint(0, 65535) for index in xrange(length)) + '"'] def genFloat(self): int_part = self.float_int_generator.createValue() float_part = self.float_float_generator.createValue() return ["%s.%s" % (int_part, float_part)] def genExistingFilename(self): filename = choice(FILENAMES) return ["'%s'" % filename] def genUserObject(self): return ["%s" % USER_OBJECT] def genUserClass(self): return ["%s" % USER_CLASS] def genOpenFile(self): filename = choice(FILENAMES) return ["open('%s')" % filename] def genException(self): return ["Exception('pouet')"] def _genList(self, open_text, close_text, empty, is_dict=False): # 90% of the time generate values of the same type same_type = (randint(0, 10) != 0) nb_item = randint(0, 10) if not nb_item: return [empty] items = [] if same_type: if is_dict: key_callback = choice(self.simple_argument_generators) value_callback = choice(self.simple_argument_generators) for index in xrange(nb_item): if is_dict: item = self.createDictItem(key_callback, value_callback) else: item = value_callback() items.append(item) else: for index in xrange(nb_item): if is_dict: item = self.createDictItem() else: item = self.createArgument() items.append(item) lines = [] for item_index, item_lines in enumerate(items): if item_index: lines[-1] += "," for index, line in enumerate(item_lines): # Add ' ' suffix to all lines item_lines[index] = ' ' + line lines.extend(item_lines) if nb_item == 1 and empty == 'tuple()': lines[-1] += ',' lines[0] = open_text + lines[0] lines[-1] += close_text return lines def createDictItem(self, key_callback=None, value_callback=None): if key_callback: key = key_callback() else: key = self.createArgument() if value_callback: value = value_callback() else: value = self.createArgument() key[-1] += ": " + value[0] key.extend(value[1:]) return key def genList(self): return self._genList('[', ']', '[]') def genTuple(self): return self._genList('(', ')', 'tuple()') def genDict(self): return self._genList('{', '}', '{}', True)
class WritePythonCode: def __init__(self, filename, module, module_name): self.simple_argument_generators = ( self.genNone, self.genBool, self.genSmallUint, self.genInt, self.genLetterDigit, self.genString, self.genUnicode, self.genUnixPath, self.genFloat, self.genExistingFilename, self.genUserObject, self.genUserClass, # self.genOpenFile, # self.genException, ) self.complex_argument_generators = self.simple_argument_generators + ( self.genList, self.genTuple, self.genDict, ) self.indent = ' ' * 4 self.filename = filename self.base_level = 0 self.smallint_generator = UnsignedGenerator(3) self.int_generator = IntegerGenerator(20) self.str_generator = BytesGenerator(0, 20) self.unix_path_generator = UnixPathGenerator(100) self.letters_generator = BytesGenerator(1, 8, LETTERS | DECIMAL_DIGITS) self.float_int_generator = IntegerGenerator(3) self.float_float_generator = UnsignedGenerator(3) self.module = module self.module_name = module_name self.functions, self.classes = self.getFunctions() if not self.functions and not self.classes: raise PythonFuzzerError("Module %s has no function and no class!" % self.module_name) def writeSource(self): self.output = open(self.filename, "w") self.write(0, "from sys import stderr") self.write(0, 'print "import %s"' % self.module_name) self.write(0, "import %s" % self.module_name) self.emptyLine() self.write(0, "class %s:" % USER_CLASS) self.write(1, "def __init__(self, x):") self.write(2, "self.x = x") self.emptyLine() self.write(1, "def test(self):") self.write(2, "print self.x") self.emptyLine() self.write(0, "%s = %s(42)" % (USER_OBJECT, USER_CLASS)) self.emptyLine() self.writeCode(self.module_name, self.module, self.functions, self.classes, 1, NB_CALL) self.output.close() def getFunctions(self): classes = [] functions = [] try: blacklist = BLACKLIST[self.module_name] except KeyError: blacklist = set() for name in dir(self.module): attr = getattr(self.module, name) if name in blacklist: continue if isinstance(attr, (FunctionType, BuiltinFunctionType)): functions.append(name) elif isinstance(attr, type): classes.append(name) return functions, classes def getMethods(self, object, class_name): try: key = "%s:%s" % (self.module_name, class_name) blacklist = BLACKLIST[key] except KeyError: blacklist = set() methods = [] for name in dir(object): if name in blacklist: continue if SKIP_PRIVATE and name.startswith("__"): continue attr = getattr(object, name) if not ismethoddescriptor(attr): continue methods.append(name) return methods def createComplexArgument(self): callback = choice(self.complex_argument_generators) return callback() def createArgument(self): callback = choice(self.simple_argument_generators) return callback() def getNbArg(self, func, func_name, min_arg): try: # Known method of arguments? value = METHODS_NB_ARG[func_name] if isinstance(value, tuple): min_arg, max_arg = value else: min_arg = max_arg = value return min_arg, max_arg except KeyError: pass if PARSE_PROTOTYPE: # Try using the documentation args = parseDocumentation(func.__doc__, MAX_VAR_ARG) if args: return args return min_arg, MAX_ARG def callFunction(self, func_index, context, func_name, func, min_arg): name = func_name func_name = "%s.%s" % (context, func_name) self.write( 0, 'print "Call %s/%s: %s()"' % (1 + func_index, self.nb_function, func_name)) self.write(0, 'try:') self.write(1, '%s(' % func_name) min_arg, max_arg = self.getNbArg(func, name, min_arg) nb_arg = randint(min_arg, max_arg) self.base_level += 1 for index in xrange(nb_arg): self.write(1, '# argument %s/%s' % (1 + index, nb_arg)) self.writeArgument(1) self.base_level -= 1 self.write(1, ')') self.exceptBlock(0) self.emptyLine() def exceptBlock(self, level): self.write(level, 'except Exception, err:') self.write(level + 1, 'print >>stderr, "ERROR: %s" % err') def writeArgument(self, level): lines = self.createComplexArgument() lines[-1] += ',' for line in lines: self.write(level, line) def write(self, level, text): indent = self.indent * (self.base_level + level) print >> self.output, indent + text def emptyLine(self): print >> self.output def useClass(self, cls_index, context, cls, class_name): methods = self.getMethods(cls, class_name) class_name = "%s.%s" % (context, class_name) self.write( 0, 'print "Class %s/%s: %s"' % (1 + cls_index, self.nb_class, class_name)) obj_name = 'obj' self.write(0, 'try:') self.write(1, '%s = %s(' % (obj_name, class_name)) nb_arg = randint(1, MAX_ARG) for index in xrange(nb_arg): self.write(2, '# argument %s/%s' % (1 + index, nb_arg)) self.writeArgument(2) self.write(1, ')') self.exceptBlock(0) self.write(0, 'else:') if methods: self.base_level += 1 self.writeCode(obj_name, cls, methods, tuple(), 0, NB_METHOD) self.base_level -= 1 self.write(1, 'del %s' % obj_name) self.emptyLine() def writeCode(self, context, object, functions, classes, func_min_arg, nb_call): if functions: self.nb_function = nb_call for index in xrange(self.nb_function): func_name = choice(functions) func = getattr(object, func_name) self.callFunction(index, context, func_name, func, func_min_arg) if classes: self.nb_class = NB_CLASS for index in xrange(self.nb_class): class_name = choice(classes) cls = getattr(object, class_name) self.useClass(index, context, cls, class_name) def genNone(self): return ['None'] def genBool(self): if randint(0, 1) == 1: return ['True'] else: return ['False'] def genSmallUint(self): return [self.smallint_generator.createValue()] def genInt(self): return [self.int_generator.createValue()] def genString(self): bytes = self.str_generator.createValue() return ['"' + ''.join(r"\x%02X" % ord(byte) for byte in bytes) + '"'] def genUnixPath(self): path = self.unix_path_generator.createValue() return ['"%s"' % path] def genLetterDigit(self): text = self.letters_generator.createValue() return ['"%s"' % text] def genUnicode(self): length = randint(0, 20) return [ 'u"' + ''.join(r"\u%04X" % randint(0, 65535) for index in xrange(length)) + '"' ] def genFloat(self): int_part = self.float_int_generator.createValue() float_part = self.float_float_generator.createValue() return ["%s.%s" % (int_part, float_part)] def genExistingFilename(self): filename = choice(FILENAMES) return ["'%s'" % filename] def genUserObject(self): return ["%s" % USER_OBJECT] def genUserClass(self): return ["%s" % USER_CLASS] def genOpenFile(self): filename = choice(FILENAMES) return ["open('%s')" % filename] def genException(self): return ["Exception('pouet')"] def _genList(self, open_text, close_text, empty, is_dict=False): # 90% of the time generate values of the same type same_type = (randint(0, 10) != 0) nb_item = randint(0, 10) if not nb_item: return [empty] items = [] if same_type: if is_dict: key_callback = choice(self.simple_argument_generators) value_callback = choice(self.simple_argument_generators) for index in xrange(nb_item): if is_dict: item = self.createDictItem(key_callback, value_callback) else: item = value_callback() items.append(item) else: for index in xrange(nb_item): if is_dict: item = self.createDictItem() else: item = self.createArgument() items.append(item) lines = [] for item_index, item_lines in enumerate(items): if item_index: lines[-1] += "," for index, line in enumerate(item_lines): # Add ' ' suffix to all lines item_lines[index] = ' ' + line lines.extend(item_lines) if nb_item == 1 and empty == 'tuple()': lines[-1] += ',' lines[0] = open_text + lines[0] lines[-1] += close_text return lines def createDictItem(self, key_callback=None, value_callback=None): if key_callback: key = key_callback() else: key = self.createArgument() if value_callback: value = value_callback() else: value = self.createArgument() key[-1] += ": " + value[0] key.extend(value[1:]) return key def genList(self): return self._genList('[', ']', '[]') def genTuple(self): return self._genList('(', ')', 'tuple()') def genDict(self): return self._genList('{', '}', '{}', True)
def __init__(self, project): CreateProcess.__init__(self, project, ["echo"]) self.datagen = BytesGenerator(1, 10, ASCII0)
def createValue(self): value = BytesGenerator.createValue(self) return 'base64_decode("%s")' % b64encode(value)
def __init__(self, project, *args): UnixSocketClient.__init__(self, project, *args) max_size = 100 self.data_gen = BytesGenerator(1, max_size) self.max_tx_bytes = max_size * 20 self.max_rx_bytes = max_size * 20
def __init__(self, max_length=10): BytesGenerator.__init__(self, 0, max_length)