def compile_template(self): _url = Static(name='url', value=self.url.encode()) _method = Static(name='method', value=self.method.encode()) template = Template(name='{}_{}'.format(self.url.replace('/', '_'), self.method), fields=[_url, _method]) self.fuzz_place = get_field_type_by_method(self.method) template.append_fields([Container(name='{}'.format(self.fuzz_place), fields=self.fuzz_params)]) return template
def testCorrectCallbackIsCalledForAllEdgesInPath(self): template1 = Template(name='template1', fields=String('str1')) template2 = Template(name='template2', fields=String('str2')) template3 = Template(name='template3', fields=String('str3')) self.cb2_call_count = 0 self.cb3_call_count = 0 def t1_t2_cb(fuzzer, edge, response): self.assertEqual(fuzzer, self.fuzzer) self.assertEqual(edge.src, template1) self.assertEqual(edge.dst, template2) self.cb2_call_count += 1 def t2_t3_cb(fuzzer, edge, response): self.assertEqual(fuzzer, self.fuzzer) self.assertEqual(edge.src, template2) self.assertEqual(edge.dst, template3) self.cb3_call_count += 1 model = GraphModel() model.logger = self.logger model.connect(template1) model.connect(template1, template2, t1_t2_cb) model.connect(template2, template3, t2_t3_cb) self.model = model self.fuzzer.set_model(model) self.fuzzer.set_range() self.fuzzer.start() self.assertEqual(template2.num_mutations() + template3.num_mutations(), self.cb2_call_count) self.assertEqual(template3.num_mutations(), self.cb3_call_count)
def compile_template(self): _url = Static(name='url', value=self.url) _method = Static(name='method', value=self.method) template = Template(name=self.name, fields=[_url, _method]) for name, field in self.field_to_param.items(): if list(field): template.append_fields([Container(name=name, fields=field)]) return template
def setUp(self): super(WebInterfaceTest, self).setUp(None) self.t_str = Template(name='simple_str_template', fields=[String(name='str1', value='kitty')]) self.t_int = Template(name='simple_int_template', fields=[UInt32(name='int1', value=0x1234)]) self.fuzzer = None self.host = '127.0.0.1' self.port = 11223 self.url = 'http://%(host)s:%(port)s' % {'host': self.host, 'port': self.port} self.prepare()
def setUp(self): self.logger = get_test_logger() self.logger.debug('TESTING METHOD: %s', self._testMethodName) self.t_str = Template(name='simple_str_template', fields=[String(name='str1', value='kitty')]) self.t_int = Template(name='simple_int_template', fields=[UInt32(name='int1', value=0x1234)]) self.fuzzer = None self.prepare()
def test_fuzzable_same_as_string_field_null(self): ''' Verify that the number of mutations is the same as for a StringField with value 'null' ''' t = warp_with_template(kjson.JsonNull(name='null', fuzzable=True)) st = Template(name='reference template', fields=String('null', name='snull')) self.assertEqual(t.num_mutations(), st.num_mutations()) while t.mutate(): st.mutate() self.assertEqual(t.render().bytes, st.render().bytes)
def test_fuzzable_same_as_quoted_string_field(self): ''' Verify that the number of mutations is the same as for a quoted StringField with the same default value ''' value = 'kitty' t = warp_with_template(kjson.JsonString(name='test', value=value, fuzzable=True)) st = Template(name='reference template', fields=String(name='reference', value=value)) self.assertEqual(t.num_mutations(), st.num_mutations()) while t.mutate(): st.mutate() self.assertEqual(t.render().bytes, '"%s"' % st.render().bytes)
def compile_template(self): _url = Static(name='url', value=self.url) _method = Static(name='method', value=self.method) template = Template(name=self.name, fields=[_url, _method]) for name, field in self.field_to_param.items(): if list(field): try: template.append_fields([Container(name=name, fields=field)]) except KittyException as e: self.logger.warning('Failed to add {} because {}, continue processing...'.format(name, e)) return template
def compile_template(self): _url = Static(name='url', value=self.url.encode()) _method = Static(name='method', value=self.method.encode()) template = Template(name='{}_{}'.format(self.url.replace('/', '_'), self.method), fields=[_url, _method]) if self.parameters: template.append_fields([Container(name='parameters', fields=self.parameters)]) if self.headers: template.append_fields([Container(name='headers', fields=self.headers)]) if self.data: template.append_fields([Container(name='data', fields=self.data)]) if self.path_variables: template.append_fields([Container(name='path_variables', fields=self.path_variables)]) return template
def main(cls): """ Main NmFuzzer function :return: 0 if successful, -1 otherwise """ args = cls.parse_args() logger = cls.logger(levels[args.log_level], "NetworkMiner.fuzz", "./session.log") prog = os.path.abspath(args.target_prog) start_tc = int(args.start) # define target target = WinAppDbgTarget("NetworkMiner", process_path=prog, process_args=[], logger=logger) # Template t1 = Template(name="PCAPs", fields=[ FsNames(args.test_corpus, name_filter="*.pcap", name="paths"), ]) model = GraphModel() model.connect(t1) # define the fuzzing session fuzzer = ServerFuzzer( name="NetworkMiner fuzzer", logger=logger, ) fuzzer.set_interface(WebInterface()) fuzzer.set_model(model) fuzzer.set_target(target) fuzzer.set_delay_between_tests(2) # Start try: logger.info("Starting fuzz session...") fuzzer.set_range(start_tc) start_time = time.time() fuzzer.start() end_time = time.time() logger.info("Done with fuzzing in {} seconds".format(end_time - start_time)) raw_input("Press enter to exit...") fuzzer.stop() except KeyboardInterrupt: logger.info("Session interrupted by user...") fuzzer.stop() return 1 except Exception as exc: logger.error(exc) fuzzer.stop() return -1 return 0
def get_templates(self): res = [] for i in range(20): name = 't%d' % i value = 'd%d' % i res.append(Template(name=name, fields=[String(value)])) return res
def new_model(self): model = GraphModel() model.logger = self.logger model.connect( Template(name='simple_str_template', fields=[String(name='str1', value='kitty')])) return model
def get_stage_map(self): stages = {} for i in range(1, 4): s = Stage(str(i), str(i), 1234) for n in range(i): name = 't%d_%d' % (i, n) value = 'd%d_%d' % (i, n) s.add_template(Template(name=name, fields=[String(value)])) stages[s] = i return stages
def main(): test_name = 'GET fuzzed' get_template = Template( name=test_name, fields=[ XmlElement( name='html', element_name='html', content=[ XmlElement( name='head', element_name='head', content='<meta http-equiv="refresh" content="5; url=/">' ), XmlElement(name='body', element_name='body', content='123', fuzz_content=True), ]) ]) fuzzer = ClientFuzzer(name='Example 3 - Browser Fuzzer') fuzzer.set_interface(WebInterface(host='0.0.0.0', port=26000)) target = ClientTarget(name='BrowserTarget') # # Note: to avoid opening the process on our X server, we use another display for it # display ':2' that is specified below was started this way: # >> sudo apt-get install xvfb # >> Xvfb :2 -screen 2 1280x1024x8 # env = os.environ.copy() env['DISPLAY'] = ':2' controller = ClientProcessController('BrowserController', '/usr/bin/opera', ['http://localhost:8082/fuzzed'], process_env=env) target.set_controller(controller) target.set_mutation_server_timeout(20) model = GraphModel() model.connect(get_template) fuzzer.set_model(model) fuzzer.set_target(target) fuzzer.set_delay_between_tests(0.1) server = MyHttpServer(('localhost', 8082), MyHttpHandler, fuzzer) fuzzer.start() while True: server.handle_request()
def testCallbackIsCalledBetweenTwoNodes(self): template1 = Template(name='template1', fields=String('str1')) template2 = Template(name='template2', fields=String('str2')) self.cb_call_count = 0 def t1_t2_cb(fuzzer, edge, response): self.assertEqual(fuzzer, self.fuzzer) self.assertEqual(edge.src, template1) self.assertEqual(edge.dst, template2) self.cb_call_count += 1 model = GraphModel() model.logger = self.logger model.connect(template1) model.connect(template1, template2, t1_t2_cb) self.model = model self.fuzzer.set_model(model) self.fuzzer.set_range() self.fuzzer.start() self.assertEqual(template2.num_mutations(), self.cb_call_count)
def craft_model_by_request(request): # Craft Kitty Model Template value_fields = [] proto = request.request_version.split('/')[0] proto_ver = float(request.request_version.split('/')[1]) # Append Request Line value_fields.append( HttpRequestLine( method=request.requestline.split()[0], uri=request.path, protocol=proto, version=proto_ver, fuzzable_method=True, fuzzable_uri=True, )) # Append headers for k, v in request.headers.items(): if k == 'Content-Length': continue if v.isdigit(): value_fields.append(IntField(key=k, value=int(v))) else: value_fields.append(TextField(key=k, value=v)) # Append data if exists if not request.headers.get('Content-Length'): value_fields.append(Static(b'\r\n')) else: content_length = int(request.headers.get('Content-Length') or 0) value_fields.append( ContentLengthField(sized_field='post_data_params', value=content_length, end=True)) data = request.rfile.read(content_length) if request.headers.get( 'Content-Type') == 'application/x-www-form-urlencoded': value_fields.append( PostFormUrlencoded(data.decode(), name='post_data_params', fuzz_param=True)) elif request.headers.get('Content-Type').startswith( 'multipart/form-data'): boundary = request.headers.get('Content-Type').split( 'boundary=')[1].encode() value_fields.append( PostMultipartFormData(data, boundary, name='post_data_params', fuzz_param=True)) return Template(value_fields, name='Http_Request')
def mod(ics_ip): print ">>>>> ICS FUZZING MODULE <<<<<\n" # 定义目标Fuzz对象的IP地址 TARGET_IP = ics_ip # 定义目标Fuzz对象的通讯端口 TARGET_PORT = 502 # 定义随机数种子 RANDSEED = int(RandShort()) # 根据ISF中Modbus-tcp协议的数据结构构造测试数据包,下面例子中将使用RandShort对请求的地址及bit位长度进行测试 write_coils_request_packet = ModbusHeaderRequest( func_code=0x05) / WriteSingleCoilRequest(ReferenceNumber=RandShort(), Value=RandShort()) # 使用ScapyField直接将Scapy的数据包结构应用于Kitty框架中 write_coils_request_packet_template = Template( name='Write Coils Request', fields=[ ScapyField( write_coils_request_packet, name='wrire_coils_request_packet', # 定义这个Field的名字,用于在报告中显示 fuzzable=True, # 定义这个Field是否需要Fuzz seed=RANDSEED, # 定义用于变异的随机数 fuzz_count=2000 # 这个数据结构的fuzz次数 ), ]) # 使用GraphModel进行Fuzz model = GraphModel() # 在使用GraphModel中注册第一个节点,由于Modbus的Read Coils请求是单次的请求/回答形式,因此这里只要注册简单的一个节点即可 model.connect(write_coils_request_packet_template) # 定义一个目标Target, 设置IP、端口及连接超时时间 modbus_target = TcpTarget(name='modbus target', host=TARGET_IP, port=TARGET_PORT, timeout=2) # 定义是需要等待Target返回响应,如果设置为True Target不返回数据包则会被识别成异常进行记录。 modbus_target.set_expect_response(True) # 定义使用ServerFuzzer的方式进行Fuzz测试 fuzzer = ServerFuzzer() # 定义fuzzer使用的交互界面为web界面 fuzzer.set_interface(WebInterface(port=26001)) # 在fuzzer中定义使用GraphModel fuzzer.set_model(model) # 在fuzzer中定义target为modbus_target fuzzer.set_target(modbus_target) # 定义每个测试用例发送之间的延迟 fuzzer.set_delay_between_tests(0.1) # 开始执行Fuzz fuzzer.start()
def add_stage(g, stage, template, count): ''' Add a stage to the session graph :param g: the GraphModel object :param stage: stage name :param template: the actual template :param count: the stage count :example: for the call add_stage(g, 'X', x, 4) we will create the following graph: :: x p1 -> x p1 -> p2 -> x p1 -> p2 -> p3 -> x ''' g.connect(template) pseudos = [ # workaround for a PseudoTemplate bug in kitty 0.6.9 # TODO: move to PseudoTemplate in next kitty version Template( name=stage, fields=Meta(fields=[ String(value=stage), UInt32(value=i) ]), fuzzable=False ) for i in range(count - 1) ] if pseudos: g.connect(pseudos[0]) for i in range(len(pseudos) - 1): g.connect(pseudos[i], pseudos[i + 1]) g.connect(pseudos[i], template) g.connect(pseudos[-1], template)
def run_proto(self) -> None: """ kitty low level field model https://kitty.readthedocs.io/en/latest/kitty.model.low_level.field.html """ js = ext_json.dict_to_JsonObject(dict(self.pb2_api[0]['Messages']), 'api') template_a = Template(name='Api', fields=js) self.logger.info(f"[{time.strftime('%H:%M:%S')}] Prepare ProtobufTarget ") target = ProtobufTarget('ProtobufTarget', host=self.target_host, port=self.target_port, max_retries=10, timeout=None, pb2_module=self.pb2_api[1]) self.logger.info(f"[{time.strftime('%H:%M:%S')}] Prepare ProtobufController ") controller = ProtobufController('ProtobufController', host=self.target_host, port=self.target_port) target.set_controller(controller) #target.set_expect_response('true') self.logger.info(f"[{time.strftime('%H:%M:%S')}] Defining GraphModel") model = GraphModel() model.connect(template_a) self.logger.info(f"[{time.strftime('%H:%M:%S')}] Prepare Server Fuzzer ") fuzzer = ServerFuzzer() fuzzer.set_interface(WebInterface(port=26001)) fuzzer.set_model(model) fuzzer.set_target(target) fuzzer.start() self.logger.info(f"[{time.strftime('%H:%M:%S')}] Start Fuzzer") self.logger.info(f"[Further info are in the related Kitty log output!]") six.moves.input('press enter to exit') self.logger.info(f"[{time.strftime('%H:%M:%S')}] End Fuzzer Session") fuzzer.stop()
def run_http(self) -> None: """ This method provides the HTTP GET, POST, ... , templating for the HTTP header as fields, data provided by the config, explained in the User Documentation. kitty low level field model https://kitty.readthedocs.io/en/latest/kitty.model.low_level.field.html :returns: None :rtype: None """ http_template = None # HTTP GET TEMPLATE self.logger.info( f"[{time.strftime('%H:%M:%S')}] Initiate template for HTTP GET ..." ) if self.http_get: http_template = Template( name='HTTP_GET', fields=[ # GET / HTTP/1.1 String('GET', name='method', fuzzable=False), Delimiter(' ', name='delimiter-1', fuzzable=False), String(self.http_path, name='path'), Delimiter(' ', name='delimiter-2', fuzzable=self.http_fuzz_protocol), String('HTTP', name='protocol name', fuzzable=self.http_fuzz_protocol), Delimiter('/', name='fws-1', fuzzable=self.http_fuzz_protocol), Dword(1, name='major version', encoder=ENC_INT_DEC, fuzzable=self.http_fuzz_protocol), Delimiter('.', name='dot-1', fuzzable=self.http_fuzz_protocol), Dword(1, name='minor version', encoder=ENC_INT_DEC, fuzzable=self.http_fuzz_protocol), Static('\r\n', name='EOL-1'), # User agent String('User-Agent:', name='user_agent_field', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-3', fuzzable=self.http_fuzz_protocol), String('Fuzzer', name='user-agent_name', fuzzable=self.http_fuzz_protocol), Static('\r\n', name='EOL-2'), # Token generated by framework to support following the session if necessary. String('Fuzzer-Token:', name='fuzzer_token', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-4', fuzzable=self.http_fuzz_protocol), String(str(self.gen_uuid), name='fuzzer_token_type', fuzzable=False), # do not fuzz token Static('\r\n', name='EOL-3'), # Accept String('Accept:', name='accept', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-5', fuzzable=self.http_fuzz_protocol), String('*/*', name='accept_type_', fuzzable=self.http_fuzz_protocol), Static('\r\n', name='EOL-4'), # Cache-control no-cache by default String('Cache-Control:', name='cache-control', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-6', fuzzable=self.http_fuzz_protocol), String('no-cache', name='cache_control_type', fuzzable=self.http_fuzz_protocol), Static('\r\n', name='EOL-5'), # Host, the target host String('Host:', name='host_name', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-7', fuzzable=self.http_fuzz_protocol), String(self.target_host, name='target_host', fuzzable=False), # do not fuzz target host address! Static('\r\n', name='EOL-6'), # Connection close, do not use keep-alive it results only one mutation, than the # fuzzer will hang. String('Connection:', name='accept_encoding', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-8', fuzzable=self.http_fuzz_protocol), String('close', name='accept_encoding_types', fuzzable=False), # do not fuzz this field! Static('\r\n', name='EOM-7'), # Content-type from config. String('Content-Type:', name='Content-Type', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-9', fuzzable=self.http_fuzz_protocol), String(self.http_content_type, name='content_type_', fuzzable=self.http_fuzz_protocol), Static('\r\n\r\n', name='EOM-8') ]) if self.http_post_put: self.logger.info( f"[{time.strftime('%H:%M:%S')}] Initiate template for HTTP POST ..." ) http_template = Template( name='HTTP_POST', fields=[ # POST / HTTP/1.1 String('POST', name='method', fuzzable=False), Delimiter(' ', name='delimiter-1', fuzzable=False), String(self.http_path, name='path'), Delimiter(' ', name='delimiter-2', fuzzable=self.http_fuzz_protocol), String('HTTP', name='protocol name', fuzzable=self.http_fuzz_protocol), Delimiter('/', name='fws-1', fuzzable=self.http_fuzz_protocol), Dword(1, name='major version', encoder=ENC_INT_DEC, fuzzable=self.http_fuzz_protocol), Delimiter('.', name='dot-1', fuzzable=self.http_fuzz_protocol), Dword(1, name='minor version', encoder=ENC_INT_DEC, fuzzable=self.http_fuzz_protocol), Static('\r\n', name='EOL-1'), # User agent String('User-Agent:', name='user_agent_field', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-3', fuzzable=self.http_fuzz_protocol), String('Fuzzer', name='user-agent_name', fuzzable=self.http_fuzz_protocol), Static('\r\n', name='EOL-2'), # Token generated by framework to support following the session if necessary. String('Fuzzer-Token:', name='fuzzer_token', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-4', fuzzable=self.http_fuzz_protocol), String(str(self.gen_uuid), name='fuzzer_token_type', fuzzable=self.http_fuzz_protocol), Static('\r\n', name='EOL-3'), # Accept String('Accept:', name='accept', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-5', fuzzable=self.http_fuzz_protocol), String('*/*', name='accept_type_', fuzzable=self.http_fuzz_protocol), Static('\r\n', name='EOL-4'), # Cache-control no-cache by default String('Cache-Control:', name='cache-control', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-6', fuzzable=self.http_fuzz_protocol), String('no-cache', name='cache_control_type', fuzzable=self.http_fuzz_protocol), Static('\r\n', name='EOL-5'), # Host, the target host String('Host:', name='host_name', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-7', fuzzable=self.http_fuzz_protocol), String(self.target_host, name='target_host', fuzzable=False), # do not fuzz target host address! Static('\r\n', name='EOL-6'), # Content length: obvious payload lenght. String('Content-Length:', name='content_length', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-9', fuzzable=self.http_fuzz_protocol), String(str(len(self.http_payload)), name='content_length_len', fuzzable=False), Static('\r\n', name='EOM-8'), # Connection close, do not use keep-alive it results only one mutation, than the # fuzzer will hang. String('Connection:', name='accept_encoding', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-8', fuzzable=self.http_fuzz_protocol), String('close', name='accept_encoding_types', fuzzable=False), # do not fuzz this field! Static('\r\n', name='EOM-7'), # Content type String('Content-Type:', name='Content-Type', fuzzable=self.http_fuzz_protocol), Delimiter(' ', name='delimiter-10', fuzzable=self.http_fuzz_protocol), String(self.http_content_type, name='content_type_', fuzzable=self.http_fuzz_protocol), Static('\n\r\n', name='EOM-9'), # Payload String(self.http_payload, name='payload'), Static('\r\n\r\n', name='EOM-10') ]) self.logger.info( f"[{time.strftime('%H:%M:%S')}] Prepare HttpTarget ...") target = HttpTarget(name='HttpTarget', host=self.target_host, port=self.target_port, max_retries=10, timeout=None) target.set_expect_response('true') self.logger.info( f"[{time.strftime('%H:%M:%S')}] Prepare HttpController ...") controller = HttpGetController('HttpGetController', host=self.target_host, port=self.target_port) target.set_controller(controller) self.logger.info( f"[{time.strftime('%H:%M:%S')}] Defining GraphModel...") model = GraphModel() model.connect(http_template) fuzzer = ServerFuzzer() fuzzer.set_interface(WebInterface(port=26001)) fuzzer.set_model(model) fuzzer.set_target(target) fuzzer.set_delay_between_tests(1) self.logger.info(f"[{time.strftime('%H:%M:%S')}] Start Fuzzer...") self.logger.info( f"[Further info are in the related Kitty log output!]") fuzzer.start() self.logger.info(f"[{time.strftime('%H:%M:%S')}] End Fuzzer Session") fuzzer.stop()
value=report_str ), RandomHidReport( name='random_sequences' ), ]) # ############### Templates ############### # hid_descriptor = Descriptor( name='hid_descriptor', descriptor_type=DescriptorType.hid, fields=[ DynamicInt('bcdHID', LE16(value=0x0110)), DynamicInt('bCountryCode', UInt8(value=0x00)), DynamicInt('bNumDescriptors', UInt8(value=0x01)), DynamicInt('bDescriptorType2', UInt8(value=DescriptorType.hid)), DynamicInt('wDescriptorLength', LE16(value=0x27)), ]) # this descriptor is based on umap # https://github.com/nccgroup/umap # commit 3ad812135f8c34dcde0e055d1fefe30500196c0f hid_report_descriptor = Template( name='hid_report_descriptor', fields=GenerateHidReport( binascii.a2b_hex('05010906A101050719E029E7150025017501950881029501750881011900296515002565750895018100C0') ) )
It also demonstrate how to user kitty fuzzer command line options. ''' import docopt from kitty.fuzzers import ServerFuzzer from kitty.interfaces import WebInterface from kitty.controllers import EmptyController from katnip.targets.file import FileTarget from kitty.model import GraphModel from kitty.model import String from kitty.model import Template opts = docopt.docopt(__doc__) t1 = Template(name='T1', fields=[ String('The default string', name='S1_1'), String('Another string', name='S1_2'), ]) # Writes content to files target = FileTarget('FileTarget', 'tmp/', 'fuzzed') controller = EmptyController('EmptyController') target.set_controller(controller) model = GraphModel() model.connect(t1) fuzzer = ServerFuzzer(name="Example 1 - File Generator", option_line=opts['--kitty-options']) fuzzer.set_interface(WebInterface(port=26001)) fuzzer.set_model(model)
fields=[ Container(name='generation', fields=fields), MutableField(name='mutation', value=report_str), RandomHidReport(name='random_sequences'), ]) # ############### Templates ############### # hid_descriptor = Descriptor(name='hid_descriptor', descriptor_type=DescriptorType.hid, fields=[ DynamicInt('bcdHID', LE16(value=0x0110)), DynamicInt('bCountryCode', UInt8(value=0x00)), DynamicInt('bNumDescriptors', UInt8(value=0x01)), DynamicInt('bDescriptorType2', UInt8(value=DescriptorType.hid)), DynamicInt('wDescriptorLength', LE16(value=0x27)), ]) # this descriptor is based on umap # https://github.com/nccgroup/umap # commit 3ad812135f8c34dcde0e055d1fefe30500196c0f hid_report_descriptor = Template( name='hid_report_descriptor', fields=GenerateHidReport( '05010906A101050719E029E7150025017501950881029501750881011900296515002565750895018100C0' .decode('hex')))
from katnip.targets.tcp import TcpTarget from kitty.model import GraphModel, Template from kitty.interfaces import WebInterface from kitty.fuzzers import ServerFuzzer from kitty.model.low_level.aliases import * from kitty.model.low_level.field import * from server_controller import SessionServerController target_ip = '127.0.0.1' target_port = 9999 web_port = 26001 get_session = Template(name='get_session', fields=[ UInt8(value=1, name='op_code', fuzzable=False), UInt16(value=0, name='session_id', fuzzable=False) ]) send_data = Template(name='send_data', fields=[ UInt8(value=2, name='op_code', fuzzable=False), Dynamic(key='session_id', default_value='\x00\x00'), String(name='data', value='some data') ]) def new_session_callback(fuzzer, edge, resp): ''' :param fuzzer: the fuzzer object :param edge: the edge in the graph we currently at.
def compile_template(self): _url = Static(name='url', value=self.url.encode()) _method = Static(name='method', value=self.method.encode()) template = Template(name=self.name, fields=[_url, _method]) if list(self.params): template.append_fields( [Container(name='params', fields=self.params)]) if list(self.headers): template.append_fields( [Container(name='headers', fields=self.headers)]) if list(self.data): template.append_fields([Container(name='data', fields=self.data)]) if list(self.path_variables): template.append_fields( [Container(name='path_variables', fields=self.path_variables)]) if list(self.cookies): template.append_fields( [Container(name='cookies', fields=self.cookies)]) return template
from kitty.model import Template, Container, Static, OneOf from id3v23 import id3v23container from apetagv2 import apev2container mp3base = Template( name="mp3base", fields=[ OneOf(name="tag", fields=[id3v23container, apev2container]), Container( name="audio_frame", fields=[ Static( name="default_data", value= "fff310c40002d11aec01401001fffffffffa9c0c0c0c0cf9d5fffff312c40103593f1401803800ffffffd3ff512097c1f37a81aa27fff310c40102f91ee809c08000fffffffff288b841789e3f0008fff310c40202f91b007800143e0403f5fffff0a809cd56000c07fff310c403036916ec7800612003f3ffffea082126016d4d000cfff310c40203291f1c78000e3f0703f5fffff106507aaee2000afff310c40202e1170c7800143f0503f5fffff0606980fa000e07fff310c40302e803307800447203fffffb7fea702755000e0703fff310c40402a123307800872af5fffff8d19ea50281fffffffffff312c40602a11f2819401002fe71a21c85fffffffffff3140dfcfff310c40903493f1401803801207f424a2afffffffc1a51e416fff310c408028006d801c000000e164c414d45332e3937202861fff310c40b00000348000000006c70686129aaaaaaaaaaaaaaaa" .decode("hex")), ]) ])
def get_templates(self): res = [] res.append(Template(name='t1', fields=[String('data1')])) res.append(Template(name='t2', fields=[String('data2'), UInt32(300)])) res.append(Template(name='t3', fields=[UInt32(400)])) return res
self.report.add('process_name', self._process_name) self.report.add('process_path', self._process_path) self.report.add('process_args', self._process_args) self.report.add('process_id', self._process.pid) #tcptarget overwrite for perfoming additional post-checks (not yet implemented) class MyTcpTarget(TcpTarget): def post_test(self, test_num): super(MyTcpTarget, self).post_test(test_num) get_startdt = Template(name='get_startdt', fields=[ UInt8(value=0x68, name='startbyte', fuzzable=False), UInt8(value=0x04, name='len'), UInt16(value=0x0700, name='c1'), UInt16(value=0x0000, name='c2') ]) get_stopdt = Template(name='get_stopdt', fields=[ UInt8(value=0x68, name='startbyte'), UInt8(value=0x04, name='len'), UInt16(value=0x1300, name='c1'), UInt16(value=0x0000, name='c2') ]) get_testfr = Template(name='get_testfr', fields=[ UInt8(value=0x68, name='startbyte'),
if content: content_name = '%s_content' + name if isinstance(content, StringTypes): fields.append(String(content, fuzzable=fuzz_content, name=content_name)) elif isinstance(content, IntType): fields.append(SInt32(content, encoder=ENC_INT_DEC, fuzzable=fuzz_content, name=content_name)) elif isinstance(content, ListType): fields.append(Static(delimiter)) for elem in content: _check_type(elem, XmlElement, 'element inside the content list') fields.append(elem) fields.append(Static('</')) fields.append(Clone(value_field)) fields.append(Static('>' + delimiter)) super(XmlElement, self).__init__(fields, name=name) if __name__ == '__main__': # name, attribute, value, fuzz_attribute=False, fuzz_value=True attributes = [ XmlAttribute(name='attr1', attribute='boom', value='attr1 value'), XmlAttribute(name='attr2', attribute='box', value=2), ] inner_elements = [ XmlElement(name='inner element', element_name='an_inner_element', content=1, delimiter='\n'), XmlElement(name='inner element 2', element_name='an_inner_element', content='brrr', delimiter='\n') ] element = XmlElement(name='element1', element_name='an_element', attributes=attributes, content=inner_elements, delimiter='\n') t = Template(element, name='test') print(t.render().tobytes())
descriptor_type=_DescriptorTypes.HID, fields=[ DynamicInt('bcdHID', LE16(value=0x1001)), DynamicInt('bCountryCode', UInt8(value=0x00)), DynamicInt('bNumDescriptors', UInt8(value=0x01)), DynamicInt('bDescriptorType2', UInt8(value=_DescriptorTypes.HID_REPORT)), DynamicInt('wDescriptorLength', LE16(value=0x2b)), ]) # this descriptor is based on umap # https://github.com/nccgroup/umap # commit 3ad812135f8c34dcde0e055d1fefe30500196c0f audio_report_descriptor = Template( name='audio_report_descriptor', fields=GenerateHidReport( '050C0901A1011500250109E909EA75019502810209E209008106050B092095018142050C09009503810226FF000900750895038102090095049102C0' .decode('hex'))) def size_in_words(x): return len(x) // 16 # This template is based on # http://www.usb.org/developers/docs/devclass_docs/audio10.pdf # Chapter 4.3 audio_control_interface_descriptor = Template( name='audio_control_interface_descriptor', fields=[ SubDescriptor(
def s7(ics_ip): print ">>>>> ICS FUZZING MODULE <<<<<\n" # snap7 server 配置信息 TARGET_IP = ics_ip TARGET_PORT = 102 RANDSEED = int(RandShort()) SRC_TSAP = "0100".encode('hex') DST_TSAP = "0103".encode('hex') # 定义COTP CR建立连接数据包 COTP_CR_PACKET = TPKT() / COTPCR() COTP_CR_PACKET.Parameters = [COTPOption() for i in range(3)] COTP_CR_PACKET.PDUType = "CR" COTP_CR_PACKET.Parameters[0].ParameterCode = "tpdu-size" COTP_CR_PACKET.Parameters[0].Parameter = "\x0a" COTP_CR_PACKET.Parameters[1].ParameterCode = "src-tsap" COTP_CR_PACKET.Parameters[2].ParameterCode = "dst-tsap" COTP_CR_PACKET.Parameters[1].Parameter = SRC_TSAP COTP_CR_PACKET.Parameters[2].Parameter = DST_TSAP # 因为是建立连接使用,因此fuzzable参数需要设置为False避免数据包被变异破坏 COTP_CR_TEMPLATE = Template(name='cotp cr template', fields=[ ScapyField(COTP_CR_PACKET, name='cotp cr', fuzzable=False), ]) # 定义通讯参数配置数据结构 SETUP_COMM_PARAMETER_PACKET = TPKT() / COTPDT(EOT=1) / S7Header( ROSCTR="Job", Parameters=S7SetConParameter()) SETUP_COMM_PARAMETER_TEMPLATE = Template( name='setup comm template', fields=[ ScapyField(SETUP_COMM_PARAMETER_PACKET, name='setup comm', fuzzable=False), ]) # 定义需要Fuzzing的数据包结构, 下面例子中将使用RandShort对请求的SZLId及SZLIndex值进行变异测试 READ_SZL_PACKET = TPKT() / COTPDT(EOT=1) / S7Header( ROSCTR="UserData", Parameters=S7ReadSZLParameterReq(), Data=S7ReadSZLDataReq(SZLId=RandShort(), SZLIndex=RandShort())) # 定义READ_SZL_TEMPLATE为可以进行变异的结构,fuzzing的次数为1000次 READ_SZL_TEMPLATE = Template(name='read szl template', fields=[ ScapyField(READ_SZL_PACKET, name='read szl', fuzzable=True, fuzz_count=1000), ]) # 使用GraphModel进行Fuzz model = GraphModel() # 在使用GraphModel中注册第一个节点, 首先发送COTP_CR请求。 model.connect(COTP_CR_TEMPLATE) # 在使用GraphModel中注册第二个节点, 在发送完COTP_CR后发送SETUP_COMM_PARAMETER请求 model.connect(COTP_CR_TEMPLATE, SETUP_COMM_PARAMETER_TEMPLATE) # 在使用GraphModel中注册第三个节点, 在发送完SETUP_COMM_PARAMETER后发送READ_SZL请求 model.connect(SETUP_COMM_PARAMETER_TEMPLATE, READ_SZL_TEMPLATE) # define target s7comm_target = TcpTarget(name='s7comm target', host=TARGET_IP, port=TARGET_PORT, timeout=2) # 定义是需要等待Target返回响应,如果设置为True Target不返回数据包则会被识别成异常进行记录 s7comm_target.set_expect_response(True) # 定义使用基础的ServerFuzzer进行Fuzz测试 fuzzer = ServerFuzzer() # 定义fuzzer使用的交互界面为web界面 fuzzer.set_interface(WebInterface(port=26001)) # 在fuzzer中定义使用GraphModel fuzzer.set_model(model) # 在fuzzer中定义target为s7comm_target fuzzer.set_target(s7comm_target) # 定义每个测试用例发送之间的延迟 fuzzer.set_delay_between_tests(0.1) # 开始执行Fuzz fuzzer.start()
def warp_with_template(fields): ''' wrap a lego with template ''' return Template(name='uut template', fields=fields)
from kitty.model import String, UInt8, BE32, BE16, RandomBytes from kitty.model import SizeInBytes from numap.fuzz.templates.generic import SizedPt # TODO: scsi_test_unit_ready_response (nothing to fuzz! no data returned, besides the csw) # TODO: scsi_send_diagnostic_response # TODO: scsi_prevent_allow_medium_removal_response # TODO: scsi_write_10_response (nothing to fuzz! no data returned, besides the csw) # TODO: scsi_write_6_response # TODO: scsi_read_6_response # TODO: scsi_verify_10_response # USBMassStorageClass msc_get_max_lun_response = Template( name='msc_get_max_lun_response', fields=UInt8(name='Max_LUN', value=0x00)) # Request Sense - FuzzableUSBMassStorageInterface scsi_request_sense_response = Template( name='scsi_request_sense_response', fields=[ UInt8(name='ResponseCode', value=0x70), UInt8(name='VALID', value=0x00), UInt8(name='Obsolete', value=0x00), UInt8(name='SenseKey', value=0x00), UInt8(name='Resv', value=0x00), UInt8(name='ILI', value=0x00), UInt8(name='EOM', value=0x00), UInt8(name='FILEMARK', value=0x00),