Skip to content

Commit

Permalink
redesigning the fuzzer
Browse files Browse the repository at this point in the history
- started to implement assignments
  • Loading branch information
susperius committed Feb 15, 2016
1 parent f4e03be commit 9825000
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 45 deletions.
102 changes: 96 additions & 6 deletions node/fuzzing/browser/javascript_ng.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from ..fuzzer import Fuzzer
from model.JsDocument import JsDocument
from model.JsObject import *
from model.JsDomElement import *
from model.values import FuzzValues

"""
1) Create a html page
Expand All @@ -32,15 +34,22 @@ class JsFuzzer(Fuzzer):
NAME = "js_fuzzer"
CONFIG_PARAMS = []
CALLING_COMMENT = "//CALLING COMMENT"
FIRST_ARRAY_LENGTH = 5

def __init__(self, seed, starting_elements, html_depth, html_max_attr, canvas_size, file_type):
self._html_fuzzer = Html5Fuzzer(seed, starting_elements, html_depth, html_max_attr, file_type)
self._canvas_fuzzer = CanvasFuzzer(canvas_size)
self._css_fuzzer = CssFuzzer(seed)
random.seed(0)
self._file_type = file_type
self._js_objects = []
self._js_arrays = []
self._js_objects = {}
self.__init_js_object_dict()
self._js_event_listener = []
self._js_array_functions = []

def __init_js_object_dict(self):
for js_obj_type in JS_OBJECTS:
self._js_objects[js_obj_type] = []

def file_type(self):
return self._file_type
Expand All @@ -65,26 +74,107 @@ def fuzz(self):
html_page = self._html_fuzzer.fuzz()
css = self._css_fuzzer.fuzz()
code = ""
code += self.__init_js_objects(html_page)
for i in range(20):
code += self.__build_assignment()
return code

def __init_js_objects(self, html_page):
available_dom_elements = html_page.get_elements_by_id()
code = "function startup() {\n"
for element_id in available_dom_elements.keys():
code += "\telem_" + element_id + " = " + JsDocument.getElementById(element_id) + ";\n"
self._js_objects['JS_DOM_ELEMENT'].append(JsDomElement("elem_" + element_id,
available_dom_elements[element_id]))
code += self.__build_js_array(self.FIRST_ARRAY_LENGTH)
code += "\t" + self.CALLING_COMMENT + "\n"
return code

def __build_js_array(self, length):
array_obj_list = []
for i in range(length):
js_obj = random.choice(self._js_objects)
js_obj = self.__get_an_js_object()
array_obj_list.append(js_obj)
js_array = JsArray("array_" + str(len(self._js_arrays)), array_obj_list)
self._js_arrays.append(js_array)
js_array = JsArray("array_" + str(len(self._js_objects['JS_ARRAY'])), array_obj_list)
self._js_objects['JS_ARRAY'].append(js_array)
return js_array.newArray()

def __build_assignment(self):
pass
code, ret_val = self.__create_a_method_or_prop_call()
if ret_val in JS_OBJECTS or ret_val in ['STRING', 'INT']:
assignment_obj = None
what_do_to_next = random.choice(['REPLACE_AN_EXISTING_OBJ', 'CREATE_A_NEW_OBJ'])
if what_do_to_next == "REPLACE_AN_EXISTING_OBJ":
assignment_obj = random.choice(self._js_objects[ret_val])
code = assignment_obj.name + " = " + code + ";\n"
elif what_do_to_next == "CREATE_A_NEW_OBJ":
assignment_obj_name = "elem_" + str(len(self._js_objects))
if ret_val == "JS_STRING" or ret_val == "STRING":
assignment_obj = JsString(assignment_obj_name)
elif ret_val == "JS_ARRAY":
assignment_obj = JsArray(assignment_obj_name, [])
elif ret_val == "JS_NUMBER" or ret_val == "INT":
assignment_obj = JsNumber(assignment_obj_name)
elif ret_val == "JS_DOM_ELEMENT":
assignment_obj = JsDomElement(assignment_obj_name, "")
self._js_objects[ret_val].append(assignment_obj)
code = assignment_obj.name + " = " + code + ";\n"
else:
code += ";\n"
return code

def __create_a_method_or_prop_call(self):
js_obj = self.__get_an_js_object()
js_obj_function = js_obj.methods_and_properties[random.choice(js_obj.methods_and_properties.keys())]
if js_obj_function['parameters'] is not None:
params = self.__get_params(js_obj_function['parameters'])
code = js_obj_function['method'](*params)
else:
code = js_obj_function['method']()
return code, js_obj_function['ret_val']

def __get_an_js_object(self):
js_obj_type = random.choice(self._js_objects.keys())
while not self._js_objects[js_obj_type]:
js_obj_type = random.choice(self._js_objects.keys())
js_obj = random.choice(self._js_objects[js_obj_type])
return js_obj

def __get_params(self, param_list):
ret_params = []
print(param_list)
for param in param_list:
if param == "STRING":
str_src = random.choice([0, 1, 2])
if str_src == 0: # Take one from FuzzValues
ret_params.append(FuzzValues.STRINGS)
elif str_src == 1: # Create a JsString
ret_params.append(self.__create_js_string())
elif str_src == 2:
key = random.choice(self._js_objects.keys())
while not self._js_objects[key]: # Find a object
key = random.choice[key]
ret_params.append(self._js_objects[key].toString())
elif param == "INT":
ret_params.append(random.choice(FuzzValues.INTS))
elif param == "NUMBER": # as string in expo writing or or or
value = random.choice(FuzzValues.INTS)
as_string = random.choice([0, 1])
if as_string == 1:
value = "\"" + value + "\""
ret_params.append(value)
elif param == "JS_ARRAY":
ret_params.append(random.choice(self._js_objects['JS_ARRAY']))
elif param == "JS_FUNCTION":
if not self._js_array_functions:
pass # TODO: Build a function!
else:
ret_params.append(random.choice(self._js_array_functions))
return ret_params

def __create_js_string(self):
x = self._js_objects
return ""



Expand Down
1 change: 1 addition & 0 deletions node/fuzzing/browser/model/JsDomElement.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def __init__(self, var_name, html_type):
self.__children = []
self.__attributes = {}
self.__html_type = html_type
# TODO: Look up ret_vals and parameters
js_element_methods_and_properties = {'addEventListener': {'ret_val': None, 'parameters': ['JS_EVENT_LISTENER'], 'method': self.addEventListener},
'appendChild': {'ret_val': None, 'parameters': ['JS_DOM_ELEMENT'], 'method': self.appendChild},
'blur': {'ret_val': None, 'parameters': None, 'method': self.blur},
Expand Down
22 changes: 17 additions & 5 deletions node/fuzzing/browser/model/JsObject.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
__author__ = 'susperius'

JS_OBJECTS = ['JS_STRING', 'JS_NUMBER', 'JS_DATE', 'JS_ARRAY', 'JS_DOM_ELEMENT']
JS_OBJECTS = ['JS_STRING', 'JS_NUMBER', 'JS_ARRAY', 'JS_DOM_ELEMENT'] # 'JS_DATE',


class JsObject:
Expand All @@ -23,9 +23,21 @@ def methods_and_properties_by_type(self):
ret_val = {}
for key in self._methods_and_properties.keys():
if self._methods_and_properties[key]['ret_val'] not in ret_val.keys():
ret_val[self._methods_and_properties[key]['ret_val']] = [{'parameters': self._methods_and_properties[key]['parameters'], 'method': self._methods_and_properties['method']}]
ret_val[self._methods_and_properties[key]['ret_val']] = [{'parameters': self._methods_and_properties[key]['parameters'], 'method': self._methods_and_properties[key]['method']}]
else:
ret_val[self._methods_and_properties[key]['ret_val']].append({'parameters': self._methods_and_properties[key]['parameters'], 'method': self._methods_and_properties['method']})
ret_val[self._methods_and_properties[key]['ret_val']].append({'parameters': self._methods_and_properties[key]['parameters'], 'method': self._methods_and_properties[key]['method']})
return ret_val

@property
def methods_and_properties_by_parameters(self):
ret_val = {}
for key in self._methods_and_properties.keys():
if self._methods_and_properties[key]['parameters'] is not None:
for param in self._methods_and_properties[key]['parameters']:
if param not in ret_val.keys():
ret_val[param] = [{'ret_val': self._methods_and_properties[key]['ret_val'], 'parameters': self._methods_and_properties[key]['parameters'], 'method': self._methods_and_properties[key]['method']}]
else:
ret_val[param].append({'ret_val': self._methods_and_properties[key]['ret_val'], 'parameters': self._methods_and_properties[key]['parameters'], 'method': self._methods_and_properties[key]['method']})
return ret_val

def toString(self):
Expand All @@ -36,7 +48,7 @@ class JsString(JsObject):
TYPE = "JsString"

def __init__(self, name):
JsObject.__init__(name)
JsObject.__init__(self, name)
js_string_methods = {'charAt': {'ret_val': 'STRING', 'parameters': ['INT'], 'method': self.charAt},
'charCodeAt': {'ret_val': 'INT', 'parameters': ['INT'], 'method': self.charCodeAt},
'concat': {'ret_val': 'STRING', 'parameters': ['STRING'], 'method': self.concat},
Expand Down Expand Up @@ -135,7 +147,7 @@ class JsNumber(JsObject):
TYPE = "JsNumber"

def __init__(self, name):
JsObject.__init__(name)
JsObject.__init__(self, name)
js_number_methods = {'toExponential': {'ret_val': 'EXP_FLOAT', 'parameters': ['NUMBER'], 'method': self.toExponential},
'toFixed': {'ret_val': 'STRING', 'parameters': ['INT'], 'method': self.toFixed},
'toPrecision': {'ret_val': 'FLOAT', 'parameters': ['INT'], 'method': self.toPrecision},
Expand Down
37 changes: 3 additions & 34 deletions node/testjs.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,8 @@
__author__ = 'susperius'

import node.fuzzing.browser.javascript as fuzz_js
import node.fuzzing.browser.canvas as fuzz_canv
from node.fuzzing.browser.javascript_ng import *

fuzzy = fuzz_js.JsDomFuzzer(30, 5000, "ie", 0, 5, "html")
fuzzer = JsFuzzer(0, 10, 5, 5, 5, 'html')

fuzzy.create_testcases(2, '.')
print(fuzzer.fuzz())

'''
for i in range(2):
with open('test'+str(i)+'.html', 'w+') as fd_html, open('test'+str(i)+'.css', 'w+') as fd_css:
html, css = fuzzy.fuzz()
fd_html.write(html)
fd_css.write(css)
'''


'''
case = fuzzy.fuzz()
reducer = red_js.JsReducer(case, 'abc')
for i in range(30):
print(i)
with open('red_case'+str(i)+'.html', 'w+') as fd:
red = reducer.reduce()
if red is not None:
fd.write(reducer.reduce())
else:
quit()
reducer.crashed(True)
'''


'''
fuzzy = fuzz_canv.CanvasFuzzer(200)
fuzzy.set_canvas_id("canvas01")
print(fuzzy.fuzz())
'''

0 comments on commit 9825000

Please sign in to comment.