Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
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))