def __init__(self, configfile, base_dir, log_dir, stdin=None, stdout=None, stderr=None): """@brief Initialize the Fuzzbunch object @param configfile The main Fuzzbunch configuration file (an XML file) @param base_dir @param log_dir Location for Fuzzbunch log files @param stdin @param stdout @param stderr """ # Initialize the command interpreter, which creates a CmdCtx self.configvars = {} # Stores global config info (not setg globals) self.readconfig(configfile) # Read in variables set for Fuzzbunch # Fix bug #2910 - Color breaks in some terminals that don't support ansi encoding. Added # option to disable color enablecolor = eval(self.configvars['globals']['Color']) FbCmd.__init__(self, stdin=stdin, stdout=stdout, stderr=stderr, enablecolor=enablecolor ) # Set the info function to Fuzzbunch's print_info function self.defaultcontext.print_info = self.print_info self.preconfig() self.fbglobalvars = util.iDict() # Our Fuzzbunch global variables self.pluginmanagers = util.iDict() # A list of PluginManagers, each # of which contains a list of Plugins. # Create our Session manager, which has a list of the plugins we've run self.session = session.Session(self.name) self.session.set_dirs(base_dir, log_dir) # Set the logdir from the Fuzzbunch.xml file, which will be overridden # later when retarget is executed self.default_logdir = os.path.normpath(log_dir) self.set_logdir(log_dir) # Create a Redirection object to keep track of the status of redirection, and to # perform transforms on the parameters prior to and after executing plugins self.redirection = redirection.RedirectionManager(self.io) self.fontdir = os.path.join(base_dir, "fonts") self.storage = os.path.join(base_dir, "storage") self.setbanner() self.postconfig() self.pwnies = False self.conv_tools = util.iDict([('MultiLine', self.toolpaste_ep), ('MD5', self.toolpaste_md5), ('SHA1', self.toolpaste_sha1), ('Base64', self.toolpaste_base64), ]) self.log = log(self.name, self.version, dict(debugging=True, enabled=True, verbose=False))
def __init__(self, type, fb): CmdCtx.__init__(self, type, type) self.pluginList = util.iDict() self.activePlugin = None self.session = fb.session self.io = fb.io self.fb = fb
def prompt_param(self, name, value, plugin): """Prompt for a parameter, and set the value in the session on response""" valid_convert = {1 : "YES", 0 : "NO"} param = plugin.getParameter(name) attribs = util.iDict(param.getAttributeList()) attribvals = param.getAttributeValueList() args = {'name' : name, 'value' : value, 'description' : attribs['Description'], 'required' : attribs['Required'], 'valid' : valid_convert[plugin.isValid(name)], 'type' : attribs.get('Type', "Choice"), 'attribs' : attribvals,} if plugin.isParamchoice(name): default_value = "" for i,p in enumerate(attribvals): if p.name.lower() == value.lower(): default_value = str(i) else: default_value = value self.io.print_prompt_param(args, default_value) line = self.io.prompt_user(name, default_value, attribvals, gvars=self.fb.fbglobalvars) if line != value: self.do_set(name + " " + line) if plugin.hasValidValue(name): return True else: return False
def iterPromptParameters(self): # Take all the root level parameters first rootparams = self._trch_getrootparameterlist() for param in self.getParameters(): if self._trch_isparameter(param.name) and \ param in rootparams and \ not self.isHiddenParameter(param.name): yield param # Walk all choices. Need to take into account that setting a choice # causes changes to everything below it. usedchoices = [] done = False while not done: for param in self.getParameters(): if self._trch_isparamchoice(param.name) and \ param.name not in usedchoices and \ not self.isHiddenParameter(param.name): usedchoices.append(param.name) yield param break else: done = True usedchoices += util.iDict(rootparams).keys() # Now all the choices are stable, we can walk all params that are under # a choice which is anything that we haven't looked at yet for param in self.getParameters(): if self._trch_isparameter(param.name) and \ param.name not in usedchoices and \ not self.isHiddenParameter(param.name): yield param
def touch_mapoutput(self, plugin, touch, contract): self.io.print_msg("Exporting Contract To Exploit") params = util.iDict() for param in contract.get_paramlist(): params[param.name] = [(param, contract)] if param.name in touch['oparams']: params[touch['oparams'][param.name]] = [(param, contract)] for var, val in plugin.iterPromptParameters(): if var in touch['oparams'].values(): self.apply_singleloop(var, params, plugin, True)
def straight_local(self, l, plugin): """Effectively just print the straight path to the target""" params = iDict(plugin.getParameters()) laddr = self.conv_param(l.listenaddr, params) lport = self.conv_param(l.listenport, params) if not laddr or not lport: return # HACK HACK # The logic here was previously wrong, which meant that people didn't have to be careful # about their redirection sections. Until we get them fixed, we need a hack that will # allow these invalid redirection sections if we try it the valid way and fail enable_hack = False try: cache = { l.destaddr: plugin.get(l.destaddr), l.destport: plugin.get(l.destport) } laddr = self.conv_param(l.destaddr, params) lport = self.conv_param(l.destport, params) except exception.CmdErr: enable_hack = True cache = { l.destaddr: plugin.get(l.listenaddr), l.destport: plugin.get(l.listenport) } self.io.print_success("Local Tunnel - %s" % l.name) try: if not enable_hack: targetip = self.prompt_redir(plugin, l.destaddr, 'Destination IP', laddr) targetport = self.prompt_redir(plugin, l.destport, 'Destination Port', lport) self.io.print_success("(%s) Local %s:%s" % (l.protocol, targetip, targetport)) else: targetip = self.prompt_redir(plugin, l.listenaddr, 'Destination IP', laddr) targetport = self.prompt_redir(plugin, l.listenport, 'Destination Port', lport) self.io.print_success("(%s) Local %s:%s" % (l.protocol, targetip, targetport)) except exception.PromptErr: self.io.print_error("Aborted by user") for (var, val) in cache.items(): try: plugin.set(var, val) except: self.io.print_error( "Error setting '%s' - May be in an inconsistent state" % var) raise except Exception as e: self.io.print_error("Error: {0}".format(str(type(e))))
def prompt_param_help(self, name, value, plugin): valid_convert = {1 : "YES", 0 : "NO"} param = plugin.getParameter(name) attribs = util.iDict(param.getAttributeList()) attribvals = param.getAttributeValueList() args = {'name' : name, 'value' : value, 'description' : attribs['Description'], 'required' : attribs['Required'], 'valid' : valid_convert[plugin.isValid(name)], 'type' : attribs.get('Type', "Choice"), 'attribs' : attribvals,} self.io.print_prompt_param_help(args)
def wrap(self, name, value): paramcache = self.cache_choiceparams(name) old = self.get(name) f(self, name, value) if not self.hasValidValue(name): # Restore to the old self._trch_set(name, old) raise exception.CmdErr, "Invalid value for %s (%s)" % (name, value) # We want var matches, not var/val for param in paramcache: if param.name in util.iDict(self.cache_choiceparams(name)): try: if not self.getParameter(param.name).isHidden(): self.set(*param) except (exception.CmdErr, AttributeError): # XXX Is ignoring errors here a good idea? pass
def getParameters(self, hidden=True): """Get the current parameter list""" # Members of the plist array are dictionary items plist = self._trch_getparameterlist() if not hidden: plist = [x for x in plist if not self.isHiddenParameter(x.name)] if not self.param_order: return plist # Give them same order in which they appear in xml file pdict = util.iDict(plist) order = [ util.Param(pname, pdict.pop(pname) or "") for pname in self.param_order if pname in pdict ] return order + list(pdict.items())
def straight_remote(self, r, plugin): params = iDict(plugin.getParameters()) lport = self.conv_param(r.listenport, params) dport = self.conv_param(r.destport, params) laddr = self.conv_param(r.listenaddr, params) if None in (lport, dport, laddr): return # Do we need to choose a random local port? # XXX - This won't happen unless lport is 0 if not lport or lport == "0": lport = rand_port() # Store off the old values so that we can restore them after the # plug-in executes cache = { r.listenaddr: plugin.get(r.listenaddr), r.listenport: plugin.get(r.listenport), r.destport: plugin.get(r.destport) } self.io.print_success("Remote Tunnel - %s" % r.name) try: # Modify the plugin and report success callbackip = self.prompt_redir(plugin, r.listenaddr, 'Listen IP', laddr) callbackport = self.prompt_redir(plugin, r.listenport, 'Listen Port', lport) plugin.set(r.destport, callbackport) self.io.print_success("(%s) Remote %s:%s" % (r.protocol, callbackip, callbackport)) except exception.PromptErr: self.io.print_error("Aborted by user") for (var, val) in cache.items(): try: plugin.set(var, val) except: self.io.print_error( "Error setting '%s' - May be in an inconsistent state" % var) raise
def do_apply(self, input): """Apply parameters values from session items""" plugin = self.get_active_plugin() params = util.iDict() inputList = input.strip().split() if not inputList: # Case where we just type 'apply' for contract in self.session.get_contractlist(): for param in contract.get_paramlist(): params.setdefault(param.name, []).append((param, contract)) self.apply_process(params, plugin) else: # Case where we type 'apply X' try: index = int(inputList[0]) except ValueError: raise exception.CmdErr, "apply [index]" contract = self.fb.session.get_contract(index) for param in contract.get_paramlist(): params[param.name] = [(param, contract)] self.apply_process(params, plugin, singlemode=True)
def parse_touchlist(xmlFile): """ Touch lists INPUT ----- Touch lists are in a plugin's meta file. Touch lists are optional. <t:touchlist> <t:plugin name="TouchPluginName" displayname="How to display in fb" description="Descr for fb"> <t:iparam name="Param1" value="val" /> <t:oparam name="Param1" value="ParamFoo" /> </t:plugin> </t:touchlist> plugin - any number of plugin sections. One for each touch. iparam - Parameters that should be autoset when running the touch ivparam - Parameters that should be autoset based on parent plugins vars oparam - Parameter map of touch output to host plugin OUTPUT ------ Python list of dictionaries touchlist = [touch1, touch2, ..., touchN] Each touch is a dictionary composed of the plugin attributes. A parameters key has a dictionary of autoset parameters. Example: touch1 = { 'name' : 'SSLTouch', 'displayname' : 'Check for SSL', 'description' : 'Checks the target for SSL', 'parameters' : {'TargetPort' : 443} } """ try: xmlDocument = xml.dom.minidom.parse(xmlFile) tlist = get_elements(xmlDocument, "touchlist")[0] # Fix to bug #574 except expat.ExpatError: # The XML failed to parse correctly import os.path (p, f) = os.path.split(xmlFile) raise exception.PluginMetaErr("Error parsing '%s' XML. Touches not configured" % (f)) return [] except IndexError: # We didn't successfully get anything from "t:touchlist" Don't print here because some # things actually don't specify touches #return [] raise touchlist = [] for plugin in get_elements(tlist, "plugin"): # Fix for bug #574 touch = {"name" : str(plugin.getAttribute("name")), "displayname" : str(plugin.getAttribute("displayname")), "description" : str(plugin.getAttribute("description")), "postmsg" : str(plugin.getAttribute("postmessage")), "iparams" : util.iDict(), "ivparams" : util.iDict(), "oparams" : util.iDict()} for p in get_elements(plugin, "iparam"): # Fix for bug #574 #plugin.getElementsByTagName("t:iparam"): touch["iparams"][str(p.getAttribute("name"))] = str(p.getAttribute("value")) for p in get_elements(plugin, "ivparam"): # Fix for bug #574 #plugin.getElementsByTagName("t:ivparam"): touch["ivparams"][str(p.getAttribute("name"))] = str(p.getAttribute("value")) for p in get_elements(plugin, "oparam"): # Fix for bug #574 #plugin.getElementsByTagName("t:oparam"): touch["oparams"][str(p.getAttribute("name"))] = str(p.getAttribute("value")) touchlist.append(touch) return touchlist
return True def write_outparams(self): pass def parseargs(args): longopt = ['InConfig=', 'OutConfig=', 'LogFile=', 'ValidateOnly='] try: opts, args = getopt.getopt(args[1:], '', longopt) except getopt.GetoptError, err: #print str(err) return None opts = util.iDict(opts) try: inxml = opts['--inconfig'] except KeyError, err: print "Missing command argument %s" % str(err) return None try: val = opts['--validateonly'] if val.lower() == 'false': validate = False else: validate = True except KeyError, err: validate = False
def __init__(self, label, params, item): self.item = item self.label = label self.params = util.iDict() for p in params: self.set(p[0], p)
def redirect_local(self, l, plugin, session_data): """ targetip = Destination IP (on the target) targetport = Destination Port (on the target) redirip = IP of the LP redirport = Port on the LP """ # listenaddr - name of variable containing the LP IP # listenport - name of variable containing the LP Port # destaddr - name of variable containing the Target IP # destport - name of variable containing the Target Port # targetip - IP of the target # targetport - Port of the target # redirip - IP of the LP # redirport - Port of the LP params = iDict(plugin.getParameters()) # Get the defaults for the user prompt laddr = self.conv_param(l.listenaddr, params, session_data['params']) lport = self.conv_param(l.listenport, params, session_data['params']) daddr = self.conv_param(l.destaddr, params, session_data['params']) dport = self.conv_param(l.destport, params, session_data['params']) if None in (laddr, lport, daddr, dport): for p, n in (laddr, l.listenaddr), (lport, l.listenport), ( daddr, l.destaddr), (dport, l.destport): if p == None: self.io.print_warning( "Parameter %s referenced by tunnel %s not found. This tunnel will " "be ignored" % (n, l.name)) return self.io.print_success("Local Tunnel - %s" % l.name) # # Get the destination IP and port for the target # targetip = self.prompt_redir_fake('Destination IP', daddr) targetport = self.prompt_redir_fake('Destination Port', dport) # # Get the redirection addresses # redirip = self.prompt_redir(plugin, l.listenaddr, 'Listen IP', '127.0.0.1') if not dport: dport = targetport redirport = self.prompt_redir(plugin, l.listenport, 'Listen Port', lport) # # # session_data['params'][l.listenaddr] = targetip session_data['params'][l.listenport] = targetport # # Record the redirection tunnel # session_data['local'].append( LocalRedirection(l.protocol, redirip, redirport, targetip, targetport, name=l.name)) self.io.print_success( "(%s) Local %s:%s -> %s:%s" % (l.protocol, redirip, redirport, targetip, targetport))
def redirect_remote(self, r, plugin, session_data): """(destaddr, destport) = r-xform(listenaddr, listenport) * Each of the identifiers above specifies a variable for the plug-in (1) Prompt for Listen IP - Likely the ultimate redirector's IP (2) Prompt for Listen Port - Likely the ultimate redirector's port (3) Prompt for Destination - Likely 0.0.0.0 (4) Prompt for Destination Port - Likely a local port Lookup the variables specified by listenaddr and listenport, transform them with a given transform function, and substitute the resulting values into the variables specified by destaddr and destport. The plug-in will then have to open a port to listen on using the variables specified by the destnation IP and destination port """ params = iDict(plugin.getParameters()) lport = self.conv_param(r.listenport, params, session_data['params']) dport = self.conv_param(r.destport, params, session_data['params']) laddr = self.conv_param(r.listenaddr, params, session_data['params']) daddr = self.conv_param(r.destaddr, params, session_data['params']) if None in (lport, dport, laddr, daddr): for p, n in (laddr, r.listenaddr), (lport, r.listenport), ( daddr, r.destaddr), (dport, r.destport): if p == None: self.io.print_warning( "Parameter %s referenced by tunnel %s not found. This tunnel will " "be ignored" % (n, r.name)) return if not lport or lport == "0": lport = rand_port() self.io.print_success("Remote Tunnel - %s" % r.name) # # Prompt the user for the listenaddr and listenport # callbackip = self.prompt_redir(plugin, r.listenaddr, 'Listen IP', laddr) callbackport = self.prompt_redir(plugin, r.listenport, 'Listen Port', lport) # # Do the substitution # session_data['params'][r.listenaddr] = callbackip session_data['params'][r.listenport] = callbackport # Get the other end of the tunnel, where the connection will eventually be made. # This will likely be, but does not have to be, the local workstation callbacklocalip = self.prompt_redir_fake('Destination IP', daddr) if not dport: dport = callbackport callbacklocalport = self.prompt_redir(plugin, r.destport, 'Destination Port', dport) session_data['params'][r.destport] = callbacklocalport session_data['remote'].append( RemoteRedirection(r.protocol, callbackip, callbacklocalport, listenport=callbackport, destaddr=callbacklocalip, name=r.name)) self.io.print_success("(%s) Remote %s:%s -> %s:%s" % (r.protocol, callbackip, callbackport, callbacklocalip, callbacklocalport))