def view(self): """ Iterate through all usernames/passwords """ table = [] Row = namedtuple('Row', ['Username', 'Password', 'Destination']) for key in self.passwords.keys(): for account in self.passwords[key]: table.append(Row(account[0], account[1], account[2])) pptable(table) super(password_sniffer, self).view()
def view(self): """ Iterate through all usernames/passwords """ table = [] Row = namedtuple('Row', ['Username', 'Password', 'Destination']) for key in self.passwords.keys(): for account in self.passwords[key]: table.append(Row(account[0],account[1],account[2])) pptable(table) super(password_sniffer,self).view()
def view(self): """ Overload view so we can print out sessions in a pretty table. """ if self.verb is 3: Setting = namedtuple('Setting', ['Host', 'SessionID']) table = [] for i in self.sessions.keys(): data = Setting(str(i).strip(), str(self.sessions[i]).strip()) table.append(data) pptable(table) else: super(http_sniffer,self).view()
def view(self): """ Overload view so we can print out sessions in a pretty table. """ if self.config['verb'].value is 4: Setting = namedtuple('Setting', ['Host', 'SessionID']) table = [] for i in self.sessions.keys(): data = Setting(str(i).strip(), str(self.sessions[i]).strip()) table.append(data) pptable(table) else: super(http_sniffer, self).view()
def parse_postgres(self, raw): """Parse PostgreSQL packet. psql is less insane.""" raw = util.get_layer_bytes(str(raw)) if len(raw) <= 1: return message_type = raw[0] if message_type == '70': # password message plen = parser_postgres.endian_int(raw[1:5]) password = '' for i in xrange(plen - 5): password += raw[5 + i].decode('hex') self.log_msg('Password hash: %s' % password) elif message_type == '51': # simple query query = parser_postgres.parse_query(raw) self.log_msg('Query: %s' % query) elif message_type == '54': if self.dump_data: # query response (columns, rows) = parser_postgres.parse_response(raw) if not columns is None and not data is None: pattern = re.compile('[\W_]+') Query = namedtuple("Query", [pattern.sub('', x.name) for x in columns]) table = [] for row in rows: row = Query._make(row) table.append(row) pptable(table) elif message_type == '58': self.log_msg('User quit.\n') elif message_type == '45': self.log_msg('Error: %s' % parser_postgres.parse_error(raw)) elif message_type == '52': if not parser_postgres.database_exists(raw): self.log_msg('Invalid database.') elif message_type == '00': # startup/other if parser_postgres.is_ssl(raw): self.log_msg('SSL request!') else: startup = parser_postgres.parse_startup(raw) self.log_msg('Startup packet:') idx = 0 while idx < len(startup) - 1: self.log_msg('\t%s -> %s' % (startup[idx], startup[idx + 1])) idx += 2
def parse_postgres(self, raw): """Parse PostgreSQL packet. psql is less insane.""" raw = util.get_layer_bytes(str(raw)) if len(raw) <= 1: return message_type = raw[0] if message_type == '70': # password message plen = parser_postgres.endian_int(raw[1:5]) password = '' for i in xrange(plen - 5): password += raw[5 + i].decode('hex') self.log_msg('Password hash: %s' % password) elif message_type == '51': # simple query query = parser_postgres.parse_query(raw) self.log_msg('Query: %s' % query) elif message_type == '54': if self.dump_data: # query response (columns, rows) = parser_postgres.parse_response(raw) if not columns is None and not data is None: pattern = re.compile('[\W_]+') Query = namedtuple( "Query", [pattern.sub('', x.name) for x in columns]) table = [] for row in rows: row = Query._make(row) table.append(row) pptable(table) elif message_type == '58': self.log_msg('User quit.\n') elif message_type == '45': self.log_msg('Error: %s' % parser_postgres.parse_error(raw)) elif message_type == '52': if not parser_postgres.database_exists(raw): self.log_msg('Invalid database.') elif message_type == '00': # startup/other if parser_postgres.is_ssl(raw): self.log_msg('SSL request!') else: startup = parser_postgres.parse_startup(raw) self.log_msg('Startup packet:') idx = 0 while idx < len(startup) - 1: self.log_msg('\t%s -> %s' % (startup[idx], startup[idx + 1])) idx += 2
def display_options(options, settings): """ Given a module's options and the column headers, generate a table, print it, and return the completed table. """ table = [] for (idx, opt) in enumerate(options.keys()): tmp = [] tmp.append(idx + 1) tmp.append(options[opt].display) tmp.append(options[opt].getStr()) tmp.append(options[opt].type) tmp.append(options[opt].required) table.append(tmp) if len(table) > 0: config.pptable([settings] + table) else: Msg('\tModule has no options.') print color.B_YELLOW + '0' + color.B_GREEN + ') ' + color.B_WHITE + 'Back' + color.END return table
def parse_mysql(self, raw): """ Parse MySQL data; not the best way, but most minimal. """ raw = util.get_layer_bytes(str(raw)) if len(raw) <= 0: return pn = int(raw[3], 16) if len(raw) > 75 and pn is 0 and self.dbi.mysql_state is 0: # probably a server greeting self.log_msg('Protocol: %d'%int(raw[4],16)) version = '' for i in range(5,len(raw)): tmp = raw[i] if tmp == '00': break version += tmp.decode('hex') salt = '' for i in range(0, 8): salt += raw[16+i] for i in range(0, 13): salt += raw[42+i] self.log_msg('Version: MySQL %s'%version) self.log_msg('Salt: %s'%salt) self.dbi.mysql_state = 1 return elif len(raw) > 50 and pn is 1 and self.dbi.mysql_state is 1: # probably a login request usr = '' hsh_idx = 0 for i in range(36, len(raw)): tmp = raw[i] if tmp == '00': hsh_idx = i+2 break usr += tmp.decode('hex') self.dbi.mysql_usr = usr pw_hash = '' for i in range(hsh_idx,len(raw)): pw_hash += raw[i] self.dbi.mysql_hsh = pw_hash self.log_msg('User: %s'%usr) self.log_msg('Password hash: %s'%pw_hash) self.dbi.mysql_state = 2 return elif self.dbi.mysql_state is 2 and len(raw) > 10: # response to login attempt if raw[7] == '02' and raw[8] == '00': self.log_msg('Login success.') self.dbi.mysql_state = 3 elif raw[5] == '15' and raw[6] == '04': self.log_msg('Access denied for \'%s\''%self.dbi.mysql_usr) self.dbi.mysql_state = 0 return elif len(raw) is 5: # user quit if set(raw) == set(['01','00','00','00','01']): self.dbi.mysql_usr = None self.dbi.mysql_hsh = None self.dbi.mysql_state = 0 self.log_msg('User quit\n') return if int(raw[3],16) is 0 and len(raw) > 5: if int(raw[4],16) is 3: # query request query = '' for i in range(5, len(raw)): tmp = raw[i] if tmp == '00': continue if int(tmp,16) >= 20 and int(tmp,16) < 127: query += tmp.decode('hex') self.log_msg('Query: %s'%query) self.dbi.mysql_state = 4 elif int(raw[4],16) is 4: # show fields field = '' for i in range(5, len(raw)): tmp = raw[i] if tmp == '00': continue if int(tmp,16) >= 20 and int(tmp,16) < 127: field += tmp.decode('hex') self.log_msg('Fetching table fields: %s'%field) self.dbi.mysql_state = 4 elif int(raw[3],16) is 1 and len(raw) > 10: if parser_mysql.is_okay(raw): # Okay packets = ACKs return # query response response = '' # parse query response if self.dump_data: (columns, data) = parser_mysql.get_response(raw) if not columns is None and not data is None: pattern = re.compile('[\W_]+') Query = namedtuple('Query', [pattern.sub('', x.name) for x in columns]) table = [] for row in data: row = Query._make(row) table.append(row) pptable(table) self.dbi.mysql_state = 3
def handle_opts(module): """ The user has selected a module, so we should parse out all the options for this particular module, set the config, and when requested, run it. This is kinda messy, but works for now. """ # fetch generic module options and module-specific options options = module.config Setting = ["", "Option", "Value", "Type", "Required"] while True: # generate list of opts table = [] for idx, opt in enumerate(options.keys()): tmp = [] tmp.append(idx + 1) tmp.append(options[opt].display) tmp.append(options[opt].getStr()) tmp.append(options[opt].type) tmp.append(options[opt].required) table.append(tmp) if len(table) > 0: config.pptable([Setting] + table) else: Msg("\tModule has no options.") print color.B_YELLOW + "0" + color.B_GREEN + ") " + color.B_WHITE + "Back" + color.END # fetch command/option try: choice = raw_input("%s > " % (color.B_WHITE + module.which + color.END)) # first check global commands tmp = check_opts(choice) if tmp == -1: continue # check module commands if choice is "0": return False elif choice == "info": if module.info is None: Msg("Module has no information available") continue print "%s%s%s" % (color.GREEN, "-" * len(module.info.split("\n")[1].strip()), color.END), print dedent(module.info.rstrip()) print "%s%s%s" % (color.GREEN, "-" * len(module.info.split("\n")[1].strip()), color.END) elif len(choice.split(" ")) > 1: choice = choice.split(" ") try: if int(choice[0]) > len(table): continue elif int(choice[0]) is 0: return False key = options.keys()[int(choice[0]) - 1] if choice[1] == "o" and module.config[key].opts is not None: Msg("Options: %s" % module.config[key].opts) continue elif choice[1] == "o" and module.config[key].type == "list": Msg("%s" % module.config[key].value) continue # generate a temporary zoption tmp = copy(module.config[key]) tmp.value = " ".join(choice[1::]) # we've got a valid number, validate the type and set it if not tmp.validate(): Error('Wrong type assigned. Expected value of type "%s"' % options[key].type) else: module.config[key] = tmp except Exception, e: Error("%s" % e) continue elif "r" in choice.lower() or "run" in choice.lower(): # verify all required options are set for opt in options.keys(): if options[opt].required and options[opt].value is None: Error("Option '%s' is required." % opt) raise FailedCheck return True
def parse_mysql(self, raw): """ Parse MySQL data; not the best way, but most minimal. """ raw = util.get_layer_bytes(str(raw)) if len(raw) <= 0: return pn = int(raw[3], 16) if len(raw) > 75 and pn is 0 and self.dbi.mysql_state is 0: # probably a server greeting self.log_msg('Protocol: %d' % int(raw[4], 16)) version = '' for i in range(5, len(raw)): tmp = raw[i] if tmp == '00': break version += tmp.decode('hex') salt = '' for i in range(0, 8): salt += raw[16 + i] for i in range(0, 13): salt += raw[42 + i] self.log_msg('Version: MySQL %s' % version) self.log_msg('Salt: %s' % salt) self.dbi.mysql_state = 1 return elif len(raw) > 50 and pn is 1 and self.dbi.mysql_state is 1: # probably a login request usr = '' hsh_idx = 0 for i in range(36, len(raw)): tmp = raw[i] if tmp == '00': hsh_idx = i + 2 break usr += tmp.decode('hex') self.dbi.mysql_usr = usr pw_hash = '' for i in range(hsh_idx, len(raw)): pw_hash += raw[i] self.dbi.mysql_hsh = pw_hash self.log_msg('User: %s' % usr) self.log_msg('Password hash: %s' % pw_hash) self.dbi.mysql_state = 2 return elif self.dbi.mysql_state is 2 and len(raw) > 10: # response to login attempt if raw[7] == '02' and raw[8] == '00': self.log_msg('Login success.') self.dbi.mysql_state = 3 elif raw[5] == '15' and raw[6] == '04': self.log_msg('Access denied for \'%s\'' % self.dbi.mysql_usr) self.dbi.mysql_state = 0 return elif len(raw) is 5: # user quit if set(raw) == set(['01', '00', '00', '00', '01']): self.dbi.mysql_usr = None self.dbi.mysql_hsh = None self.dbi.mysql_state = 0 self.log_msg('User quit\n') return if int(raw[3], 16) is 0 and len(raw) > 5: if int(raw[4], 16) is 3: # query request query = '' for i in range(5, len(raw)): tmp = raw[i] if tmp == '00': continue if int(tmp, 16) >= 20 and int(tmp, 16) < 127: query += tmp.decode('hex') self.log_msg('Query: %s' % query) self.dbi.mysql_state = 4 elif int(raw[4], 16) is 4: # show fields field = '' for i in range(5, len(raw)): tmp = raw[i] if tmp == '00': continue if int(tmp, 16) >= 20 and int(tmp, 16) < 127: field += tmp.decode('hex') self.log_msg('Fetching table fields: %s' % field) self.dbi.mysql_state = 4 elif int(raw[3], 16) is 1 and len(raw) > 10: if parser_mysql.is_okay(raw): # Okay packets = ACKs return # query response response = '' # parse query response if self.dump_data: (columns, data) = parser_mysql.get_response(raw) if not columns is None and not data is None: pattern = re.compile('[\W_]+') Query = namedtuple( 'Query', [pattern.sub('', x.name) for x in columns]) table = [] for row in data: row = Query._make(row) table.append(row) pptable(table) self.dbi.mysql_state = 3