Example #1
0
    def stop(self):
        manager = AuditManager()
        manager.remove_decoder(NET_LAYER, LL_TYPE_IP, self.ip_decoder)
        manager.remove_injector(0, LL_TYPE_IP, ip_injector)
        manager.remove_injector(0, STATELESS_IP_MAGIC, stateless_ip_injector)

        self.decoder = None
Example #2
0
def udp_decoder():
    manager = AuditManager()

    conf = manager.get_configuration(UDP_NAME)
    checksum_check = conf['checksum_check']

    def udp(mpkt):
        mpkt.l4_len = UDP_LENGTH
        mpkt.l4_src, \
        mpkt.l4_dst = mpkt.get_fields('udp', ('sport', 'dport'))

        load = mpkt.get_field('udp')[mpkt.l4_len:]

        if load:
            mpkt.data = load

        if checksum_check:
            udpraw = mpkt.get_field('udp')

            if udpraw:
                if mpkt.payload_len == len(udpraw):
                    psdhdr = pack("!4s4sHH",
                                  inet_aton(mpkt.l3_src),
                                  inet_aton(mpkt.l3_dst),
                                  mpkt.l4_proto,
                                  mpkt.payload_len)

                    chksum = checksum(psdhdr + udpraw[:6] + \
                                      '\x00\x00' + udpraw[8:])

                    if mpkt.get_field('udp.chksum') != chksum:
                        mpkt.set_cfield('good_checksum', hex(chksum))
                        manager.user_msg(
                            _("Invalid UDP packet from %s to %s : " \
                              "wrong checksum %s instead of %s") %  \
                            (mpkt.l3_src, mpkt.l3_dst,              \
                             hex(mpkt.get_field('udp.chksum', 0)),  \
                             hex(chksum)),                          \
                            5, UDP_NAME)

        manager.run_decoder(APP_LAYER, PL_DEFAULT, mpkt)

        if mpkt.flags & MPKT_MODIFIED and \
           mpkt.flags & MPKT_FORWARDABLE:

            mpkt.set_field('udp.chksum', None)

        return None

    return udp
Example #3
0
    def register_decoders(self):
        self.manager = AuditManager()
        conf = self.manager.get_configuration('decoder.tcp')

        self.checksum_check = conf['checksum_check']

        self.manager.add_decoder(PROTO_LAYER, NL_TYPE_TCP, self._process_tcp)
        self.manager.add_injector(1, NL_TYPE_TCP, self._inject_tcp)

        if conf['enable_reassemble']:
            self.reassembler = Reassembler(conf['reassemble_workarounds'],
                                           conf['reassemble_maxstreams'])
            self.manager.add_decoder_hook(PROTO_LAYER, NL_TYPE_ICMP,
                                          self.reassembler.process_icmp, 1)
Example #4
0
def udp_decoder():
    manager = AuditManager()

    conf = manager.get_configuration(UDP_NAME)
    checksum_check = conf['checksum_check']

    def udp(mpkt):
        mpkt.l4_len = UDP_LENGTH
        mpkt.l4_src, \
        mpkt.l4_dst = mpkt.get_fields('udp', ('sport', 'dport'))

        load = mpkt.get_field('udp')[mpkt.l4_len:]

        if load:
            mpkt.data = load

        if checksum_check:
            udpraw = mpkt.get_field('udp')

            if udpraw:
                if mpkt.payload_len == len(udpraw):
                    psdhdr = pack("!4s4sHH", inet_aton(mpkt.l3_src),
                                  inet_aton(mpkt.l3_dst), mpkt.l4_proto,
                                  mpkt.payload_len)

                    chksum = checksum(psdhdr + udpraw[:6] + \
                                      '\x00\x00' + udpraw[8:])

                    if mpkt.get_field('udp.chksum') != chksum:
                        mpkt.set_cfield('good_checksum', hex(chksum))
                        manager.user_msg(
                            _("Invalid UDP packet from %s to %s : " \
                              "wrong checksum %s instead of %s") %  \
                            (mpkt.l3_src, mpkt.l3_dst,              \
                             hex(mpkt.get_field('udp.chksum', 0)),  \
                             hex(chksum)),                          \
                            5, UDP_NAME)

        manager.run_decoder(APP_LAYER, PL_DEFAULT, mpkt)

        if mpkt.flags & MPKT_MODIFIED and \
           mpkt.flags & MPKT_FORWARDABLE:

            mpkt.set_field('udp.chksum', None)

        return None

    return udp
Example #5
0
    def scan_path(self):
        """
        Walk the path passed in the constructor for .ump files,
        then save the found plugins on a dict that could be accesed with
        get_plugins()

        No recursive scan, only top-level directory is considerated.
        """

        if self.scanned or not os.path.exists(self.path):
            return

        for file in os.listdir(self.path):
            path = os.path.join(self.path, file)

            if file.endswith(".ump") and \
               os.path.isfile(path):

                try:
                    reader = PluginReader(path)

                    for conf_name, conf_dict in reader.configurations:
                        AuditManager().register_configuration(conf_name,
                                                               conf_dict)
                except BadPlugin, exp:
                    log.info("%s" % exp)
                    continue

                self._plugins[file] = reader
Example #6
0
    def stop(self):
        manager = AuditManager()
        manager.remove_decoder(PROTO_LAYER, NL_TYPE_TCP, self._process_tcp)
        manager.remove_injector(1, NL_TYPE_TCP, self._inject_tcp)

        try:
            manager.remove_decoder_hook(PROTO_LAYER, NL_TYPE_ICMP,
                                             self.reassembler.process_icmp, 1)
        except:
            pass
Example #7
0
    def stop(self):
        manager = AuditManager()
        manager.remove_decoder(NET_LAYER, LL_TYPE_IP, self.ip_decoder)
        manager.remove_injector(0, LL_TYPE_IP, ip_injector)
        manager.remove_injector(0, STATELESS_IP_MAGIC, stateless_ip_injector)

        self.decoder = None
Example #8
0
    def __on_bool_toggled(self, widget, udata):
        conf_name, opt_id = udata

        if widget.get_active():
            widget.get_child().set_text(_('Enabled'))
        else:
            widget.get_child().set_text(_('Disabled'))

        AuditManager().get_configuration(conf_name)[opt_id] = \
                     widget.get_active()
Example #9
0
def stateless_ip_injector(context, mpkt, length):
    ident = IPIdent.create(mpkt)
    sess = SessionManager().get_session(ident)

    if not sess:
        return False, length

    mpkt.session = sess

    injector = AuditManager().get_injector(0, LL_TYPE_IP)
    return injector(context, mpkt, length)
Example #10
0
    def stop(self):
        obj = self.fingerprint
        self.fingerprint = None

        log.debug('Destroying OSFP object %s' % obj)
        del obj

        try:
            AuditManager().remove_decoder_hook(PROTO_LAYER, NL_TYPE_TCP,
                                               self._tcp_hook, 1)
        except:
            pass
Example #11
0
def icmp_decoder():
    manager = AuditManager()

    conf = manager.get_configuration('decoder.icmp')
    checksum_check = conf['checksum_check']

    def icmp(mpkt):
        if not checksum_check:
            return None

        if mpkt.get_field('ip.flags', 0) & 1:
            # Only a fragment
            return None

        payload = mpkt.cfields.get('reassembled_payload', None)

        if not payload:
            payload = mpkt.get_field('icmp')

            if not payload:
                return None

        cur_chksum = hex(unpack("!H", payload[2:4])[0])
        icmpraw = payload[0:2] + '\x00\x00' + payload[4:]
        com_chksum = hex(checksum(icmpraw))

        if com_chksum != cur_chksum:
            mpkt.set_cfield('good_checksum', com_chksum)
            manager.user_msg(_("Invalid ICMP packet from %s to %s : " \
                               "wrong checksum %s instead of %s") %  \
                             (mpkt.get_field('ip.src'),          \
                              mpkt.get_field('ip.dst'),          \
                              cur_chksum, com_chksum),
                             5, 'decoder.icmp')

        return None

    return icmp
Example #12
0
def icmp_decoder():
    manager = AuditManager()

    conf = manager.get_configuration('decoder.icmp')
    checksum_check = conf['checksum_check']

    def icmp(mpkt):
        if not checksum_check:
            return None

        if mpkt.get_field('ip.flags', 0) & 1:
            # Only a fragment
            return None

        payload = mpkt.cfields.get('reassembled_payload', None)

        if not payload:
            payload = mpkt.get_field('icmp')

            if not payload:
                return None

        cur_chksum = hex(unpack("!H", payload[2:4])[0])
        icmpraw = payload[0:2] + '\x00\x00' + payload[4:]
        com_chksum = hex(checksum(icmpraw))

        if com_chksum != cur_chksum:
            mpkt.set_cfield('good_checksum', com_chksum)
            manager.user_msg(_("Invalid ICMP packet from %s to %s : " \
                               "wrong checksum %s instead of %s") %  \
                             (mpkt.get_field('ip.src'),          \
                              mpkt.get_field('ip.dst'),          \
                              cur_chksum, com_chksum),
                             5, 'decoder.icmp')

        return None

    return icmp
Example #13
0
    def __on_query_tooltip(self, widget, x, y, ktip, tooltip):
        if not widget.get_tooltip_context(x, y, ktip):
            return False

        model, path, iter = widget.get_tooltip_context(x, y, ktip)

        value = model.get_value(iter, 2)[1:-1]

        try:
            desc = AuditManager().get_configuration('global.cfields') \
                 .get_description(value)

            tooltip.set_markup('<b>%s:</b> %s' % (value, desc))
            widget.set_tooltip_row(tooltip, path)

            return True
        except:
            return False
Example #14
0
def udp_injector(context, mpkt, length):
    mpkt.set_fields('udp', {
        'sport': mpkt.l4_src,
        'dport': mpkt.l4_dst,
        'chksum': None
    })

    length += UDP_LENGTH
    mpkt.session = None

    injector = AuditManager().get_injector(0, STATELESS_IP_MAGIC)
    is_ok, length = injector(context, mpkt, length)

    length = context.get_mtu() - length

    if length > mpkt.inject_len:
        length = mpkt.inject_len

    payload = mpkt.inject[:length]
    payload_pkt = MetaPacket.new('raw')
    payload_pkt.set_field('raw.load', payload)
    mpkt.add_to('udp', payload_pkt)

    return True, length
Example #15
0
 def register_hooks(self):
     AuditManager().add_decoder_hook(PROTO_LAYER, NL_TYPE_TCP,
                                     self._tcp_hook, 1)
Example #16
0
 def register_decoders(self):
     AuditManager().add_decoder(PROTO_LAYER, NL_TYPE_ICMP, icmp_decoder())
Example #17
0
 def stop(self):
     AuditManager().remove_decoder(PROTO_LAYER, NL_TYPE_ICMP,
                                   icmp_decoder())
Example #18
0
def ip_decoder():
    manager = AuditManager()

    conf = manager.get_configuration('decoder.ip')
    checksum_check, reassemble, max_len, max_frags = \
        conf['checksum_check'], conf['reassemble'], \
        conf['reassemble_max_fraglist'], conf['reassemble_max_fragments']

    reas_dict = {}

    def ip_reassemble(mpkt):
        # Here we have to check for fragmentation
        # by creating a dict to holds id of ip packets
        # and set mpkt.lock() on it if mpkg is MF
        # until the resegmentation is done.
        # If it's a fragment we have to return None
        # to break the chain.

        # TODO: check ip.flags standard name in UMPA
        ts = time.time()
        mf = mpkt.get_field('ip.flags', 0) & 1
        frag_off = mpkt.get_field('ip.frag', 0) * 8

        if not mf and frag_off == 0:
            return False

        ipid = mpkt.get_field('ip.id')

        if ipid in reas_dict:
            plist = reas_dict[ipid]

            if len(plist) >= max_frags:
                del reas_dict[ipid]
                manager.user_msg(_('Dropping out the sequence with ID: '
                                   '%s due reassemble_max_fragments') %
                                 ipid, 7, 'decoder.ip')

                return False

            ret = 0
            idx = 0
            inserted = False

            while idx < len(plist):
                ts2, frag_off2, mpkt2 = plist[idx]

                if frag_off2 == frag_off:
                    plist[idx] = (ts, frag_off, mpkt.copy())
                    break
                elif frag_off2 < frag_off:
                    ret += frag_off2
                    idx += 1
                    continue

                inserted = True
                plist.insert(idx, (ts, frag_off, mpkt.copy()))
                break

            if not inserted:
                plist.append((ts, frag_off, mpkt.copy()))

            # Now let's get the last packet and see if MF = 0
            # EVASION!
            if plist[-1][-1].get_field('ip.flags') & 1 == 0:

                if idx == len(plist) -1:
                    ret = frag_off - ret
                else:
                    while idx < len(plist) - 1:
                        ts2, frag_off2, mpkt2 = plist[idx]
                        ret += frag_off2
                        idx += 1

                        ret = plist[-1][1] - ret

                if ret == 0:
                    log.debug('Reassembling sequence with ID: %s' % \
                              ipid)

                    reas_payload = ''

                    for ts2, frag_off2, mpkt2 in plist:
                        try:
                            ihl = mpkt2.l3_len
                            reas_payload += mpkt2.get_field('ip')[ihl:]
                        except:
                            pass

                    # Ok check that we have a complete payload
                    ihl = mpkt.l3_len
                    p_len = frag_off + mpkt.get_field('ip.len') - ihl

                    if len(reas_payload) != p_len:
                        mpkt.set_cfield('reassembled_payload', None)
                        manager.user_msg(_('Reassemble of IP packet ' \
                                           'from %s to %s failed') %  \
                                         (mpkt.l3_src, mpkt.l3_dst),  \
                                         4, 'decoder.ip')

                    # Nice drop out everythin!
                    del reas_dict[ipid]

                    mpkt.set_cfield('reassembled_payload', reas_payload)
                    return True
        else:
            if len(reas_dict) >= max_len:
                # Ok just drop the list with the minor ts (the oldest)
                min_k = min([(v, k) for k, v in reas_dict.items()])[1]
                del reas_dict[min_k]

                # Debug
                manager.user_msg(_('Dropping out the oldest sequence '
                                   'with ID: %s') % min_k,
                                 7, 'decoder.ip')

            log.debug('First packet of the sequence with ID: %s' % ipid)
            reas_dict[ipid] = [(ts, frag_off, mpkt)]

        return False

    def ip(mpkt):
        mpkt.l3_src, \
        mpkt.l3_dst, \
        mpkt.l4_proto = mpkt.get_fields('ip', ('src', 'dst', 'proto'))

        # TODO: handle IPv6

        ipraw = mpkt.get_field('ip')

        if not ipraw:
            return

        mpkt.l3_len = mpkt.get_field('ip.ihl') * 4
        mpkt.payload_len = mpkt.get_field('ip.len') - mpkt.l3_len

        if mpkt.context:
            mpkt.context.check_forwarded(mpkt)

            if mpkt.flags & MPKT_FORWARDED:
                return None

            mpkt.context.set_forwardable(mpkt)

        iplen = min(20, len(ipraw))

        if mpkt.get_field('ip.len') > len(ipraw):
            # Probably we are capturing with low snaplen
            # so the packets are not fully captured. Avoid
            # further calculation.
            return PROTO_LAYER, mpkt.l4_proto

        if checksum_check:
            ihl = max(20, mpkt.l3_len)
            pkt = ipraw[:10] + '\x00\x00' + ipraw[12:ihl]

            chksum = checksum(pkt)

            # Probably here it's better to set also a cfield
            # and to turn False the checksum_check default value
            if mpkt.get_field('ip.chksum') != chksum:
                mpkt.set_cfield('good_checksum', hex(chksum))
                manager.user_msg(_("Invalid IP packet from %s to %s : " \
                                   "wrong checksum %s instead of %s") %  \
                                 (mpkt.l3_src, mpkt.l3_dst,          \
                                  hex(mpkt.get_field('ip.chksum')),  \
                                  hex(chksum)),
                                 5, 'decoder.ip')

            elif reassemble:
                ip_reassemble(mpkt)

        ident = IPIdent.create(mpkt)
        sess = SessionManager().get_session(ident)

        if not sess:
            sess = Session(ident)
            sess.data = IPStatus()
            SessionManager().put_session(sess)

        sess.prev = mpkt.session
        mpkt.session = sess

        status = sess.data
        status.last_id = mpkt.get_field('ip.id', 0)

        manager.run_decoder(PROTO_LAYER, mpkt.l4_proto, mpkt)

        if mpkt.flags & MPKT_DROPPED:
            status.id_adj -= 1
        elif mpkt.flags & MPKT_MODIFIED or status.id_adj != 0:
            mpkt.set_field('ip.id', mpkt.get_field('ip.id', 0) + status.id_adj)
            mpkt.set_field('ip.len', mpkt.get_field('ip.len', 0) + mpkt.inj_delta)
            mpkt.set_field('ip.chksum', None)

    return ip
class MainWindow(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self)

        self.set_title("Packet Manipulator - " + str(PM_VERSION))
        self.set_icon_list(
            gtk.gdk.pixbuf_new_from_file(
                os.path.join(PIXMAPS_DIR, 'pm-logo.png')))
        self.set_default_size(600, 400)

        self.registered_tabs = {}

        # Binders for plugins
        self.perspective_binder = []
        self.session_binder = []

        for i in PerspectiveType.types:
            self.perspective_binder.append(list())

        for i in SessionType.types:
            self.session_binder.append(list())

        self.perspective_binder = tuple(self.perspective_binder)
        self.session_binder = tuple(self.session_binder)

        self.__create_widgets()
        self.__pack_widgets()
        self.__connect_signals()

        self.statusbar.push(_("Ready."), image=gtk.STOCK_YES)

        self.show_all()

    def __create_widgets(self):
        "Create widgets"

        self.main_actions = [
            ('File', None, _('File'), None),
            ('NewAudit', gtk.STOCK_NEW, _('New A_udit'), '<Control>t',
             _('Create a new audit'), self.__on_new_audit),
            ('NewSequence', gtk.STOCK_NEW, _('_New sequence'), '<Control>n',
             _('Create a new sequence'), self.__on_new_sequence),
            ('Open', gtk.STOCK_OPEN, _('_Open'), '<Control>o',
             _('Open session'), self.__on_open_session),
            ('Save', gtk.STOCK_SAVE, _('_Save'), '<Control>s',
             _('Save session'), self.__on_save_session),
            ('SaveAs', gtk.STOCK_SAVE_AS, _('_Save as'), '<Control><Shift>s',
             _('Save session as'), self.__on_save_session_as),
            ('Quit', gtk.STOCK_QUIT, _('_Quit'), '<Control>q',
             _('Quit from application'), self.__on_quit),
            ('Capture', None, _('Capture'), None),
            ('Interface', gtk.STOCK_CONNECT, _('_Interface'), '<Control>i',
             _('Capture from interface'), self.__on_select_iface),
            ('Audits', None, _('Audits'), None),
            ('Mitm', None, _('MITM'), None),
            ('Options', None, _('Options'), None),
            ('Routes', gtk.STOCK_NETWORK, _('Routing table'), '<Control>r',
             _('Routes editor'), self.__on_routing),
            ('Plugins', 'extension_small', _('Plugins'), None,
             _('Plugin manager'), self.__on_plugins),
            ('Preferences', gtk.STOCK_PREFERENCES, _('_Preferences'),
             '<Control>p', _('Preferences'), self.__on_preferences),
            ('Views', None, _('Views'), None),
            ('Help', None, _('Help'), None),
            ('About', gtk.STOCK_ABOUT, _('About'), None, None,
             self.__on_about),
        ]

        self.default_ui = """<menubar>
            <menu action='File'>
                <menuitem action='NewSequence'/>
                <menuitem action='NewAudit'/>
                <separator/>
                <menuitem action='Open'/>
                <menuitem action='Save'/>
                <menuitem action='SaveAs'/>
                <separator/>
                <menuitem action='Quit'/>
            </menu>
            <menu action='Capture'>
                <menuitem action='Interface'/>
            </menu>
            <menu action='Audits'/>
            <menu action='Mitm'/>
            <menu action='Options'>
                <menuitem action='Routes'/>
                <separator/>
                <menuitem action='Plugins'/>
                <separator/>
                <menuitem action='Preferences'/>
            </menu>
            <menu action='Views'/>
            <menu action='Help'>
                <menuitem action='About'/>
            </menu>
            </menubar>

            <toolbar>
                <toolitem action='NewSequence'/>
                <toolitem action='NewAudit'/>
                <separator/>
                <toolitem action='Open'/>
                <toolitem action='Save'/>
                <separator/>
                <toolitem action='Interface'/>
                <toolitem action='Routes'/>
                <separator/>
                <toolitem action='Plugins'/>
                <toolitem action='Preferences'/>
                <separator/>
            </toolbar>
            """

        self.ui_manager = gtk.UIManager()

        self.main_accel_group = gtk.AccelGroup()
        self.main_action_group = gtk.ActionGroup('MainActionGroup')
        self.main_action_group.add_actions(self.main_actions)

        self.add_accel_group(self.main_accel_group)

        for action in self.main_action_group.list_actions():
            action.set_accel_group(self.main_accel_group)
            action.connect_accelerator()

        self.ui_manager.insert_action_group(self.main_action_group, 0)
        self.ui_manager.add_ui_from_string(self.default_ui)

        self.ui_manager.connect('connect-proxy', self.__on_connect_proxy)
        self.ui_manager.connect('disconnect-proxy', self.__on_disconnect_proxy)

        # Set unsensitive the audit menu and also Mitm
        item = self.ui_manager.get_widget('/menubar/Audits')
        item.set_sensitive(False)

        item = self.ui_manager.get_widget('/menubar/Mitm')
        item.set_sensitive(False)

        # Central widgets
        self.main_paned = UmitPaned()

        self.vbox = gtk.VBox(False, 2)
        self.statusbar = StatusBar()

        self.plugin_window = PluginWindow()

    def register_audit_item(self, name, lbl, tooltip, stock, callback):
        return self.__register_audit_item('/menubar/Audits', name, lbl,
                                          tooltip, stock, callback)

    def register_audit_mitm_item(self, name, lbl, tooltip, stock, callback):
        return self.__register_audit_item('/menubar/Mitm', name, lbl, tooltip,
                                          stock, callback)

    def __register_audit_item(self, mname, name, lbl, tooltip, stock, cb):
        audititem = self.ui_manager.get_widget(mname)
        menu = audititem.get_submenu()

        audititem.show()

        if not menu:
            menu = gtk.Menu()
            audititem.set_submenu(menu)

        act = gtk.Action(name, lbl, tooltip, stock)
        act.connect('activate', cb)

        item = act.create_menu_item()
        item.set_name(name)
        item.show()

        menu.append(item)

        return act, item

    def deregister_audit_item(self, item):
        return self.__deregister_audit_item('/menubar/Audits', item)

    def deregister_audit_mitm_item(self, item):
        return self.__deregister_audit_item('/menubar/Mitm', item)

    def __deregister_audit_item(self, mname, item):
        audititem = self.ui_manager.get_widget(mname)
        menu = audititem.get_submenu()

        if not menu:
            return False

        for citem in menu:
            if citem is item:
                citem.hide()
                menu.remove(citem)

                if not menu.get_children():
                    audititem.set_sensitive(False)

                return True

        return False

    def get_tab(self, name):
        """
        Get a tab from its name

        @param name the name of the tab
        """

        return self.registered_tabs[name]

    def deregister_tab(self, tab):
        """
        Deregister a tab deleting his CheckMenu and tab from the paned

        @param tab the tab to deregister
        @return True if is ok or False
        """

        item = self.ui_manager.get_widget('/menubar/Views')
        menu = item.get_submenu()

        def find_tab(item, udata):
            tab, find = udata

            if item.get_data('tab-object') is tab:
                find = item
                return True

        find = None
        menu.foreach(find_tab, (tab, find))

        if find is not None:
            menu.remove(find)
            self.main_paned.remove_view(tab)
            del self.registered_tabs[tab.name]

            return True

        return False

    def register_tab(self, tab, show=True):
        """
        Register a tab

        @param tab the Tab object
        @param show if the Tab should be showed
        """

        item = self.ui_manager.get_widget('/menubar/Views')
        menu = item.get_submenu()

        item.show()

        if not menu:
            menu = gtk.Menu()
            item.set_submenu(menu)

        if tab.name in self.registered_tabs:
            raise Exception("Tab already present")

        # Ok we should add a CheckMenuItem to this f*****g menu
        self.registered_tabs[tab.name] = tab

        log.debug("Tab %s registered as %s" % (tab.label_text, tab.name))

        if tab.tab_position is None:
            # This is the central widget so it should be added
            # with no MenuItem
            self.main_paned.add_view(tab)
            return

        new_item = gtk.CheckMenuItem(tab.label_text)
        new_item.set_data('tab-object', tab)
        new_item.connect('toggled', self.__on_toggle_tab_menu, tab)

        if show:
            new_item.set_active(True)

        new_item.show()
        menu.append(new_item)

    def create_session(self, menu, tup):
        """
        Create a new session using ctxklass and sessklass

        @param menu gtk.MenuItem
        @param tuple a tuple containing (sessklass, ctxklass)
        """
        sessklass, ctxklass = tup
        ServiceBus().call('pm.sessions', 'create_session', sessklass, ctxklass)

    def register_session(self, sessklass, ctxklass=None):
        """
        Register a custom session class and returns the new id
        of the SessionType

        @param sessklass the custom session class
        @param ctxklass the context class to use
        @return id
        """

        log.debug('Registering a new session')

        if sessklass.session_menu is not None:
            log.debug('Creating new menu entry named %s for the session' % \
                      sessklass.session_menu)

            item = self.ui_manager.get_widget('/menubar/File')
            menu = item.get_submenu()

            item = gtk.MenuItem(sessklass.session_menu)
            item.connect('activate', self.create_session,
                         (sessklass, ctxklass))
            item.show()

            menu.insert(item, 2)

            sessklass.session_menu_object = item

        return SessionType.add_session(sessklass)

    def deregister_session(self, sessklass):
        if sessklass.session_menu_object:
            menu = self.ui_manager.get_widget('/menubar/File').get_submenu()
            sessklass.session_menu_object.hide()

            menu.remove(sessklass.session_menu_object)

        return SessionType.remove_session(sessklass)

    def bind_session(self, ptype, persp_klass, show_pers=True, resize=False):
        """
        Bind the perspective 'pers_klass' to Session 'ptype'

        @param ptype the Session type to customize
        @param persp_klass the perspective class to add to the selected Session
        @param show_pers choose to show the perspective
        @param resize if True child should resize when the paned is resized
        """

        log.debug(
            "Binding perspective %s to Session %s" % \
            (persp_klass, SessionType.types[ptype])
        )

        self.session_binder[ptype].append((persp_klass, show_pers, resize))

        klass = SessionType.types[ptype]

        for page in ServiceBus().call('pm.sessions', 'get_sessions'):
            if isinstance(page, klass):
                self.apply_bindings(page, ptype, persp_klass)

    def unbind_session(self, ptype, persp_klass):
        try:
            for i in range(len(self.session_binder[ptype])):
                (klass, show, resize) = self.session_binder[ptype][i]

                if klass is not persp_klass:
                    continue

                del self.session_binder[ptype][i]

                klass = SessionType.types[ptype]

                for page in ServiceBus().call('pm.sessions', 'get_sessions'):
                    if isinstance(page, klass):
                        page.remove_perspective(persp_klass)

                log.debug(
                    "Binding method %s for perspective of type %s removed" % \
                    (persp_klass, SessionType.types[ptype])
                )

                return True
        except:
            log.error(
                "Failed to remove binding method %s for session of type %s" % \
                (persp_klass, SessionType.type[ptype])
            )

        return False

    def apply_bindings(self, page, ptype, klass=None):
        for persp_klass, show, resize in self.session_binder[ptype]:
            if not klass or (klass and persp_klass is klass):
                page.add_perspective(persp_klass, show, resize)

    def bind_perspective(self, ptype, callback):
        """
        Bind the perspective 'type'

        The callback should be of the type
          def perspective_cb(perspective, type, already_present, added)

        @param type the perspective's type (see also PerspectiveType)
        @param callback the callback to execute when a new
               perspective of type 'type' is created
        """

        log.debug(
            "Binding method %s for perspective of type %s" % \
            (callback, PerspectiveType.types[ptype])
        )

        self.perspective_binder[ptype].append(callback)

        for page in ServiceBus().call('pm.sessions', 'get_sessions'):
            if not isinstance(page, Session):
                continue

            for perspective in page.perspectives:
                idx = PerspectiveType.types[type(perspective)]

                callback(perspective, idx, True, True)

    def debind_perspective(self, type, callback):
        """
        Remove the binding callback for perspective of type 'type'

        @param type the perspective type
        @param callback the callback to remove
        @return True if the callback is removed correctly
        """

        try:
            self.perspective_binder[type].remove(callback)

            for page in ServiceBus().call('pm.sessions', 'get_sessions'):
                if not isinstance(page, Session):
                    continue

                for perspective in page.perspectives:
                    idx = PerspectiveType.types[type(perspective)]

                    callback(perspective, idx, True, False)

            log.debug(
                "Binding method %s for perspective of type %s removed" % \
                (callback, PerspectiveType.types[type])
            )

            return True
        except:
            log.error(
                "Failed to remove binding method %s "
                "for perspective of type %s" % \
                (callback, PerspectiveType.types[type])
            )

        return False

    def __pack_widgets(self):
        "Pack widgets"

        self.menubar = self.ui_manager.get_widget("/menubar")
        self.vbox.pack_start(self.menubar, False, False, 0)

        self.toolbar = self.ui_manager.get_widget("/toolbar")
        self.toolbar.set_style(gtk.TOOLBAR_ICONS)

        self.vbox.pack_start(self.toolbar, False, False, 0)

        item = self.ui_manager.get_widget('/menubar/Views')
        item.remove_submenu()

        item = self.ui_manager.get_widget('/menubar/Audits')
        item.remove_submenu()

        item = self.ui_manager.get_widget('/menubar/Mitm')
        item.remove_submenu()

        self.vbox.pack_start(self.main_paned)
        self.vbox.pack_start(self.statusbar, False, False)

        # Tabs
        self.register_tab(MainTab())

        self.register_tab(ProtocolSelectorTab(),
                          Prefs()['gui.views.protocol_selector_tab'].value)
        self.register_tab(PropertyTab(),
                          Prefs()['gui.views.property_tab'].value)
        self.register_tab(StatusTab(), Prefs()['gui.views.status_tab'].value)
        self.register_tab(OperationsTab(),
                          Prefs()['gui.views.operations_tab'].value)
        self.register_tab(VteTab(), Prefs()['gui.views.vte_tab'].value)
        self.register_tab(HackTab(), Prefs()['gui.views.hack_tab'].value)
        self.register_tab(ConsoleTab(), Prefs()['gui.views.console_tab'].value)
        self.register_tab(HostListTab(),
                          Prefs()['gui.views.hostlist_tab'].value)

        self.add(self.vbox)

    def __on_menuitem_selected(self, menuitem, tooltip):
        self.statusbar.push(tooltip)

    def __on_menuitem_deselected(self, menuitem):
        self.statusbar.pop()

    def __on_connect_proxy(self, uimgr, action, widget):
        tooltip = action.get_property('tooltip')

        if isinstance(widget, gtk.MenuItem) and tooltip:
            cid = widget.connect('select', self.__on_menuitem_selected,
                                 tooltip)
            cid2 = widget.connect('deselect', self.__on_menuitem_deselected)
            widget.set_data('pm::cids', (cid, cid2))

    def __on_disconnect_proxy(self, uimgr, action, widget):
        cids = widget.get_data('pm::cids')

        if not isinstance(cids, tuple):
            return

        try:
            for name, cid in cids:
                widget.disconnect(cid)
        except:
            pass

    def __connect_signals(self):
        "Connect signals"
        self.connect('delete-event', self.__on_quit)

        # Ok we need also to connect signals from main notebook
        # so we could manage easilly the bind_perspective calls

        maintab = self.get_tab("MainTab")
        maintab.session_notebook.connect('page-added',
                                         self.__on_maintab_page_added)
        maintab.session_notebook.connect('page-removed',
                                         self.__on_maintab_page_removed)
        maintab.session_notebook.connect('switch-page',
                                         self.__on_maintab_page_switched)
        self.__on_maintab_page_switched(maintab.session_notebook, None, 0)

    def connect_tabs_signals(self):
        "Used to connect signals between tabs"

        for key, tab in self.registered_tabs.items():
            tab.connect_tab_signals()

    def __on_maintab_page_added(self, notebook, page, pagenum):
        if not isinstance(page, Session):
            return

        for perspective in page.perspectives:
            try:
                idx = PerspectiveType.types[type(perspective)]

                for callback in self.perspective_binder[idx]:
                    callback(perspective, idx, False, True)
            except:
                pass

    def __on_maintab_page_removed(self, notebook, page, pagenum):
        if not isinstance(page, Session):
            return

        for perspective in page.perspectives:
            try:
                idx = PerspectiveType.types[type(perspective)]

                for callback in self.perspective_binder[idx]:
                    callback(perspective, idx, True, False)
            except:
                pass

    def __on_maintab_page_switched(self, notebook, page, pagenum):
        page = notebook.get_nth_page(pagenum)

        item = self.ui_manager.get_widget('/menubar/Audits')
        mitm_item = self.ui_manager.get_widget('/menubar/Mitm')

        if isinstance(page, Session) and getattr(page, 'context', None):
            enabled = (page.context.file_types and True or False)
        else:
            enabled = False

        for act in ('Save', 'SaveAs'):
            self.main_action_group.get_action(act).set_sensitive(enabled)

        if not isinstance(page, AuditSession):
            item.set_sensitive(False)
            mitm_item.set_sensitive(False)
        else:
            submenu = item.get_submenu()

            if submenu and submenu.get_children():
                item.set_sensitive(True)

            submenu = mitm_item.get_submenu()

            if submenu and submenu.get_children():
                mitm_item.set_sensitive(True)

                for item in submenu:
                    if item.get_name() in page.mitm_attacks:
                        item.set_sensitive(False)
                    else:
                        item.set_sensitive(True)

    def __on_toggle_tab_menu(self, menuitem, tab):
        if menuitem.get_active():
            self.main_paned.add_view(tab)
        else:
            self.main_paned.remove_view(tab)

    def __on_routing(self, action):
        dialog = RoutesDialog(self)
        dialog.set_transient_for(self)

        if dialog.run() == gtk.RESPONSE_ACCEPT:
            dialog.save()

        dialog.hide()
        dialog.destroy()

    def __on_plugins(self, action):
        self.plugin_window.show()

    def __on_preferences(self, action):
        dialog = PreferenceDialog(self)
        dialog.set_transient_for(self)
        dialog.show()

    def __on_about(self, action):
        dialog = gtk.AboutDialog()

        dialog.set_logo(
            gtk.gdk.pixbuf_new_from_file(
                os.path.join(PIXMAPS_DIR, 'pm-logo.png')))
        dialog.set_transient_for(self)
        dialog.set_name("PacketManipulator")
        dialog.set_version(PM_VERSION + (PM_CODENAME \
                                         and ' (%s)' % PM_CODENAME \
                                         or ''))

        dialog.set_website(PM_SITE)
        dialog.set_website_label(PM_SITE)

        dialog.set_comments(_("Packet manipulation made easy%s\n%s") % \
                             ((PM_DEVELOPMENT \
                               and ' (SVN revision %s)' % PM_SVN_REVISION \
                               or ''),
                             "«%s»" % random.choice(PM_SLOGANS)))

        dialog.set_authors(['Francesco Piccinno <*****@*****.**>'])

        dialog.set_copyright('\n'.join(
            ('Copyright (C) 2008 Francesco Piccinno' \
                     ' <stack.box at gmail dot com>',
             'Copyright (C) 2008 Adriano Monteiro Marques' \
                          ' <py.adriano at gmail dot com>')))

        dialog.set_license(
            _('This program is relased '
              'under the terms of GPLv2'))

        dialog.run()
        dialog.hide()
        dialog.destroy()

    def __on_select_iface(self, action):
        dialog = InterfaceDialog(self)
        dialog.set_transient_for(self)

        if dialog.run() == gtk.RESPONSE_ACCEPT:
            iface = dialog.get_selected()
            args = dialog.get_options()

            if iface or args['capmethod'] == 1:
                tab = self.get_tab('OperationsTab')
                tab.tree.append_operation(SniffOperation(iface, **args))

        dialog.hide()
        dialog.destroy()

    def start_new_audit(self, dev1, dev2, bpf_filter, skipfwd, unoffensive):
        log.debug('Creating a new AuditOperation using dev1: %s dev2: %s '
                  'bpf: %s skipfwd: %s unoffensive: %s' \
                  % (dev1, dev2, bpf_filter, skipfwd, unoffensive))

        tab = self.get_tab('OperationsTab')
        tab.tree.append_operation(AuditOperation(dev1, dev2, bpf_filter, \
                                                 skipfwd, unoffensive))

    def __on_new_audit(self, action):
        dialog = NewAuditDialog(self)
        dialog.set_transient_for(self)

        if dialog.run() == gtk.RESPONSE_ACCEPT:
            inputs = dialog.get_inputs()
            self.start_new_audit(*inputs)

        dialog.hide()
        dialog.destroy()

    def __on_new_sequence(self, action):
        ServiceBus().call('pm.sessions', 'create_sequence_session', [])

    def __on_open_session(self, action):
        types = {}
        sessions = (backend.StaticContext, backend.SequenceContext,
                    backend.SniffContext)

        for ctx in sessions:
            for name, pattern in ctx.file_types:
                types[pattern] = (name, ctx)

        dialog = gtk.FileChooserDialog(
            _("Select a session"),
            self,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,
                     gtk.RESPONSE_ACCEPT))
        dialog.set_transient_for(self)

        filterall = gtk.FileFilter()
        filterall.set_name(_('All supported files'))
        [filterall.add_pattern(k) for k in types]
        dialog.add_filter(filterall)

        for pattern, (name, ctx) in types.items():
            filter = gtk.FileFilter()
            filter.set_name(name)
            filter.add_pattern(pattern)
            dialog.add_filter(filter)

        if dialog.run() == gtk.RESPONSE_ACCEPT:
            ctx = None
            fname = dialog.get_filename()

            try:
                find = fname.split('.')[-1]

                for pattern in types:
                    if pattern.split('.')[-1] == find:
                        ctx = types[pattern][1]
            except:
                pass

            if ctx is not backend.SequenceContext and \
               ctx is not backend.SniffContext and \
               ctx is not backend.StaticContext:

                d = HIGAlertDialog(
                    type=gtk.MESSAGE_ERROR,
                    message_format=_("Unable to open selected session"),
                    secondary_text=_(
                        "PacketManipulator is unable to guess the "
                        "file type. Try to modify the extension "
                        "and to reopen the file."))
                d.set_transient_for(self)
                d.run()
                d.destroy()
            else:
                self.open_generic_file_async(fname)

        dialog.hide()
        dialog.destroy()

    def open_generic_file_async(self, fname):
        """
        Open a generic file (pcap/sequence and other supported file format)
        @param fname the path to the file to open
        """
        tab = self.get_tab("OperationsTab")
        tab.tree.append_operation(FileOperation(fname,
                                                FileOperation.TYPE_LOAD))

    def open_generic_file(self, fname):
        """
        Open a generic file (pcap/sequence and other supported file format)
        @param fname the path to the file to open
        @return a umit.pm.session.base.Session object or None on errors
        """

        if not os.path.isfile(fname):
            return None

        types = {}
        sessions = (backend.StaticContext, backend.SequenceContext,
                    backend.SniffContext)

        for ctx in sessions:
            for name, pattern in ctx.file_types:
                types[pattern] = (name, ctx)

        try:
            find = fname.split('.')[-1]

            for pattern in types:
                if pattern.split('.')[-1] == find:
                    ctx = types[pattern][1]
        except:
            pass

        if ctx is backend.SequenceContext:
            return ServiceBus().call('pm.sessions', 'load_sequence_session',
                                     fname)

        elif ctx is backend.SniffContext:
            return ServiceBus().call('pm.sessions', 'load_sniff_session',
                                     fname)

        elif ctx is backend.StaticContext:
            return ServiceBus().call('pm.sessions', 'load_static_session',
                                     fname)

    def __on_save_session(self, action):
        session = ServiceBus().call('pm.sessions', 'get_current_session')

        if session:
            session.save()

    def __on_save_session_as(self, action):
        session = ServiceBus().call('pm.sessions', 'get_current_session')

        if session:
            session.save_as()

    def __on_quit(self, *args):
        self.hide()

        # We need to stop the pending sniff threads
        lst = []

        for page in ServiceBus().call('pm.sessions', 'get_sessions'):
            if isinstance(page, Session) and \
               isinstance(page.context, backend.TimedContext):
                lst.append(page.context)

        for ctx in lst:
            ctx.stop()

        # Avoids joining all threads are daemon
        #for ctx in lst:
        #    ctx.join()

        errs = []

        try:
            log.debug('Saving options before exiting')
            Prefs().write_options()
        except IOError, err:
            errs.append(err)

        try:
            log.debug('Saving audit configurations')
            AuditManager().write_configurations()
        except IOError, err:
            errs.append(err)
Example #20
0
 def register_decoders(self):
     manager = AuditManager()
     manager.add_decoder(NET_LAYER, LL_TYPE_IP, self.ip_decoder)
     manager.add_injector(0, LL_TYPE_IP, ip_injector)
     manager.add_injector(0, STATELESS_IP_MAGIC, stateless_ip_injector)
Example #21
0
 def stop(self):
     manager = AuditManager()
     manager.remove_decoder(PROTO_LAYER, NL_TYPE_UDP, self.decoder)
     manager.remove_injector(1, NL_TYPE_UDP, self.injector)
Example #22
0
    def __on_str_changed(self, widget, udata):
        conf_name, opt_id = udata

        AuditManager().get_configuration(conf_name)[opt_id] = \
                     widget.get_text()
Example #23
0
 def register_decoders(self):
     manager = AuditManager()
     manager.add_decoder(NET_LAYER, LL_TYPE_IP, self.ip_decoder)
     manager.add_injector(0, LL_TYPE_IP, ip_injector)
     manager.add_injector(0, STATELESS_IP_MAGIC, stateless_ip_injector)
Example #24
0
 def register_decoders(self):
     manager = AuditManager()
     manager.add_decoder(PROTO_LAYER, NL_TYPE_UDP, self.decoder)
     manager.add_injector(1, NL_TYPE_UDP, self.injector)
Example #25
0
 def stop(self):
     manager = AuditManager()
     manager.remove_decoder(PROTO_LAYER, NL_TYPE_UDP, self.decoder)
     manager.remove_injector(1, NL_TYPE_UDP, self.injector)
Example #26
0
    def _inject_tcp(self, context, mpkt, length):
        """
        Function that manages injection of fragments in active TCP connection
        """

        ident = TCPIdent.create(mpkt)
        sess = SessionManager().get_session(ident)

        if not sess:
            log.debug("No TCP session found.")
            return False, length

        if ident.l3_src == sess.ident.l3_src:
            status = sess.data[1]
            ostatus = sess.data[0]
        else:
            status = sess.data[0]
            ostatus = sess.data[1]

        mpkt.set_fields('tcp', {
            'sport' : mpkt.l4_src,
            'dport' : mpkt.l4_dst,
            'dataofs' : 5,
            'chksum' : None,
            'urgptr' : 0,
            'flags' : TH_PSH,
            'options' : {}})

        if status.injectable & INJ_FIN or \
           not status.injectable & INJ_FWD or \
           not ostatus.injectable & INJ_FWD:
            log.debug("Session is not injectable.")
            return False, length

        mpkt.set_fields('tcp', {
            'seq' : status.last_seq + status.seq_adj,
            'ack' : status.last_ack - ostatus.seq_adj})

        if status.last_ack != 0:
            mpkt.set_field('tcp.flags', mpkt.l4_flags | TH_ACK)

        mpkt.session = sess.prev
        length += 20 + mpkt.l2_len

        injector = AuditManager().get_injector(0, mpkt.session.ident.magic)
        is_ok, length = injector(context, mpkt, length)

        if not is_ok:
            return is_ok, length

        length = context.get_mtu() - length

        if length > mpkt.inject_len:
            length = mpkt.inject_len

        payload = mpkt.inject[:length]
        payload_pkt = MetaPacket.new('raw')
        payload_pkt.set_field('raw.load', payload)
        mpkt.add_to('tcp', payload_pkt)

        status.seq_adj += length
        mpkt.data_len = length

        return True, length
Example #27
0
def ip_decoder():
    manager = AuditManager()

    conf = manager.get_configuration('decoder.ip')
    checksum_check, reassemble, max_len, max_frags = \
        conf['checksum_check'], conf['reassemble'], \
        conf['reassemble_max_fraglist'], conf['reassemble_max_fragments']

    reas_dict = {}

    def ip_reassemble(mpkt):
        # Here we have to check for fragmentation
        # by creating a dict to holds id of ip packets
        # and set mpkt.lock() on it if mpkg is MF
        # until the resegmentation is done.
        # If it's a fragment we have to return None
        # to break the chain.

        # TODO: check ip.flags standard name in UMPA
        ts = time.time()
        mf = mpkt.get_field('ip.flags', 0) & 1
        frag_off = mpkt.get_field('ip.frag', 0) * 8

        if not mf and frag_off == 0:
            return False

        ipid = mpkt.get_field('ip.id')

        if ipid in reas_dict:
            plist = reas_dict[ipid]

            if len(plist) >= max_frags:
                del reas_dict[ipid]
                manager.user_msg(
                    _('Dropping out the sequence with ID: '
                      '%s due reassemble_max_fragments') % ipid, 7,
                    'decoder.ip')

                return False

            ret = 0
            idx = 0
            inserted = False

            while idx < len(plist):
                ts2, frag_off2, mpkt2 = plist[idx]

                if frag_off2 == frag_off:
                    plist[idx] = (ts, frag_off, mpkt.copy())
                    break
                elif frag_off2 < frag_off:
                    ret += frag_off2
                    idx += 1
                    continue

                inserted = True
                plist.insert(idx, (ts, frag_off, mpkt.copy()))
                break

            if not inserted:
                plist.append((ts, frag_off, mpkt.copy()))

            # Now let's get the last packet and see if MF = 0
            # EVASION!
            if plist[-1][-1].get_field('ip.flags') & 1 == 0:

                if idx == len(plist) - 1:
                    ret = frag_off - ret
                else:
                    while idx < len(plist) - 1:
                        ts2, frag_off2, mpkt2 = plist[idx]
                        ret += frag_off2
                        idx += 1

                        ret = plist[-1][1] - ret

                if ret == 0:
                    log.debug('Reassembling sequence with ID: %s' % \
                              ipid)

                    reas_payload = ''

                    for ts2, frag_off2, mpkt2 in plist:
                        try:
                            ihl = mpkt2.l3_len
                            reas_payload += mpkt2.get_field('ip')[ihl:]
                        except:
                            pass

                    # Ok check that we have a complete payload
                    ihl = mpkt.l3_len
                    p_len = frag_off + mpkt.get_field('ip.len') - ihl

                    if len(reas_payload) != p_len:
                        mpkt.set_cfield('reassembled_payload', None)
                        manager.user_msg(_('Reassemble of IP packet ' \
                                           'from %s to %s failed') %  \
                                         (mpkt.l3_src, mpkt.l3_dst),  \
                                         4, 'decoder.ip')

                    # Nice drop out everythin!
                    del reas_dict[ipid]

                    mpkt.set_cfield('reassembled_payload', reas_payload)
                    return True
        else:
            if len(reas_dict) >= max_len:
                # Ok just drop the list with the minor ts (the oldest)
                min_k = min([(v, k) for k, v in reas_dict.items()])[1]
                del reas_dict[min_k]

                # Debug
                manager.user_msg(
                    _('Dropping out the oldest sequence '
                      'with ID: %s') % min_k, 7, 'decoder.ip')

            log.debug('First packet of the sequence with ID: %s' % ipid)
            reas_dict[ipid] = [(ts, frag_off, mpkt)]

        return False

    def ip(mpkt):
        mpkt.l3_src, \
        mpkt.l3_dst, \
        mpkt.l4_proto = mpkt.get_fields('ip', ('src', 'dst', 'proto'))

        # TODO: handle IPv6

        ipraw = mpkt.get_field('ip')

        if not ipraw:
            return

        mpkt.l3_len = mpkt.get_field('ip.ihl') * 4
        mpkt.payload_len = mpkt.get_field('ip.len') - mpkt.l3_len

        if mpkt.context:
            mpkt.context.check_forwarded(mpkt)

            if mpkt.flags & MPKT_FORWARDED:
                return None

            mpkt.context.set_forwardable(mpkt)

        iplen = min(20, len(ipraw))

        if mpkt.get_field('ip.len') > len(ipraw):
            # Probably we are capturing with low snaplen
            # so the packets are not fully captured. Avoid
            # further calculation.
            return PROTO_LAYER, mpkt.l4_proto

        if checksum_check:
            ihl = max(20, mpkt.l3_len)
            pkt = ipraw[:10] + '\x00\x00' + ipraw[12:ihl]

            chksum = checksum(pkt)

            # Probably here it's better to set also a cfield
            # and to turn False the checksum_check default value
            if mpkt.get_field('ip.chksum') != chksum:
                mpkt.set_cfield('good_checksum', hex(chksum))
                manager.user_msg(_("Invalid IP packet from %s to %s : " \
                                   "wrong checksum %s instead of %s") %  \
                                 (mpkt.l3_src, mpkt.l3_dst,          \
                                  hex(mpkt.get_field('ip.chksum')),  \
                                  hex(chksum)),
                                 5, 'decoder.ip')

            elif reassemble:
                ip_reassemble(mpkt)

        ident = IPIdent.create(mpkt)
        sess = SessionManager().get_session(ident)

        if not sess:
            sess = Session(ident)
            sess.data = IPStatus()
            SessionManager().put_session(sess)

        sess.prev = mpkt.session
        mpkt.session = sess

        status = sess.data
        status.last_id = mpkt.get_field('ip.id', 0)

        manager.run_decoder(PROTO_LAYER, mpkt.l4_proto, mpkt)

        if mpkt.flags & MPKT_DROPPED:
            status.id_adj -= 1
        elif mpkt.flags & MPKT_MODIFIED or status.id_adj != 0:
            mpkt.set_field('ip.id', mpkt.get_field('ip.id', 0) + status.id_adj)
            mpkt.set_field('ip.len',
                           mpkt.get_field('ip.len', 0) + mpkt.inj_delta)
            mpkt.set_field('ip.chksum', None)

    return ip
Example #28
0
def tcp_fp(finger):
    manager = AuditManager()

    def internal(mpkt):
        try:
            finger.push(mpkt, finger.TTL, mpkt.get_field('ip.ttl'))
            finger.push(mpkt, finger.DF, mpkt.get_field('ip.frag', 0) & 0x400)
            finger.push(mpkt, finger.LT, mpkt.get_field('ip.ihl', 0) * 4)

            tcpraw = mpkt.get_field('tcp')
            flags = mpkt.get_field('tcp.flags')

            if flags and finger and flags & TH_SYN:
                opt_start = 20
                opt_end = mpkt.get_field('tcp.dataofs') * 4

                finger.push(mpkt, finger.WINDOW, mpkt.get_field('tcp.window', 0))
                finger.push(mpkt, finger.TCPFLAG, (flags & TH_ACK) and 1 or 0)
                finger.push(mpkt, finger.LT, opt_end)

                while opt_start < opt_end:
                    val = ord(tcpraw[opt_start])

                    if val == TCPOPT_EOL:
                        opt_start = opt_end
                    elif val == TCPOPT_NOP:
                        finger.push(mpkt, finger.NOP, 1)
                        opt_start += 1
                    elif val == TCPOPT_SACKOK:
                        finger.push(mpkt, finger.SACK, 1)
                        opt_start += 2
                    elif val == TCPOPT_MAXSEG:
                        opt_start += 2
                        finger.push(mpkt, finger.MSS, pntos(unpack("H",
                                    tcpraw[opt_start:opt_start + 2])[0]))
                        opt_start += 2
                    elif val == TCPOPT_WSCALE:
                        opt_start += 2
                        finger.push(mpkt, finger.WS, ord(tcpraw[opt_start]))
                        opt_start += 1
                    elif val == TCPOPT_TIMESTAMP:
                        finger.push(mpkt, finger.TIMESTAMP, 1)
                        opt_start +=1
                        opt_start += ord(tcpraw[opt_start]) - 1
                    else:
                        opt_start += 1
                        if opt_start < len(tcpraw):# and ord(tcpraw[opt_start]):
                            opt_start += val - 1

                remote_os = finger.report(mpkt)

                mpkt.set_cfield('remote_os', remote_os)
                manager.user_msg(_('%s is running %s') % (mpkt.get_field('ip.src'),
                                                          remote_os),
                                 5, 'fingerprint')
        except Exception, err:
            log.error('Ignoring exception while setting fingerprint.')
            log.error(generate_traceback())

            log.debug('Clearing fingerprint.')
            finger.clear(mpkt)
Example #29
0
 def register_decoders(self):
     manager = AuditManager()
     manager.add_decoder(PROTO_LAYER, NL_TYPE_UDP, self.decoder)
     manager.add_injector(1, NL_TYPE_UDP, self.injector)
Example #30
0
    def __init__(self):
        gtk.VBox.__init__(self, False, 2)

        self.set_border_width(4)

        self.store = gtk.ListStore(str, int, str)
        self.view = gtk.TreeView(self.store)
        self.view.set_rules_hint(True)
        self.view.set_reorderable(True)

        idx = 0
        lbls = (_('Column title'), _('Column size'), _('Function/cfield'))

        for lbl in lbls[:-1]:
            rend = gtk.CellRendererText()
            rend.set_property('editable', True)
            rend.connect('edited', self.__on_rend_edited, idx)

            col = gtk.TreeViewColumn(lbl, rend, text=idx)
            self.view.append_column(col)
            idx += 1

        # Last column
        model = gtk.ListStore(str)
        cfields = AuditManager().get_configuration('global.cfields').keys()
        cfields.sort()

        for field in cfields:
            model.append(['%' + field + '%'])

        rend = gtk.CellRendererCombo()
        rend.set_property('model', model)
        rend.set_property('text-column', 0)
        rend.set_property('editable', True)
        rend.connect('edited', self.__on_rend_edited, idx)

        self.view.props.has_tooltip = True
        self.view.connect('query-tooltip', self.__on_query_tooltip)

        col = gtk.TreeViewColumn(lbls[-1], rend, text=idx)
        self.view.append_column(col)

        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)

        sw.add(self.view)

        bb = gtk.HButtonBox()
        bb.set_layout(gtk.BUTTONBOX_END)

        btn = gtk.Button(stock=gtk.STOCK_ADD)
        btn.connect('clicked', self.__on_add_row)
        bb.pack_start(btn)

        btn = gtk.Button(stock=gtk.STOCK_REMOVE)
        btn.connect('clicked', self.__on_remove_row)
        bb.pack_start(btn)

        self.pack_start(sw)
        self.pack_end(bb, False, False)

        # Let's populate
        columns_str = Prefs()['gui.maintab.sniffview.columns'].value

        for column_str in columns_str.split(','):
            try:
                label, pixel_size, eval_str = column_str.split('|', 2)
                pixel_size = int(pixel_size)

                self.store.append([label, pixel_size, eval_str])
            except:
                pass

        self.widgets = []
Example #31
0
class TCPDecoder(Plugin, PassiveAudit):
    def start(self, reader):
        self.checksum_check = True
        self.reassembler = None
        self.manager = None

    def stop(self):
        manager = AuditManager()
        manager.remove_decoder(PROTO_LAYER, NL_TYPE_TCP, self._process_tcp)
        manager.remove_injector(1, NL_TYPE_TCP, self._inject_tcp)

        try:
            manager.remove_decoder_hook(PROTO_LAYER, NL_TYPE_ICMP,
                                             self.reassembler.process_icmp, 1)
        except:
            pass

    def register_decoders(self):
        self.manager = AuditManager()
        conf = self.manager.get_configuration('decoder.tcp')

        self.checksum_check = conf['checksum_check']

        self.manager.add_decoder(PROTO_LAYER, NL_TYPE_TCP, self._process_tcp)
        self.manager.add_injector(1, NL_TYPE_TCP, self._inject_tcp)

        if conf['enable_reassemble']:
            self.reassembler = Reassembler(conf['reassemble_workarounds'],
                                           conf['reassemble_maxstreams'])
            self.manager.add_decoder_hook(PROTO_LAYER, NL_TYPE_ICMP,
                                          self.reassembler.process_icmp, 1)

    def _inject_tcp(self, context, mpkt, length):
        """
        Function that manages injection of fragments in active TCP connection
        """

        ident = TCPIdent.create(mpkt)
        sess = SessionManager().get_session(ident)

        if not sess:
            log.debug("No TCP session found.")
            return False, length

        if ident.l3_src == sess.ident.l3_src:
            status = sess.data[1]
            ostatus = sess.data[0]
        else:
            status = sess.data[0]
            ostatus = sess.data[1]

        mpkt.set_fields('tcp', {
            'sport' : mpkt.l4_src,
            'dport' : mpkt.l4_dst,
            'dataofs' : 5,
            'chksum' : None,
            'urgptr' : 0,
            'flags' : TH_PSH,
            'options' : {}})

        if status.injectable & INJ_FIN or \
           not status.injectable & INJ_FWD or \
           not ostatus.injectable & INJ_FWD:
            log.debug("Session is not injectable.")
            return False, length

        mpkt.set_fields('tcp', {
            'seq' : status.last_seq + status.seq_adj,
            'ack' : status.last_ack - ostatus.seq_adj})

        if status.last_ack != 0:
            mpkt.set_field('tcp.flags', mpkt.l4_flags | TH_ACK)

        mpkt.session = sess.prev
        length += 20 + mpkt.l2_len

        injector = AuditManager().get_injector(0, mpkt.session.ident.magic)
        is_ok, length = injector(context, mpkt, length)

        if not is_ok:
            return is_ok, length

        length = context.get_mtu() - length

        if length > mpkt.inject_len:
            length = mpkt.inject_len

        payload = mpkt.inject[:length]
        payload_pkt = MetaPacket.new('raw')
        payload_pkt.set_field('raw.load', payload)
        mpkt.add_to('tcp', payload_pkt)

        status.seq_adj += length
        mpkt.data_len = length

        return True, length

    def _process_tcp(self, mpkt):
        mpkt.l4_src, \
        mpkt.l4_dst, \
        mpkt.l4_ack, \
        mpkt.l4_seq, \
        mpkt.l4_flags = mpkt.get_fields('tcp', ('sport', 'dport', 'ack', \
                                                'seq', 'flags'))
        mpkt.l4_len = mpkt.get_field('tcp.dataofs', 5) * 4

        if mpkt.l4_src is None:
            return None

        tcpraw = mpkt.get_field('tcp')

        if tcpraw:
            mpkt.data_len = mpkt.payload_len - mpkt.l4_len
            mpkt.data = tcpraw[mpkt.l4_len:]

        wrong = False

        if self.checksum_check and tcpraw:
            if mpkt.payload_len == len(tcpraw):
                ip_src = mpkt.l3_src
                ip_dst = mpkt.l3_dst

                psdhdr = pack("!4s4sHH",
                              inet_aton(ip_src),
                              inet_aton(ip_dst),
                              mpkt.l4_proto,
                              mpkt.payload_len)

                chksum = checksum(psdhdr + tcpraw[:16] + \
                                  "\x00\x00" + tcpraw[18:])

                if mpkt.get_field('tcp.chksum', 0) != chksum:
                    wrong = True
                    mpkt.set_cfield('good_checksum', hex(chksum))
                    self.manager.user_msg(
                                _("Invalid TCP packet from %s to %s : " \
                                  "wrong checksum %s instead of %s") %  \
                                (ip_src, ip_dst,                        \
                                 hex(mpkt.get_field('tcp.chksum', 0)),  \
                                 hex(chksum)),
                                5, 'decoder.tcp')

        if wrong:
            self.manager.run_decoder(APP_LAYER, PL_DEFAULT, mpkt)
            return None

        if self.reassembler:
            self.reassembler.process_tcp(mpkt)

        ident = TCPIdent.create(mpkt)
        sess = SessionManager().get_session(ident)

        if not sess:
            sess = Session(ident)
            sess.data = (TCPStatus(), TCPStatus())
            SessionManager().put_session(sess)

        sess.prev = mpkt.session
        mpkt.session = sess

        if ident.l3_src == sess.ident.l3_src:
            status = sess.data[1]
            ostatus = sess.data[0]
        else:
            status = sess.data[0]
            ostatus = sess.data[1]

        status.last_seq = mpkt.l4_seq + mpkt.data_len

        if mpkt.l4_flags & TH_ACK:
            status.last_ack = mpkt.l4_ack

        if mpkt.l4_flags & TH_SYN:
            status.last_seq += 1

        if mpkt.l4_flags & TH_RST:
            status.injectable |= INJ_FIN
            ostatus.injectable |= INJ_FIN

        if mpkt.flags & MPKT_FORWARDABLE:
            status.injectable |= INJ_FWD
        elif status.injectable & INJ_FWD:
            status.injectable ^= INJ_FWD

        self.manager.run_decoder(APP_LAYER, PL_DEFAULT, mpkt)

        if mpkt.l4_flags & TH_FIN:
            status.injectable |= INJ_FIN

        if mpkt.flags & MPKT_DROPPED and mpkt.flags & MPKT_FORWARDABLE:
            status.seq_adj += mpkt.inj_delta
        elif (mpkt.flags & MPKT_MODIFIED or \
             status.seq_adj != 0 or ostatus != 0) and \
             mpkt.flags & MPKT_FORWARDABLE:

            mpkt.set_field('tcp.seq', mpkt.l4_seq + status.seq_adj)
            mpkt.set_field('tcp.ack', mpkt.l4_ack - ostatus.seq_adj)

            status.seq_adj += mpkt.inj_delta

            mpkt.set_field('tcp.chksum', None)

        return None
Example #32
0
    def __on_float_changed(self, widget, udata):
        conf_name, opt_id = udata

        AuditManager().get_configuration(conf_name)[opt_id] = \
                     widget.get_value()
Example #33
0
    def __init__(self):
        gtk.VBox.__init__(self, False, 2)

        self.set_border_width(4)

        self.store = gtk.ListStore(str, int, str)
        self.view = gtk.TreeView(self.store)
        self.view.set_rules_hint(True)
        self.view.set_reorderable(True)

        idx = 0
        lbls = (_('Column title'), _('Column size'), _('Function/cfield'))

        for lbl in lbls[:-1]:
            rend = gtk.CellRendererText()
            rend.set_property('editable', True)
            rend.connect('edited', self.__on_rend_edited, idx)

            col = gtk.TreeViewColumn(lbl, rend, text=idx)
            self.view.append_column(col)
            idx += 1

        # Last column
        model = gtk.ListStore(str)
        cfields = AuditManager().get_configuration('global.cfields').keys()
        cfields.sort()

        for field in cfields:
            model.append(['%' + field + '%'])

        rend = gtk.CellRendererCombo()
        rend.set_property('model', model)
        rend.set_property('text-column', 0)
        rend.set_property('editable', True)
        rend.connect('edited', self.__on_rend_edited, idx)

        self.view.props.has_tooltip = True
        self.view.connect('query-tooltip', self.__on_query_tooltip)

        col = gtk.TreeViewColumn(lbls[-1], rend, text=idx)
        self.view.append_column(col)

        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)

        sw.add(self.view)

        bb = gtk.HButtonBox()
        bb.set_layout(gtk.BUTTONBOX_END)

        btn = gtk.Button(stock=gtk.STOCK_ADD)
        btn.connect('clicked', self.__on_add_row)
        bb.pack_start(btn)

        btn = gtk.Button(stock=gtk.STOCK_REMOVE)
        btn.connect('clicked', self.__on_remove_row)
        bb.pack_start(btn)

        self.pack_start(sw)
        self.pack_end(bb, False, False)

        # Let's populate
        columns_str = Prefs()['gui.maintab.sniffview.columns'].value

        for column_str in columns_str.split(','):
            try:
                label, pixel_size, eval_str = column_str.split('|', 2)
                pixel_size = int(pixel_size)

                self.store.append([label, pixel_size, eval_str])
            except:
                pass

        self.widgets = []