Esempio n. 1
0
    def __init__ (self, block_name, request, min_reps=0, max_reps=None, step=1, variable=None, fuzzable=True, name=None):
        '''
        Repeat the rendered contents of the specified block cycling from min_reps to max_reps counting by step. By
        default renders to nothing. This block modifier is useful for fuzzing overflows in table entries. This block
        modifier MUST come after the block it is being applied to.

        @type  block_name: String
        @param block_name: Name of block to apply sizer to
        @type  request:    s_request
        @param request:    Request this block belongs to
        @type  min_reps:   Integer
        @param min_reps:   (Optional, def=0) Minimum number of block repetitions
        @type  max_reps:   Integer
        @param max_reps:   (Optional, def=None) Maximum number of block repetitions
        @type  step:       Integer
        @param step:       (Optional, def=1) Step count between min and max reps
        @type  variable:   Sulley Integer Primitive
        @param variable:   (Optional, def=None) Repititions will be derived from this variable, disables fuzzing
        @type  fuzzable:   Boolean
        @param fuzzable:   (Optional, def=True) Enable/disable fuzzing of this primitive
        @type  name:       String
        @param name:       (Optional, def=None) Specifying a name gives you direct access to a primitive
        '''

        self.block_name    = block_name
        self.request       = request
        self.variable      = variable
        self.min_reps      = min_reps
        self.max_reps      = max_reps
        self.step          = step
        self.fuzzable      = fuzzable
        self.name          = name

        self.value         = self.original_value = ""   # default to nothing!
        self.rendered      = ""                         # rendered value
        self.fuzz_complete = False                      # flag if this primitive has been completely fuzzed
        self.fuzz_library  = []                         # library of static fuzz heuristics to cycle through.
        self.mutant_index  = 0                          # current mutation number
        self.current_reps  = min_reps                   # current number of repetitions

        # ensure the target block exists.
        if self.block_name not in self.request.names:
            raise sex.SullyRuntimeError("CAN NOT ADD REPEATER FOR NON-EXISTANT BLOCK: %s" % self.block_name)

        # ensure the user specified either a variable to tie this repeater to or a min/max val.
        if self.variable == None and self.max_reps == None:
            raise sex.SullyRuntimeError("REPEATER FOR BLOCK %s DOES NOT HAVE A MIN/MAX OR VARIABLE BINDING" % self.block_name)

        # if a variable is specified, ensure it is an integer type.
        if self.variable and not isinstance(self.variable, primitives.bit_field):
            print self.variable
            raise sex.SullyRuntimeError("ATTEMPT TO BIND THE REPEATER FOR BLOCK %s TO A NON INTEGER PRIMITIVE" % self.block_name)

        # if not binding variable was specified, propogate the fuzz library with the repetition counts.
        if not self.variable:
            self.fuzz_library = range(self.min_reps, self.max_reps + 1, self.step)
        # otherwise, disable fuzzing as the repitition count is determined by the variable.
        else:
            self.fuzzable = False
Esempio n. 2
0
    def post_fail(self, logger, *args, **kwargs):
        """Tries to reset device over HTTP and wait before returning.

        After sending HTTP request and receiving response, wait
        self._reset_delay + self._dut_reset_time seconds.

        If the outlet does not respond (after self._timeout seconds), this
        method will raise an exception.

        This method will log actions associated with HTTP communication. It
        assumes that a test step is already opened.

        Args:
            logger (ifuzz_logger.IFuzzLogger):
                For logging communications with outlet device.
            *args: Kept for forward-compatibility.
            **kwargs: Kept for forward-compatibility.

        Raises:
            sex.SulleyRuntimeError: If the reset fails due to:
                - no response in self._timeout seconds or
                - unexpected response contents (see
                  EzOutletReset.EXPECTED_RESPONSE_CONTENTS)
        """
        _ = args  # only for forward-compatibility
        _ = kwargs  # only for forward-compatibility
        logger = logger

        url = _build_url(self._hostname, self.RESET_URL_PATH)

        logger.log_info(self.LOG_REQUEST_MSG.format(url))

        try:
            opened_url = urllib2.urlopen(url, timeout=self._timeout)
        except urllib2.URLError:
            if logger is not None:
                logger.log_info(self.NO_RESPONSE_MSG.format(self._timeout))
            raise sex.SullyRuntimeError(self.NO_RESPONSE_MSG.format(self._timeout)), \
                None, \
                sys.exc_info()[2]

        received = opened_url.read()

        logger.log_recv(received)

        if received != self.EXPECTED_RESPONSE_CONTENTS:
            raise sex.SullyRuntimeError(
                self.UNEXPECTED_RESPONSE_MSG.format(received))

        time.sleep(self._reset_delay + self._dut_reset_time)
Esempio n. 3
0
    def push(self, item):
        '''
        Push an item into the block structure. If no block is open, the item goes onto the request stack. otherwise,
        the item goes onto the last open blocks stack.
        '''

        # if the item has a name, add it to the internal dictionary of names.
        if hasattr(item, "name") and item.name:
            # ensure the name doesn't already exist.
            if item.name in self.names.keys():
                raise sex.SullyRuntimeError("BLOCK NAME ALREADY EXISTS: %s" %
                                            item.name)

            self.names[item.name] = item

        # if there are no open blocks, the item gets pushed onto the request stack.
        # otherwise, the pushed item goes onto the stack of the last opened block.
        if not self.block_stack:
            self.stack.append(item)
        else:
            self.block_stack[-1].push(item)

        # add the opened block to the block stack.
        if isinstance(item, block):
            self.block_stack.append(item)
Esempio n. 4
0
    def post_fail(self, logger, *args, **kwargs):
        """Call reset() and log actions.

        See reset() docstring for details.

        This method will log actions associated with HTTP communication. It
        assumes that a test step is already opened.

        Args:
            logger (ifuzz_logger.IFuzzLogger):
                For logging communications with outlet device.
            *args: Kept for forward-compatibility.
            **kwargs: Kept for forward-compatibility.

        Raises:
            sex.SullyRuntimeError: If the reset fails due to:
                - no response in self._timeout seconds or
                - unexpected response contents (see
                  EzOutletReset.EXPECTED_RESPONSE_CONTENTS)
        """
        _ = args  # only for forward-compatibility
        _ = kwargs  # only for forward-compatibility

        logger.log_info(self.LOG_REQUEST_MSG.format(self.url))

        try:
            response = self.reset()
            logger.log_recv(response)
        except EzOutletResetError as e:
            logger.log_info(e.message)
            raise sex.SullyRuntimeError(e.message), \
                None, \
                sys.exc_info()[2]
Esempio n. 5
0
    def pop (self):
        '''
        The last open block was closed, so pop it off of the block stack.
        '''

        if not self.block_stack:
            raise sex.SullyRuntimeError("BLOCK STACK OUT OF SYNC")

        self.block_stack.pop()
Esempio n. 6
0
    def __init__ (self, name, request, group=None, encoder=None, dep=None, dep_value=None, dep_values=[], dep_compare="=="):
        '''
        The basic building block. Can contain primitives, sizers, checksums or other blocks.

        @type  name:        String
        @param name:        Name of the new block
        @type  request:     s_request
        @param request:     Request this block belongs to
        @type  group:       String
        @param group:       (Optional, def=None) Name of group to associate this block with
        @type  encoder:     Function Pointer
        @param encoder:     (Optional, def=None) Optional pointer to a function to pass rendered data to prior to return
        @type  dep:         String
        @param dep:         (Optional, def=None) Optional primitive whose specific value this block is dependant on
        @type  dep_value:   Mixed
        @param dep_value:   (Optional, def=None) Value that field "dep" must contain for block to be rendered
        @type  dep_values:  List of Mixed Types
        @param dep_values:  (Optional, def=[]) Values that field "dep" may contain for block to be rendered
        @type  dep_compare: String
        @param dep_compare: (Optional, def="==") Comparison method to apply to dependency (==, !=, >, >=, <, <=)
        '''

        self.name          = name
        self.request       = request
        self.group         = group
        self.encoder       = encoder
        self.dep           = dep
        self.dep_value     = dep_value
        self.dep_values    = dep_values
        self.dep_compare   = dep_compare
        self.s_type        = "block"

        if not name:
            raise sex.SullyRuntimeError("'%s' requires a name" % self.s_type)
        if name and not type(name) is str:
            raise sex.SullyRuntimeError("'%s' name has to be of type str" % self.s_type)


        self.stack         = []     # block item stack.
        self.rendered      = ""     # rendered block contents.
        self.fuzzable      = True   # blocks are always fuzzable because they may contain fuzzable items.
        self.group_idx     = 0      # if this block is tied to a group, the index within that group.
        self.fuzz_complete = False  # whether or not we are done fuzzing this block.
        self.mutant_index  = 0      # current mutation index.
Esempio n. 7
0
    def __init__(self, block_name, request, algorithm="crc32", length=0, endian="<", name=None):
        '''
        Create a checksum block bound to the block with the specified name. You *can not* create a checksm for any
        currently open blocks.

        @type  block_name: String
        @param block_name: Name of block to apply sizer to
        @type  request:    s_request
        @param request:    Request this block belongs to
        @type  algorithm:  String
        @param algorithm:  (Optional, def=crc32) Checksum algorithm to use. (crc32, adler32, md5, sha1)
        @type  length:     Integer
        @param length:     (Optional, def=0) Length of checksum, specify 0 to auto-calculate
        @type  endian:     Character
        @param endian:     (Optional, def=LITTLE_ENDIAN) Endianess of the bit field (LITTLE_ENDIAN: <, BIG_ENDIAN: >)
        @type  name:       String
        @param name:       Name of this checksum field
        '''

        self.block_name = block_name
        self.request    = request
        self.algorithm  = algorithm
        self.length     = length
        self.endian     = endian
        self.name       = name
        self.s_type     = "checksum"

        if not block_name:
            raise sex.SullyRuntimeError("'%s' requires a block_name" % self.s_type)
        if block_name and not type(block_name) is str:
            raise sex.SullyRuntimeError("'%s' requires block_name to be of type str" % self.s_type)
        if algorithm and not type(algorithm) is str:
            raise sex.SullyRuntimeError("'%s' requires algorithm to be of type str" % self.s_type)
        if length and not type(length) is int:
            raise sex.SullyRuntimeError("'%s' requires length to be of type int" % self.s_type)
        if endian != ">" and endian != "<":
            raise sex.SullyRuntimeError("'%s' requires endian to be '>' or '<'" % self.s_type)

        self.rendered   = ""
        self.fuzzable   = False

        if not self.length and self.checksum_lengths.has_key(self.algorithm):
            self.length = self.checksum_lengths[self.algorithm]
Esempio n. 8
0
    def checksum(self, data):
        '''
        Calculate and return the checksum (in raw bytes) over the supplied data.

        @type  data: Raw
        @param data: Rendered block data to calculate checksum over.

        @rtype:  Raw
        @return: Checksum.
        '''

        if type(self.algorithm) is str:
            if self.algorithm == "crc32":
                return struct.pack(self.endian + "L",
                                   (zlib.crc32(data) & 0xFFFFFFFFL))

            elif self.algorithm == "adler32":
                return struct.pack(self.endian + "L",
                                   (zlib.adler32(data) & 0xFFFFFFFFL))

            elif self.algorithm == "md5":
                digest = hashlib.md5(data).digest()

                # TODO: is this right?
                if self.endian == ">":
                    (a, b, c, d) = struct.unpack("<LLLL", digest)
                    digest = struct.pack(">LLLL", a, b, c, d)

                return digest

            elif self.algorithm == "sha1":
                digest = hashlib.sha1(data).digest()

                # TODO: is this right?
                if self.endian == ">":
                    (a, b, c, d, e) = struct.unpack("<LLLLL", digest)
                    digest = struct.pack(">LLLLL", a, b, c, d, e)

                return digest
            elif self.algorithm == "crc16":
                return struct.pack(self.endian + "H",
                                   CRC16(data).intchecksum())

            else:
                raise sex.SullyRuntimeError(
                    "INVALID CHECKSUM ALGORITHM SPECIFIED: %s" %
                    self.algorithm)
        else:
            return self.algorithm(data)
Esempio n. 9
0
    def render (self):
        '''
        Nothing fancy on render, simply return the value.
        '''

        # if the target block for this sizer is not closed, raise an exception.
        if self.block_name not in self.request.closed_blocks:
            raise sex.SullyRuntimeError("CAN NOT APPLY REPEATER TO UNCLOSED BLOCK: %s" % self.block_name)

        # if a variable-bounding was specified then set the value appropriately.
        if self.variable:
            block      = self.request.closed_blocks[self.block_name]
            self.value = block.rendered * self.variable.value

        self.rendered = self.value
        return self.rendered
Esempio n. 10
0
    def render(self):
        '''
        @desc: 获取测试数据的字符流
        @type: String
        @return: 返回测试用例
        '''
        # ensure there are no open blocks lingering.
        if self.block_stack:
            raise sex.SullyRuntimeError("UNCLOSED BLOCK: %s" %
                                        self.block_stack[-1].name)

        # render every item in the stack.
        for item in self.stack:
            item.render()

        # process remaining callbacks.
        for key in self.callbacks.keys():
            for item in self.callbacks[key]:
                item.render()

        def update_size(stack, name):
            # walk recursively through each block to update its size
            blocks = []

            for item in stack:
                if isinstance(item, size):
                    item.render()
                elif isinstance(item, block):
                    blocks += [item]

            for b in blocks:
                update_size(b.stack, b.name)
                b.render()

        # call update_size on each block of the request
        for item in self.stack:
            if isinstance(item, block):
                update_size(item.stack, item.name)
                item.render()

        # now collect, merge and return the rendered items.
        self.rendered = ""

        for item in self.stack:
            self.rendered += item.rendered

        return self.rendered
Esempio n. 11
0
    def mutate(self):
        '''
        Mutate the primitive by stepping through the fuzz library, return False on completion. If variable-bounding is
        specified then fuzzing is implicitly disabled. Instead, the render() routine will properly calculate the
        correct repitition and return the appropriate data.

        @rtype:  Boolean
        @return: True on success, False otherwise.
        '''

        # render the contents of the block we are repeating.
        self.request.names[self.block_name].render()

        # if the target block for this sizer is not closed, raise an exception.
        if self.block_name not in self.request.closed_blocks:
            raise sex.SullyRuntimeError(
                "CAN NOT APPLY REPEATER TO UNCLOSED BLOCK: %s" %
                self.block_name)

        # if we've run out of mutations, raise the completion flag.
        if self.mutant_index == self.num_mutations():
            self.fuzz_complete = True

        # if fuzzing was disabled or complete, and mutate() is called, ensure the original value is restored.
        if not self.fuzzable or self.fuzz_complete:
            self.value = self.original_value
            self.current_reps = self.min_reps
            return False

        if self.variable:
            self.current_reps = self.variable.value
        else:
            self.current_reps = self.fuzz_library[self.mutant_index]

        # set the current value as a multiple of the rendered block based on the current fuzz library count.
        block = self.request.closed_blocks[self.block_name]
        self.value = block.rendered * self.fuzz_library[self.mutant_index]

        # increment the mutation count.
        self.mutant_index += 1

        return True
Esempio n. 12
0
    def fuzz (self, this_node=None, path=[]):
        '''
        Call this routine to get the ball rolling. No arguments are necessary as they are both utilized internally
        during the recursive traversal of the session graph.

        @type  this_node: request (node)
        @param this_node: (Optional, def=None) Current node that is being fuzzed.
        @type  path:      List
        @param path:      (Optional, def=[]) Nodes along the path to the current one being fuzzed.
        '''

        # if no node is specified, then we start from the root node and initialize the session.
        if not this_node:
            # we can't fuzz if we don't have at least one target and one request.
            if not self.targets:
                raise sex.SullyRuntimeError("NO TARGETS SPECIFIED IN SESSION")

            if not self.edges_from(self.root.id):
                raise sex.SullyRuntimeError("NO REQUESTS SPECIFIED IN SESSION")

            this_node = self.root

            try:    self.server_init()
            except: return

        # TODO: complete parallel fuzzing, will likely have to thread out each target
        target = self.targets[0]

        # step through every edge from the current node.
        for edge in self.edges_from(this_node.id):
            # the destination node is the one actually being fuzzed.
            self.fuzz_node = self.nodes[edge.dst]
            num_mutations  = self.fuzz_node.num_mutations()

            # keep track of the path as we fuzz through it, don't count the root node.
            # we keep track of edges as opposed to nodes because if there is more then one path through a set of
            # given nodes we don't want any ambiguity.
            path.append(edge)

            current_path  = " -> ".join([self.nodes[e.src].name for e in path[1:]])
            current_path += " -> %s" % self.fuzz_node.name

            self.logger.info("current fuzz path: %s" % current_path)
            self.logger.info("fuzzed %d of %d total cases" % (self.total_mutant_index, self.total_num_mutations))

            done_with_fuzz_node = False
            crash_count         = 0

            # loop through all possible mutations of the fuzz node.
            while not done_with_fuzz_node:
                # if we need to pause, do so.
                self.pause()

                # if we have exhausted the mutations of the fuzz node, break out of the while(1).
                # note: when mutate() returns False, the node has been reverted to the default (valid) state.
                if not self.fuzz_node.mutate():
                    self.logger.error("all possible mutations for current fuzz node exhausted")
                    done_with_fuzz_node = True
                    continue

                # make a record in the session that a mutation was made.
                self.total_mutant_index += 1

                # if we've hit the restart interval, restart the target.
                if self.restart_interval and self.total_mutant_index % self.restart_interval == 0:
                    self.logger.error("restart interval of %d reached" % self.restart_interval)
                    self.restart_target(target)

                # exception error handling routine, print log message and restart target.
                def error_handler (e, msg, target, sock=None):
                    if sock:
                        sock.close()

                    msg += "\nException caught: %s" % repr(e)
                    msg += "\nRestarting target and trying again"

                    self.logger.critical(msg)
                    self.restart_target(target)

                # if we don't need to skip the current test case.
                if self.total_mutant_index > self.skip:
                    self.logger.info("fuzzing %d of %d" % (self.fuzz_node.mutant_index, num_mutations))

                    # attempt to complete a fuzz transmission. keep trying until we are successful, whenever a failure
                    # occurs, restart the target.
                    while 1:
                        # instruct the debugger/sniffer that we are about to send a new fuzz.
                        if target.procmon:
                            try:
                                target.procmon.pre_send(self.total_mutant_index)
                            except Exception, e:
                                error_handler(e, "failed on procmon.pre_send()", target)
                                continue

                        if target.netmon:
                            try:
                                target.netmon.pre_send(self.total_mutant_index)
                            except Exception, e:
                                error_handler(e, "failed on netmon.pre_send()", target)
                                continue

                        try:
                            # establish a connection to the target.
                            sock = socket.socket(socket.AF_INET, self.proto)
                        except Exception, e:
                            error_handler(e, "failed creating socket", target)
                            continue

                        if self.bind:
                            try:
                                sock.bind(self.bind)
                            except Exception, e:
                                error_handler(e, "failed binding on socket", target, sock)
                                continue

                        try:
                            sock.settimeout(self.timeout)
                            # Connect is needed only for TCP stream
                            if self.proto == socket.SOCK_STREAM:
                                sock.connect((target.host, target.port))
                        except Exception, e:
                            error_handler(e, "failed connecting on socket", target, sock)
                            continue
Esempio n. 13
0
    def __init__(
                  self,
                  session_filename=None,
                  skip=0,
                  sleep_time=1.0,
                  log_level=logging.INFO,
                  logfile=None,
                  logfile_level=logging.DEBUG,
                  proto="tcp",
                  bind=None,
                  restart_interval=0,
                  timeout=5.0,
                  web_port=26000,
                  crash_threshold=3,
                  restart_sleep_time=300
                ):
        '''
        Extends pgraph.graph and provides a container for architecting protocol dialogs.

        @type  session_filename:   String
        @kwarg session_filename:   (Optional, def=None) Filename to serialize persistant data to
        @type  skip:               Integer
        @kwarg skip:               (Optional, def=0) Number of test cases to skip
        @type  sleep_time:         Float
        @kwarg sleep_time:         (Optional, def=1.0) Time to sleep in between tests
        @type  log_level:          Integer
        @kwarg log_level:          (Optional, def=logger.INFO) Set the log level
        @type  logfile:            String
        @kwarg logfile:            (Optional, def=None) Name of log file
        @type  logfile_level:      Integer
        @kwarg logfile_level:      (Optional, def=logger.INFO) Set the log level for the logfile
        @type  proto:              String
        @kwarg proto:              (Optional, def="tcp") Communication protocol ("tcp", "udp", "ssl")
        @type  bind:               Tuple (host, port)
        @kwarg bind:               (Optional, def=random) Socket bind address and port
        @type  timeout:            Float
        @kwarg timeout:            (Optional, def=5.0) Seconds to wait for a send/recv prior to timing out
        @type  restart_interval:   Integer
        @kwarg restart_interval    (Optional, def=0) Restart the target after n test cases, disable by setting to 0
        @type  crash_threshold:    Integer
        @kwarg crash_threshold     (Optional, def=3) Maximum number of crashes allowed before a node is exhaust
        @type  restart_sleep_time: Integer
        @kwarg restart_sleep_time: Optional, def=300) Time in seconds to sleep when target can't be restarted
        @type  web_port:	   Integer
        @kwarg web_port:           (Optional, def=26000) Port for monitoring fuzzing campaign via a web browser	
	'''

        # run the parent classes initialization routine first.
        pgraph.graph.__init__(self)

        self.session_filename    = session_filename
        self.skip                = skip
        self.sleep_time          = sleep_time
        self.proto               = proto.lower()
        self.bind                = bind
        self.ssl                 = False
        self.restart_interval    = restart_interval
        self.timeout             = timeout
        self.web_port            = web_port
        self.crash_threshold     = crash_threshold
        self.restart_sleep_time  = restart_sleep_time

        # Initialize logger
        self.logger = logging.getLogger("Sulley_logger")
        self.logger.setLevel(log_level)
        formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] -> %(message)s')

        if logfile != None:
            filehandler = logging.FileHandler(logfile)
            filehandler.setLevel(logfile_level)
            filehandler.setFormatter(formatter)
            self.logger.addHandler(filehandler)

        consolehandler = logging.StreamHandler()
        consolehandler.setFormatter(formatter)
        consolehandler.setLevel(log_level)
        self.logger.addHandler(consolehandler)

        self.total_num_mutations = 0
        self.total_mutant_index  = 0
        self.fuzz_node           = None
        self.targets             = []
        self.netmon_results      = {}
        self.procmon_results     = {}
        self.protmon_results     = {}
        self.pause_flag          = False
        self.crashing_primitives = {}

        if self.proto == "tcp":
            self.proto = socket.SOCK_STREAM

        elif self.proto == "ssl":
            self.proto = socket.SOCK_STREAM
            self.ssl   = True

        elif self.proto == "udp":
            self.proto = socket.SOCK_DGRAM

        else:
            raise sex.SullyRuntimeError("INVALID PROTOCOL SPECIFIED: %s" % self.proto)

        # import settings if they exist.
        self.import_file()

        # create a root node. we do this because we need to start fuzzing from a single point and the user may want
        # to specify a number of initial requests.
        self.root       = pgraph.node()
        self.root.name  = "__ROOT_NODE__"
        self.root.label = self.root.name
        self.last_recv  = None

        self.add_node(self.root)
Esempio n. 14
0
class session ():
    def __init__(
                  self,
                  loop_sleep_time=0.0,      #每次循环fuzz的时间间隔
                  proto="tcp",              #使用的连接协议
                  sock_timeout=None,        #socket超时时间
                  send_iface="eth0",        #发送数据包使用的网卡
                  sniff_iface="eth0",       #进行网络监听的网卡
                  sniff_stop_filter=None,   #设置网络监视器的stop_filter
                  sniff_timout=None,        #网络监视器超时间隔
                  sniff_switch=False,       #是否启动网络监视器
                  sniff_filter="",          #设置数据包过滤
                  keep_alive=False,         #是否保持socket连接
                  send_sleep_time=0.0,      #发送每个测试用例的时间间隔
                  fuzz_store_limit=None,    #存储生成的fuzz数据最大数量
                  pinger_threshold=None,    #是否开启ping检测crash
                  tcpScan_threshold=None,   #是否开启tcp scan检测crash
                  udpScan_threshold=None,   #是否开启udp scan检测crash
                  cusDect_threshold=None,   #是否开启自定义callback函数检测crash
                  procDect_threshold=None   #是否开启procmon检测crash
                ):

        log_level=logging.INFO
        logfile=None
        logfile_level=logging.DEBUG

        self.loop_sleep_time     = loop_sleep_time
        self.send_sleep_time     = send_sleep_time
        self.proto               = proto.lower()
        self.timeout             = sock_timeout
        self.total_mutant_index  = 0
        self.fuzz_targets        = []
        self.fuzz_blocks         = []
        self.afl_fuzz_blocks     = []
        self.procmon_results     = {}
        self.protmon_results     = {}
        self.pause_flag          = False
        self.crashing_primitives = {}
        self.keep_alive          = keep_alive

        self.layer2              = False
        self.custom              = False
        self.iface               = send_iface

        self.message             = ''
        self.sniff_iface         = sniff_iface
        self.sniff_thread        = None
        self.sniff_switch        = sniff_switch
        self.sniff_filter        = sniff_filter
        self.sniff_stop_filter   = sniff_stop_filter
        self.sniff_timeout       = sniff_timout

        self.cur_mutate_frame    = None
        self.fuzz_store_list     = []
        self.fuzz_store_limit    = fuzz_store_limit
        self.fuzz_send_count     = 0

        self.pinger_threshold    = pinger_threshold
        self.tcpScan_threshold   = tcpScan_threshold
        self.udpScan_threshold   = udpScan_threshold
        self.cusDect_threshold   = cusDect_threshold
        self.procDect_threshold  = procDect_threshold

        #创建网络监视器
        if self.sniff_switch:
            try:
                self.sniff_thread = SniffThread.Sniffer(self.sniff_iface,self.sniff_filter,self.sniff_stop_filter,self.sniff_timeout)
            except Exception, e:
                print "sniff thread create failed. Exception: %s" % str(e)
                os.kill(0 - os.getpid(), signal.SIGKILL)

        #初始化日志
        self.logger = logging.getLogger("NetFuzzer_logger")
        self.logger.setLevel(log_level)
        formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] -> %(message)s')

        if logfile != None:
            filehandler = logging.FileHandler(logfile)
            filehandler.setLevel(logfile_level)
            filehandler.setFormatter(formatter)
            self.logger.addHandler(filehandler)

        consolehandler = logging.StreamHandler()
        consolehandler.setFormatter(formatter)
        consolehandler.setLevel(log_level)
        self.logger.addHandler(consolehandler)

        #判断用户使用的连接协议
        if self.proto == "tcp":
            self.proto = socket.SOCK_STREAM

        elif self.proto == "udp":
            self.proto = socket.SOCK_DGRAM

        elif self.proto == "layer2":
           self.layer2 = True

        elif self.proto == "custom":
            self.custom = True

        else:
            raise sex.SullyRuntimeError("INVALID PROTOCOL SPECIFIED: %s" % self.proto)
Esempio n. 15
0
    def __init__ (self, block_name, request, offset=0, length=4, endian="<", format="binary", synchsafe=False, inclusive=False, signed=False, math=None, fuzzable=False, name=None):
        '''
        Create a sizer block bound to the block with the specified name. You *can not* create a sizer for any
        currently open blocks.

        @type  block_name: String
        @param block_name: Name of block to apply sizer to
        @type  request:    s_request
        @param request:    Request this block belongs to
        @type  offset:     Integer
        @param offset:     (Optional, def=0) Offset for calculated size value
        @type  length:     Integer
        @param length:     (Optional, def=4) Length of sizer
        @type  endian:     Character
        @param endian:     (Optional, def=LITTLE_ENDIAN) Endianess of the bit field (LITTLE_ENDIAN: <, BIG_ENDIAN: >)
        @type  format:     String
        @param format:     (Optional, def=binary) Output format, "binary" or "ascii"
        @type  inclusive:  Boolean
        @param inclusive:  (Optional, def=False) Should the sizer count its own length?
        @type  signed:     Boolean
        @param signed:     (Optional, def=False) Make size signed vs. unsigned (applicable only with format="ascii")
        @type  math:       Function
        @param math:       (Optional, def=None) Apply the mathematical operations defined in this function to the size
        @type  fuzzable:   Boolean
        @param fuzzable:   (Optional, def=False) Enable/disable fuzzing of this sizer
        @type  name:       String
        @param name:       Name of this sizer field
        @type  synchsafe:  Boolean
        @param synchsafe: (Optional, def=False) Synchsafe (https://en.wikipedia.org/wiki/Synchsafe)
        '''

        self.block_name    = block_name
        self.request       = request
        self.offset        = offset
        self.length        = length
        self.endian        = endian
        self.format        = format
        self.inclusive     = inclusive
        self.signed        = signed
        self.math          = math
        self.fuzzable      = fuzzable
        self.name          = name
        self.synchsafe     = synchsafe
        self.s_type        = "size"

        if not block_name:
            raise sex.SullyRuntimeError("'%s' requires a block_name" % self.s_type)
        if block_name and not type(block_name) is str:
            raise sex.SullyRuntimeError("'%s' requires block_name to be of type str" % self.s_type)
        if name and not type(name) is str:
            raise sex.SullyRuntimeError("'%s' requires name to be of type str" % self.s_type)
        if fuzzable != True and fuzzable != False:
            raise sex.SullyRuntimeError("'%s' requires fuzzable to be of type boolean" % self.s_type)
        if not type(offset) is int:
            raise sex.SullyRuntimeError("'%s' requires offset to be of type int" % self.s_type)
        if not type(length) is int:
            raise sex.SullyRuntimeError("'%s' requires length to be of type int" % self.s_type)
        if endian != ">" and endian != "<":
            raise sex.SullyRuntimeError("'%s' requires endian to be '>' or '<'" % self.s_type)
        if not type(format) is str:
            raise sex.SullyRuntimeError("'%s' requires format to be of type str" % self.s_type)
        if synchsafe != True and synchsafe != False:
            raise sex.SullyRuntimeError("'%s' requires synchsafe to be of type boolean" % self.s_type)
        if inclusive != True and inclusive != False:
            raise sex.SullyRuntimeError("'%s' requires inclusive to be of type boolean" % self.s_type)
        if signed != True and signed != False:
            raise sex.SullyRuntimeError("'%s' requires signed to be of type boolean" % self.s_type)

        self.original_value = "N/A"    # for get_primitive
        self.s_type         = "size"   # for ease of object identification
        self.bit_field      = primitives.bit_field(0, self.length*8, endian=self.endian, format=self.format, signed=self.signed, synchsafe=self.synchsafe)
        self.rendered       = ""
        self.fuzz_complete  = self.bit_field.fuzz_complete
        self.fuzz_library   = self.bit_field.fuzz_library
        self.mutant_index   = self.bit_field.mutant_index
        self.value          = self.bit_field.value

        if self.math == None:
            self.math = lambda (x): x