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
Beispiel #2
0
    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)
Beispiel #3
0
 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
Beispiel #4
0
 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()
Beispiel #5
0
    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()
Beispiel #6
0
 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)
Beispiel #7
0
 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)
Beispiel #8
0
 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
Beispiel #9
0
 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
Beispiel #10
0
    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)
Beispiel #11
0
    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
Beispiel #12
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
Beispiel #13
0
 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
Beispiel #14
0
 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
Beispiel #15
0
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()
Beispiel #16
0
    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)
Beispiel #17
0
    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)
Beispiel #18
0
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')
Beispiel #19
0
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()
Beispiel #20
0
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()
Beispiel #22
0
    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()
Beispiel #23
0
                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')
    )
)
Beispiel #24
0
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)
Beispiel #25
0
                 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')))
Beispiel #26
0
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.
Beispiel #27
0
 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
Beispiel #28
0
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")),
            ])
    ])
Beispiel #29
0
 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'),
Beispiel #31
0
        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())
Beispiel #32
0
    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(
Beispiel #33
0
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()
Beispiel #34
0
def warp_with_template(fields):
    '''
    wrap a lego with template
    '''
    return Template(name='uut template', fields=fields)
Beispiel #35
0
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),