def smb(mpkt): try: nbt = MetaPacket.new_from_str('nbt', mpkt.data) except: return sess = sessions.lookup_session(mpkt, SMB_PORTS, SMB_NAME) if not sess: if nbt.get_field('smb.Start', '') != '\xffSMB': return # From server if mpkt.l4_src in SMB_PORTS and \ nbt.get_field('smb.Command', 0) == 0x72: mpkt.set_cfield('banner', 'SMB') # Negotiate response sess = sessions.lookup_session(mpkt, SMB_PORTS, SMB_NAME, True) session_data = SMBSession() sess.data = session_data if nbt.get_field('smbneg_resp.SecurityMode', None) == 0: session_data.auth_type = PLAIN_TEXT_AUTH session_data.status = WAITING_PLAIN_TEXT else: keylength, challenge = nbt.get_fields( 'smbneg_resp', ('EncryptionKeyLength', 'EncryptionKey')) if challenge: keylength -= 1 while keylength >= 0: session_data.challenge += struct.pack( "B", (challenge >> (8 * keylength)) & 255) keylength -= 1 session_data.status = WAITING_ENCRYPT session_data.auth_type = CHALLENGE_RESPONSE_AUTH else: session_data.status = WAITING_CHALLENGE session_data.auth_type = NTLMSSP_AUTH # From client if mpkt.l4_dst in SMB_PORTS and \ nbt.get_field('smb.Command', 0) == 0x73: blob = nbt.get_field('smbsax_req_as.SecurityBlob', '') idx = blob.find("NTLMSSP") if idx < 0: return blob = blob[idx:] if blob[8] != '\x01': return sess = sessions.lookup_session(mpkt, SMB_PORTS, SMB_NAME, True) session_data = SMBSession() session_data.status = WAITING_CHALLENGE session_data.auth_type = NTLMSSP_AUTH sess.data = session_data else: session_data = sess.data # Client packets if mpkt.l4_dst in SMB_PORTS: if session_data.auth_type == NTLMSSP_AUTH and \ session_data.status == LOGON_COMPLETED_FAILURE: session_data.status = WAITING_CHALLENGE if nbt.get_field('smb.Start', '') != '\xffSMB': return if nbt.get_field('smb.Command', 0) == 0x73: if session_data.status == WAITING_PLAIN_TEXT or \ session_data.status == WAITING_ENCRYPT: resp1, resp2, user, domain, os = \ nbt.get_fields('smbsax_req', ('ANSIPassword', 'UnicodePassword', 'Account', 'PrimaryDomain', 'NativeOS')) path = nbt.get_field('smbtcax_req.Path', '') session_data.response1 = resp1 session_data.response2 = resp2 session_data.user = user session_data.domain = domain if os: session_data.domain += ' OS: %s' % os if path: session_data.domain += ' PATH: %s' % path # Empty session if not resp1.replace('\x00', '') and \ not resp2.replace('\x00', ''): session_data.response1 = '' session_data.response2 = '' session_data.user = '' #session_data.domain = '' session_data.status = WAITING_LOGON_RESPONSE elif session_data.status == WAITING_RESPONSE: blob = nbt.get_field('smbsax_req_as.SecurityBlob', '') idx = blob.find("NTLMSSP") if idx < 0: return blob = blob[idx:] if blob[8] == '\x03': lm_len = ord(blob[12]) lm_off = ord(blob[16]) nt_len = ord(blob[20]) nt_off = ord(blob[24]) dm_len = ord(blob[28]) dm_off = ord(blob[32]) un_len = ord(blob[36]) un_off = ord(blob[40]) if nt_len != 24: session_data.status = WAITING_CHALLENGE return session_data.user = blob[un_off:un_off + un_len].replace( '\x00', '') session_data.domain = blob[dm_off:dm_off + dm_len].replace( '\x00', '') if lm_len == 24: session_data.response1 = blob[lm_off:lm_off + 24] session_data.response2 = blob[nt_off:nt_off + 24] session_data.status = WAITING_LOGON_RESPONSE else: # Server packets if nbt.get_field('smb.Command', 0) == 0x73: if session_data.status == WAITING_CHALLENGE: blob = nbt.get_field('smbsax_resp_as.SecurityBlob', '') idx = blob.find('NTLMSSP') if idx < 0: return blob = blob[idx:] if blob[8] == '\x02': session_data.challenge = blob[8 + 16:8 + 16 + 8] session_data.status = WAITING_RESPONSE elif session_data.status == WAITING_LOGON_RESPONSE: if mpkt.get_field('smb.Error_Class', 0) == 0: session_data.status = LOGON_COMPLETED_OK session_data.report(mpkt, manager) sessions.delete_session(sess) else: session_data.status = LOGON_COMPLETED_FAILURE session_data.report(mpkt, manager) if session_data.auth_type == CHALLENGE_RESPONSE_AUTH: session_data.status = WAITING_ENCRYPT
def smb(mpkt): try: nbt = MetaPacket.new_from_str('nbt', mpkt.data) except: return sess = sessions.lookup_session(mpkt, SMB_PORTS, SMB_NAME) if not sess: if nbt.get_field('smb.Start', '') != '\xffSMB': return # From server if mpkt.l4_src in SMB_PORTS and \ nbt.get_field('smb.Command', 0) == 0x72: mpkt.set_cfield('banner', 'SMB') # Negotiate response sess = sessions.lookup_session(mpkt, SMB_PORTS, SMB_NAME, True) session_data = SMBSession() sess.data = session_data if nbt.get_field('smbneg_resp.SecurityMode', None) == 0: session_data.auth_type = PLAIN_TEXT_AUTH session_data.status = WAITING_PLAIN_TEXT else: keylength, challenge = nbt.get_fields( 'smbneg_resp', ('EncryptionKeyLength', 'EncryptionKey') ) if challenge: keylength -= 1 while keylength >= 0: session_data.challenge += struct.pack("B", (challenge >> (8 * keylength)) & 255 ) keylength -= 1 session_data.status = WAITING_ENCRYPT session_data.auth_type = CHALLENGE_RESPONSE_AUTH else: session_data.status = WAITING_CHALLENGE session_data.auth_type = NTLMSSP_AUTH # From client if mpkt.l4_dst in SMB_PORTS and \ nbt.get_field('smb.Command', 0) == 0x73: blob = nbt.get_field('smbsax_req_as.SecurityBlob', '') idx = blob.find("NTLMSSP") if idx < 0: return blob = blob[idx:] if blob[8] != '\x01': return sess = sessions.lookup_session(mpkt, SMB_PORTS, SMB_NAME, True) session_data = SMBSession() session_data.status = WAITING_CHALLENGE session_data.auth_type = NTLMSSP_AUTH sess.data = session_data else: session_data = sess.data # Client packets if mpkt.l4_dst in SMB_PORTS: if session_data.auth_type == NTLMSSP_AUTH and \ session_data.status == LOGON_COMPLETED_FAILURE: session_data.status = WAITING_CHALLENGE if nbt.get_field('smb.Start', '') != '\xffSMB': return if nbt.get_field('smb.Command', 0) == 0x73: if session_data.status == WAITING_PLAIN_TEXT or \ session_data.status == WAITING_ENCRYPT: resp1, resp2, user, domain, os = \ nbt.get_fields('smbsax_req', ('ANSIPassword', 'UnicodePassword', 'Account', 'PrimaryDomain', 'NativeOS')) path = nbt.get_field('smbtcax_req.Path', '') session_data.response1 = resp1 session_data.response2 = resp2 session_data.user = user session_data.domain = domain if os: session_data.domain += ' OS: %s' % os if path: session_data.domain += ' PATH: %s' % path # Empty session if not resp1.replace('\x00', '') and \ not resp2.replace('\x00', ''): session_data.response1 = '' session_data.response2 = '' session_data.user = '' #session_data.domain = '' session_data.status = WAITING_LOGON_RESPONSE elif session_data.status == WAITING_RESPONSE: blob = nbt.get_field('smbsax_req_as.SecurityBlob', '') idx = blob.find("NTLMSSP") if idx < 0: return blob = blob[idx:] if blob[8] == '\x03': lm_len = ord(blob[12]) lm_off = ord(blob[16]) nt_len = ord(blob[20]) nt_off = ord(blob[24]) dm_len = ord(blob[28]) dm_off = ord(blob[32]) un_len = ord(blob[36]) un_off = ord(blob[40]) if nt_len != 24: session_data.status = WAITING_CHALLENGE return session_data.user = blob[un_off:un_off + un_len].replace('\x00', '') session_data.domain = blob[dm_off:dm_off + dm_len].replace('\x00', '') if lm_len == 24: session_data.response1 = blob[lm_off:lm_off + 24] session_data.response2 = blob[nt_off:nt_off + 24] session_data.status = WAITING_LOGON_RESPONSE else: # Server packets if nbt.get_field('smb.Command', 0) == 0x73: if session_data.status == WAITING_CHALLENGE: blob = nbt.get_field('smbsax_resp_as.SecurityBlob', '') idx = blob.find('NTLMSSP') if idx < 0: return blob = blob[idx:] if blob[8] == '\x02': session_data.challenge = blob[8 + 16:8 + 16 + 8] session_data.status = WAITING_RESPONSE elif session_data.status == WAITING_LOGON_RESPONSE: if mpkt.get_field('smb.Error_Class', 0) == 0: session_data.status = LOGON_COMPLETED_OK session_data.report(mpkt, manager) sessions.delete_session(sess) else: session_data.status = LOGON_COMPLETED_FAILURE session_data.report(mpkt, manager) if session_data.auth_type == CHALLENGE_RESPONSE_AUTH: session_data.status = WAITING_ENCRYPT
class SnoopTab(UmitView): icon_name = gtk.STOCK_INFO tab_position = gtk.POS_LEFT label_text = _('DNS Cache snoop') name = 'DNSCacheSnoop' def create_ui(self): self.active = False self.output = [] self.toolbar = gtk.Toolbar() self.toolbar.set_style(gtk.TOOLBAR_ICONS) self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL) for name, stock, cb in (('Copy', gtk.STOCK_COPY, self.__on_copy), ('Open', gtk.STOCK_OPEN, self.__on_open), ('Execute', gtk.STOCK_EXECUTE, self.__on_execute)): act = gtk.Action(name, name, '', stock) act.connect('activate', cb) self.toolbar.insert(act.create_tool_item(), -1) self._main_widget.pack_start(self.toolbar, False, False) self.server = gtk.Entry() self._main_widget.pack_start(self.server, False, False) self.store = gtk.ListStore(bool, str, int) self.tree = gtk.TreeView(self.store) self.tree.append_column( gtk.TreeViewColumn('', gtk.CellRendererToggle(), active=0)) rend = gtk.CellRendererText() rend.connect('edited', self.__edited_cb) rend.set_property('editable', True) col = gtk.TreeViewColumn('Host', rend, text=1) col.set_expand(True) self.tree.append_column(col) self.tree.append_column( gtk.TreeViewColumn('TTL', gtk.CellRendererText(), text=2)) self.tree.set_rules_hint(True) self.selection = self.tree.get_selection() self.menu = gtk.Menu() for name, stock, cb in (('Add', gtk.STOCK_ADD, self.__on_add), ('Remove', gtk.STOCK_REMOVE, self.__on_remove)): act = gtk.Action(name, name, '', stock) act.connect('activate', cb) self.menu.append(act.create_menu_item()) self.tree.connect('button-press-event', self.__on_button) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) sw.add(self.tree) self._main_widget.pack_start(sw) self._main_widget.show_all() def __edited_cb(self, rend, path, new_text): iter = self.store.get_iter_from_string(path) self.store.set_value(iter, 1, new_text) def __on_button(self, tree, evt): if evt.button != 3: return False self.menu.show_all() self.menu.popup(None, None, None, evt.button, evt.time) return True def __on_add(self, widget): model, iter = self.selection.get_selected() newrow = (False, 'edit me', 0) if not iter: self.store.append(newrow) else: self.store.insert_after(None, iter, newrow) def __on_remove(self, widget): model, iter = self.selection.get_selected() if iter: self.store.remove(iter) def __on_copy(self, act): out = '' for row in self.store: out += "[%s] %s (%d)\n" % (row[0] and '+' or '-', row[1], row[2]) if out: clip = gtk.clipboard_get() clip.set_text('Result for %s DNS server\n' % self.server.get_text() + out) def __on_execute(self, act): if self.active: return self.active = True self.thread = None self.tree.set_sensitive(False) self.server.set_sensitive(False) self.toolbar.set_sensitive(False) server = self.server.get_text() targets = [row[1] for row in self.store] self.thread = Thread(target=self.__main_thread, name='DNSCacheSnoop', kwargs={ 'targets': targets, 'server': server }) self.thread.setDaemon(True) self.thread.start() gobject.timeout_add(1000, self.__check_finished) def __check_finished(self): if self.thread is not None: return True log.debug(str(self.output)) idx = 0 while idx < len(self.output): present, ttl = self.output[idx] iter = self.store.get_iter((idx, )) if iter: self.store.set(iter, 0, present, 2, ttl) idx += 1 self.output = [] self.tree.set_sensitive(True) self.server.set_sensitive(True) self.toolbar.set_sensitive(True) self.active = False return False def __on_open(self, act): dialog = gtk.FileChooserDialog(_('Select a query file'), PMApp().main_window, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT, gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) if dialog.run() == gtk.RESPONSE_ACCEPT: fname = dialog.get_filename() if fname: fd = open(fname, 'r') contents = fd.read() fd.close() self.store.clear() for line in contents.splitlines(): line = line.strip() if line: self.store.append((False, line, 0)) dialog.hide() dialog.destroy() def __main_thread(self, server, targets): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(5) if ':' in server: server, port = server.split(':', 1) else: port = 53 try: port = int(port) except: port = 53 sock.connect((server, port)) for target in targets: dnsqr = MetaPacket.new('dnsqr') dnsqr.set_field('dnsqr.qname', target) mpkt = MetaPacket.new('dns') mpkt.set_fields('dns', {'id': randint(0, 2L**16 - 1), 'qd': dnsqr}) sock.send(mpkt.get_raw()) try: buff = sock.recv(1024) mpkt = MetaPacket.new_from_str('dns', buff) if mpkt.get_field('dns.ancount', 0) == 0: self.output.append((False, 0)) else: found = False qd = mpkt.get_field('dns.an', None) while qd is not None: rrname = qd.get_field('dnsrr.rrname', '') if rrname.startswith(target): self.output.append((True, \ qd.get_field('dnsrr.ttl', 0))) log.debug('Reply for %s' % target) found = True break qd = mpkt.get_field('dnsrr.payload', None) if not found: self.output.append((False, 0)) log.debug('No reply for %s' % target) except Exception, exc: log.debug('Cannot parse DNS reply for %s ' \ 'or timeout occurred' % target) log.error(generate_traceback()) self.output.append((False, 0))