Пример #1
0
 def __new__(cls, name, bases, dct):
     c = super(ASN1_Object_metaclass, cls).__new__(cls, name, bases, dct)
     try:
         c.tag.register_asn1_object(c)
     except:
         warning("Error registering %r for %r" % (c.tag, c.codec))
     return c
Пример #2
0
    def recv(self, x=MTU):
        pkt, sa_ll = self.ins.recvfrom(x)
        if sa_ll[2] == socket.PACKET_OUTGOING:
            return None
        if sa_ll[3] in conf.l2types:
            cls = conf.l2types[sa_ll[3]]
            lvl = 2
        elif sa_ll[1] in conf.l3types:
            cls = conf.l3types[sa_ll[1]]
            lvl = 3
        else:
            cls = conf.default_l2
            warning(
                "Unable to guess type (interface=%s protocol=%#x family=%i). Using %s"
                % (sa_ll[0], sa_ll[1], sa_ll[3], cls.name))
            lvl = 3

        try:
            pkt = cls(pkt)
        except KeyboardInterrupt:
            raise
        except:
            if conf.debug_dissector:
                raise
            pkt = conf.raw_layer(pkt)
        if lvl == 2:
            pkt = pkt.payload

        if pkt is not None:
            from .arch import get_last_packet_timestamp
            pkt.time = get_last_packet_timestamp(self.ins)
        return pkt
Пример #3
0
    def recv(self, x=MTU):
        pkt, sa_ll = self.ins.recvfrom(x)
        if sa_ll[2] == socket.PACKET_OUTGOING:
            return None
        if sa_ll[3] in conf.l2types:
            cls = conf.l2types[sa_ll[3]]
            lvl = 2
        elif sa_ll[1] in conf.l3types:
            cls = conf.l3types[sa_ll[1]]
            lvl = 3
        else:
            cls = conf.default_l2
            warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s" % (sa_ll[0],sa_ll[1],sa_ll[3],cls.name))
            lvl = 3

        try:
            pkt = cls(pkt)
        except KeyboardInterrupt:
            raise
        except:
            if conf.debug_dissector:
                raise
            pkt = conf.raw_layer(pkt)
        if lvl == 2:
            pkt = pkt.payload
            
        if pkt is not None:
            from .arch import get_last_packet_timestamp
            pkt.time = get_last_packet_timestamp(self.ins)
        return pkt
Пример #4
0
 def lazy_init(self):
     try:
         f=open(self.filename)
     except IOError:
         warning("Can't open base %s" % self.filename)
         return
     try:
         self.base = []
         for l in f:
             if l[0] in ["#","\n"]:
                 continue
             l = tuple(l.split(":"))
             if len(l) < 8:
                 continue
             def a2i(x):
                 if x.isdigit():
                     return int(x)
                 return x
             li = [ a2i(i) for i in l[1:4] ]
             #if li[0] not in self.ttl_range:
             #    self.ttl_range.append(li[0])
             #    self.ttl_range.sort()
             self.base.append((l[0], li[0], li[1], li[2], l[4], l[5], l[6], l[7][:-1]))
     except:
         warning("Can't parse p0f database (new p0f version ?)")
         self.base = None
     f.close()
Пример #5
0
 def __new__(cls, name, bases, dct):
     c = super(ASN1_Object_metaclass, cls).__new__(cls, name, bases, dct)
     try:
         c.tag.register_asn1_object(c)
     except:
         warning("Error registering %r for %r" % (c.tag, c.codec))
     return c
Пример #6
0
 def __new__(cls, name, bases, dct):
     c = super(BERcodec_metaclass, cls).__new__(cls, name, bases, dct)
     try:
         c.tag.register(c.codec, c)
     except:
         warning("Error registering %r for %r" % (c.tag, c.codec))
     return c
Пример #7
0
    def lazy_init(self):
        try:
            f = open(self.filename)
        except IOError:
            warning("Can't open base %s" % self.filename)
            return
        try:
            self.base = []
            for l in f:
                if l[0] in ["#", "\n"]:
                    continue
                l = tuple(l.split(":"))
                if len(l) < 8:
                    continue

                def a2i(x):
                    if x.isdigit():
                        return int(x)
                    return x

                li = [a2i(i) for i in l[1:4]]
                #if li[0] not in self.ttl_range:
                #    self.ttl_range.append(li[0])
                #    self.ttl_range.sort()
                self.base.append(
                    (l[0], li[0], li[1], li[2], l[4], l[5], l[6], l[7][:-1]))
        except:
            warning("Can't parse p0f database (new p0f version ?)")
            self.base = None
        f.close()
Пример #8
0
 def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
     if iface is None:
         iface = conf.iface
     self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
     self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
     if not nofilter: 
         if conf.except_filter:
             if filter:
                 filter = "(%s) and not (%s)" % (filter, conf.except_filter)
             else:
                 filter = "not (%s)" % conf.except_filter
         if filter is not None:
             attach_filter(self.ins, filter, iface)
     self.ins.bind((iface, type))
     _flush_fd(self.ins)
     self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
     self.outs = self.ins
     self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30)
     sa_ll = self.outs.getsockname()
     if sa_ll[3] in conf.l2types:
         self.LL = conf.l2types[sa_ll[3]]
     elif sa_ll[1] in conf.l3types:
         self.LL = conf.l3types[sa_ll[1]]
     else:
         self.LL = conf.default_l2
         warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s" % (sa_ll[0],sa_ll[1],sa_ll[3],self.LL.name))
Пример #9
0
 def __new__(cls, name, bases, dct):
     c = super(BERcodec_metaclass, cls).__new__(cls, name, bases, dct)
     try:
         c.tag.register(c.codec, c)
     except:
         warning("Error registering %r for %r" % (c.tag, c.codec))
     return c
Пример #10
0
 def delt(self,  *args, **kargs):
     """delt(host|net, gw|dev)"""
     self.invalidate_cache()
     route = self.make_route(*args,**kargs)
     try:
         i=self.routes.index(route)
         del(self.routes[i])
     except ValueError:
         warning("no matching route found")
Пример #11
0
 def stop(self, _cmd="X"):
     try:
         with self.command_lock:
             if self.threadid is not None:
                 os.write(self.__fdw, _cmd.encode(encoding='UTF-8'))
                 while not self.thread_lock.acquire(0):
                     time.sleep(0.01) # interruptible wait for thread to terminate
                 self.thread_lock.release() # (not using .join() because it needs 'threading' module)
             else:
                 warning("Pipe engine thread not running")
     except KeyboardInterrupt:
         print("Interrupted by user.")
Пример #12
0
def get_if_list():
    try:
        f=open("/proc/net/dev","r")
    except IOError:
        warning("Can't open /proc/net/dev !")
        return []
    lst = []
    f.readline()
    f.readline()
    for l in f:
        lst.append(l.split(":")[0].strip())
    f.close()
    return lst
Пример #13
0
 def stop(self, _cmd="X"):
     try:
         with self.command_lock:
             if self.threadid is not None:
                 os.write(self.__fdw, _cmd.encode(encoding='UTF-8'))
                 while not self.thread_lock.acquire(0):
                     time.sleep(
                         0.01)  # interruptible wait for thread to terminate
                 self.thread_lock.release(
                 )  # (not using .join() because it needs 'threading' module)
             else:
                 warning("Pipe engine thread not running")
     except KeyboardInterrupt:
         print("Interrupted by user.")
Пример #14
0
 def run(self):
     log_interactive.info("Pipe engine thread started.")
     try:
         for p in self.active_pipes:
             p.start()
         sources = self.active_sources
         sources.add(self.__fdr)
         exhausted = set([])
         RUN = True
         STOP_IF_EXHAUSTED = False
         while RUN and (not STOP_IF_EXHAUSTED or len(sources) > 1):
             fds, fdo, fde = select.select(sources, [], [])
             for fd in fds:
                 if fd is self.__fdr:
                     cmd = os.read(self.__fdr, 1).decode(encoding='UTF-8')
                     if cmd == "X":
                         RUN = False
                         break
                     elif cmd == "B":
                         STOP_IF_EXHAUSTED = True
                     elif cmd == "A":
                         sources = self.active_sources - exhausted
                         sources.add(self.__fdr)
                     else:
                         warning(
                             "Unknown internal pipe engine command: %r. Ignoring."
                             % cmd)
                 elif fd in sources:
                     try:
                         fd.deliver()
                     except Exception as e:
                         log_interactive.exception(
                             "piping from %s failed: %s" % (fd.name, e))
                     else:
                         if fd.exhausted():
                             exhausted.add(fd)
                             sources.remove(fd)
     except KeyboardInterrupt:
         pass
     finally:
         try:
             for p in self.active_pipes:
                 p.stop()
         finally:
             self.thread_lock.release()
             log_interactive.info("Pipe engine thread stopped.")
Пример #15
0
 def run(self):
     log_interactive.info("Pipe engine thread started.")
     try:
         for p in self.active_pipes:
             p.start()
         sources = self.active_sources
         sources.add(self.__fdr)
         exhausted = set([])
         RUN=True
         STOP_IF_EXHAUSTED = False
         while RUN and (not STOP_IF_EXHAUSTED or len(sources) > 1):
             fds,fdo,fde=select.select(sources,[],[])
             for fd in fds:
                 if fd is self.__fdr:
                     cmd = os.read(self.__fdr,1).decode(encoding='UTF-8')
                     if cmd == "X":
                         RUN=False
                         break
                     elif cmd == "B":
                         STOP_IF_EXHAUSTED = True
                     elif cmd == "A":
                         sources = self.active_sources-exhausted
                         sources.add(self.__fdr)
                     else:
                         warning("Unknown internal pipe engine command: %r. Ignoring." % cmd)
                 elif fd in sources:
                     try:
                         fd.deliver()
                     except Exception as e:
                         log_interactive.exception("piping from %s failed: %s" % (fd.name, e))
                     else:
                         if fd.exhausted():
                             exhausted.add(fd)
                             sources.remove(fd)
     except KeyboardInterrupt:
         pass
     finally:
         try:
             for p in self.active_pipes:
                 p.stop()
         finally:
             self.thread_lock.release()
             log_interactive.info("Pipe engine thread stopped.")
Пример #16
0
    def recv(self, x=MTU):
        pkt, sa_ll = self.ins.recvfrom(x)
        if sa_ll[3] in conf.l2types :
            cls = conf.l2types[sa_ll[3]]
        elif sa_ll[1] in conf.l3types:
            cls = conf.l3types[sa_ll[1]]
        else:
            cls = conf.default_l2
            warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s" % (sa_ll[0],sa_ll[1],sa_ll[3],cls.name))

        try:
            pkt = cls(pkt)
        except KeyboardInterrupt:
            raise
        except:
            if conf.debug_dissector:
                raise
            pkt = conf.raw_layer(pkt)
        pkt.time = get_last_packet_timestamp(self.ins)
        return pkt
Пример #17
0
def p0f(pkt):
    """Passive OS fingerprinting: which OS emitted this TCP packet ?
p0f(packet) -> accuracy, [list of guesses]
"""
    db, sig = packet2p0f(pkt)
    if db:
        pb = db.get_base()
    else:
        pb = []
    if not pb:
        warning("p0f base empty.")
        return []
    #s = len(pb[0][0])
    r = []
    max = len(sig[4].split(",")) + 5
    for b in pb:
        d = p0f_correl(sig, b)
        if d == max:
            r.append((b[6], b[7], b[1] - pkt[IP].ttl))
    return r
Пример #18
0
def p0f(pkt):
    """Passive OS fingerprinting: which OS emitted this TCP packet ?
p0f(packet) -> accuracy, [list of guesses]
"""
    db, sig = packet2p0f(pkt)
    if db:
        pb = db.get_base()
    else:
        pb = []
    if not pb:
        warning("p0f base empty.")
        return []
    #s = len(pb[0][0])
    r = []
    max = len(sig[4].split(",")) + 5
    for b in pb:
        d = p0f_correl(sig,b)
        if d == max:
            r.append((b[6], b[7], b[1] - pkt[IP].ttl))
    return r
Пример #19
0
    def route(self,dest,verbose=None):
        if type(dest) is list and dest:
            dest = dest[0]
        if dest in self.cache:
            return self.cache[dest]
        if verbose is None:
            verbose=conf.verb
        # Transform "192.168.*.1-5" to one IP of the set
        dst = dest.split("/")[0]
        dst = dst.replace("*","0") 
        while True:
            l = dst.find("-")
            if l < 0:
                break
            m = (dst[l:]+".").find(".")
            dst = dst[:l]+dst[l+m:]

            
        dst = atol(dst)
        pathes=[]
        for d,m,gw,i,a in self.routes:
            aa = atol(a)
            #Commented out after issue with virtual network with local address 0.0.0.0
            #if aa == dst:
            #    pathes.append((0xffffffff,(LOOPBACK_NAME,a,"0.0.0.0")))
            if (dst & m) == (d & m):
                pathes.append((m,(i,a,gw)))
        if not pathes:
            if verbose:
                warning("No route found (no default route?)")
            return LOOPBACK_NAME,"0.0.0.0","0.0.0.0" #XXX linux specific!
        # Choose the more specific route (greatest netmask).
        # XXX: we don't care about metrics
        pathes.sort()
        ret = pathes[-1][1]
        self.cache[dest] = ret
        return ret
Пример #20
0
def read_routes():
    try:
        f=open("/proc/net/route","rb")
    except IOError:
        warning("Can't open /proc/net/route !")
        return []
    routes = []
    s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x",LOOPBACK_NAME.encode('utf-8')))
    addrfamily = struct.unpack("h",ifreq[16:18])[0]
    if addrfamily == socket.AF_INET:
        ifreq2 = ioctl(s, SIOCGIFNETMASK,struct.pack("16s16x",LOOPBACK_NAME.encode('utf-8')))
        msk = socket.ntohl(struct.unpack("I",ifreq2[20:24])[0])
        dst = socket.ntohl(struct.unpack("I",ifreq[20:24])[0]) & msk
        ifaddr = kamene.utils.inet_ntoa(ifreq[20:24])
        routes.append((dst, msk, "0.0.0.0", LOOPBACK_NAME, ifaddr))
    else:
        warning("Interface lo: unkown address family (%i)"% addrfamily)

    for l in f.readlines()[1:]:
        iff,dst,gw,flags,x,x,x,msk,x,x,x = l.split()
        flags = int(flags,16)
        if flags & RTF_UP == 0:
            continue
        if flags & RTF_REJECT:
            continue
        try:
            ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x",iff))
        except IOError: # interface is present in routing tables but does not have any assigned IP
            ifaddr="0.0.0.0"
        else:
            addrfamily = struct.unpack("h",ifreq[16:18])[0]
            if addrfamily == socket.AF_INET:
                ifaddr = kamene.utils.inet_ntoa(ifreq[20:24])
            else:
                warning("Interface %s: unkown address family (%i)"%(iff, addrfamily))
                continue
        routes.append((socket.htonl(int(dst,16))&0xffffffff,
                       socket.htonl(int(msk,16))&0xffffffff,
                       kamene.utils.inet_ntoa(struct.pack("I",int(gw,16))),
                       iff.decode('utf-8'), ifaddr))
    
    f.close()
    return routes
Пример #21
0
 def get_if_bcast(self, iff):
     for net, msk, gw, iface, addr in self.routes:
         if (iff == iface and net != 0):
             bcast = atol(addr)|(~msk&0xffffffff); # FIXME: check error in atol()
             return ltoa(bcast);
     warning("No broadcast address found for iface %s\n" % iff);
Пример #22
0
def p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None,
                    extrahops=0, mtu=1500, uptime=None):
    """Modifies pkt so that p0f will think it has been sent by a
specific OS.  If osdetails is None, then we randomly pick up a
personality matching osgenre. If osgenre and signature are also None,
we use a local signature (using p0f_getlocalsigs). If signature is
specified (as a tuple), we use the signature.

For now, only TCP Syn packets are supported.
Some specifications of the p0f.fp file are not (yet) implemented."""
    pkt = pkt.copy()
    #pkt = pkt.__class__(str(pkt))
    while pkt.haslayer(IP) and pkt.haslayer(TCP):
        pkt = pkt.getlayer(IP)
        if isinstance(pkt.payload, TCP):
            break
        pkt = pkt.payload
    
    if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
        raise TypeError("Not a TCP/IP packet")
    
    if uptime is None:
        uptime = random.randint(120,100*60*60*24*365)
    
    db = p0f_selectdb(pkt.payload.flags)
    if osgenre:
        pb = db.get_base()
        if pb is None:
            pb = []
        #pb = filter(lambda x: x[6] == osgenre, pb)
        pb = [ x for x in pb if x[6] == osgenre ]
        if osdetails:
            #pb = filter(lambda x: x[7] == osdetails, pb)
            pb = [ x for x in pb if x[7] == osdetails ]
    elif signature:
        pb = [signature]
    else:
        pb = p0f_getlocalsigs()[db]
    if db == p0fr_kdb:
        # 'K' quirk <=> RST+ACK
        if pkt.payload.flags & 0x4 == 0x4:
            #pb = filter(lambda x: 'K' in x[5], pb)
            pb = [ x for x in pb if 'K' in x[5] ]
        else:
            #pb = filter(lambda x: 'K' not in x[5], pb)
            pb = [ x for x in pb if 'K' not in x[5] ]
    if not pb:
        raise Kamene_Exception("No match in the p0f database")
    pers = pb[random.randint(0, len(pb) - 1)]
    
    # options (we start with options because of MSS)
    ## TODO: let the options already set if they are valid
    options = []
    if pers[4] != '.':
        for opt in pers[4].split(','):
            if opt[0] == 'M':
                # MSS might have a maximum size because of window size
                # specification
                if pers[0][0] == 'S':
                    maxmss = (2**16-1) / int(pers[0][1:])
                else:
                    maxmss = (2**16-1)
                # If we have to randomly pick up a value, we cannot use
                # kamene RandXXX() functions, because the value has to be
                # set in case we need it for the window size value. That's
                # why we use random.randint()
                if opt[1:] == '*':
                    options.append(('MSS', random.randint(1,maxmss)))
                elif opt[1] == '%':
                    coef = int(opt[2:])
                    options.append(('MSS', coef*random.randint(1,maxmss/coef)))
                else:
                    options.append(('MSS', int(opt[1:])))
            elif opt[0] == 'W':
                if opt[1:] == '*':
                    options.append(('WScale', RandByte()))
                elif opt[1] == '%':
                    coef = int(opt[2:])
                    options.append(('WScale', coef*RandNum(min=1,
                                                           max=(2**8-1)/coef)))
                else:
                    options.append(('WScale', int(opt[1:])))
            elif opt == 'T0':
                options.append(('Timestamp', (0, 0)))
            elif opt == 'T':
                if 'T' in pers[5]:
                    # FIXME: RandInt() here does not work (bug (?) in
                    # TCPOptionsField.m2i often raises "OverflowError:
                    # long int too large to convert to int" in:
                    #    oval = struct.pack(ofmt, *oval)"
                    # Actually, this is enough to often raise the error:
                    #    struct.pack('I', RandInt())
                    options.append(('Timestamp', (uptime, random.randint(1,2**32-1))))
                else:
                    options.append(('Timestamp', (uptime, 0)))
            elif opt == 'S':
                options.append(('SAckOK', ''))
            elif opt == 'N':
                options.append(('NOP', None))
            elif opt == 'E':
                options.append(('EOL', None))
            elif opt[0] == '?':
                if int(opt[1:]) in TCPOptions[0]:
                    optname = TCPOptions[0][int(opt[1:])][0]
                    optstruct = TCPOptions[0][int(opt[1:])][1]
                    options.append((optname,
                                    struct.unpack(optstruct,
                                                  RandString(struct.calcsize(optstruct))._fix())))
                else:
                    options.append((int(opt[1:]), ''))
            ## FIXME: qqP not handled
            else:
                warning("unhandled TCP option " + opt)
            pkt.payload.options = options
    
    # window size
    if pers[0] == '*':
        pkt.payload.window = RandShort()
    elif pers[0].isdigit():
        pkt.payload.window = int(pers[0])
    elif pers[0][0] == '%':
        coef = int(pers[0][1:])
        pkt.payload.window = coef * RandNum(min=1,max=(2**16-1)/coef)
    elif pers[0][0] == 'T':
        pkt.payload.window = mtu * int(pers[0][1:])
    elif pers[0][0] == 'S':
        ## needs MSS set
        #MSS = filter(lambda x: x[0] == 'MSS', options)
        MSS = [ x for x in options if x[0] == 'MSS' ]
        if not MSS:
            raise Kamene_Exception("TCP window value requires MSS, and MSS option not set")
        pkt.payload.window = MSS[0][1] * int(pers[0][1:])
    else:
        raise Kamene_Exception('Unhandled window size specification')
    
    # ttl
    pkt.ttl = pers[1]-extrahops
    # DF flag
    pkt.flags |= (2 * pers[2])
    ## FIXME: ss (packet size) not handled (how ? may be with D quirk
    ## if present)
    # Quirks
    if pers[5] != '.':
        for qq in pers[5]:
            ## FIXME: not handled: P, I, X, !
            # T handled with the Timestamp option
            if qq == 'Z': pkt.id = 0
            elif qq == 'U': pkt.payload.urgptr = RandShort()
            elif qq == 'A': pkt.payload.ack = RandInt()
            elif qq == 'F':
                #if db == p0fo_kdb:
                #    pkt.payload.flags |= 0x20 # U
                #else:
                    pkt.payload.flags |= RandChoice(8, 32, 40) #P / U / PU
            elif qq == 'D' and db != p0fo_kdb:
                pkt /= conf.raw_layer(load=RandString(random.randint(1, 10))) # XXX p0fo.fp
            elif qq == 'Q': pkt.payload.seq = pkt.payload.ack
            #elif qq == '0': pkt.payload.seq = 0
        #if db == p0fr_kdb:
        # '0' quirk is actually not only for p0fr.fp (see
        # packet2p0f())
    if '0' in pers[5]:
        pkt.payload.seq = 0
    elif pkt.payload.seq == 0:
        pkt.payload.seq = RandInt()
    
    while pkt.underlayer:
        pkt = pkt.underlayer
    return pkt
Пример #23
0
def read_routes():
    if kamene.arch.SOLARIS:
        f = check_output(["netstat", "-rvn"],
                         universal_newlines=True)  # -f inet
    elif kamene.arch.FREEBSD:
        f = check_output(
            ["netstat", "-rnW"],
            universal_newlines=True)  # -W to handle long interface names
    else:
        f = check_output(["netstat", "-rn"],
                         universal_newlines=True)  # -f inet
    ok = False
    routes = []
    pending_if = []
    for l in f.split('\n'):
        l = l.strip()
        if l.find("----") >= 0:  # a separation line
            continue
        if not ok:
            if_index = [
                l.split().index(i)
                for i in ['Iface', 'Netif', 'Interface', 'Device']
                if i in l.split()
            ]
            if if_index:
                ok = True
                if_index = if_index[0]
            continue
        if not l:
            break
        if kamene.arch.SOLARIS:
            lspl = l.split()
            if len(lspl) == 10:
                dest, mask, gw, netif, mxfrg, rtt, ref, flg = lspl[:8]
            else:  # missing interface
                dest, mask, gw, mxfrg, rtt, ref, flg = lspl[:7]
                netif = None
        else:
            rt = l.split()
            dest, gw, flg = rt[:3]
            netif = rt[if_index]
        if flg.find("Lc") >= 0:
            continue
        if dest == "default":
            dest = 0
            netmask = 0
        else:
            if kamene.arch.SOLARIS:
                netmask = kamene.utils.atol(mask)
            elif "/" in dest:
                dest, netmask = dest.split("/")
                netmask = kamene.utils.itom(int(netmask))
            else:
                netmask = kamene.utils.itom((dest.count(".") + 1) * 8)
            dest += ".0" * (3 - dest.count("."))
            dest = kamene.utils.atol(dest)
        if not "G" in flg:
            gw = '0.0.0.0'
        if netif is not None:
            ifaddr = kamene.arch.get_if_addr(netif)
            routes.append((dest, netmask, gw, netif, ifaddr))
        else:
            pending_if.append((dest, netmask, gw))

    # On Solaris, netstat does not provide output interfaces for some routes
    # We need to parse completely the routing table to route their gw and
    # know their output interface
    for dest, netmask, gw in pending_if:
        gw_l = kamene.utils.atol(gw)
        max_rtmask, gw_if, gw_if_addr, = 0, None, None
        for rtdst, rtmask, _, rtif, rtaddr in routes[:]:
            if gw_l & rtmask == rtdst:
                if rtmask >= max_rtmask:
                    max_rtmask = rtmask
                    gw_if = rtif
                    gw_if_addr = rtaddr
        if gw_if:
            routes.append((dest, netmask, gw, gw_if, gw_if_addr))
        else:
            warning("Did not find output interface to reach gateway %s" % gw)

    return routes
Пример #24
0
def p0f_impersonate(pkt,
                    osgenre=None,
                    osdetails=None,
                    signature=None,
                    extrahops=0,
                    mtu=1500,
                    uptime=None):
    """Modifies pkt so that p0f will think it has been sent by a
specific OS.  If osdetails is None, then we randomly pick up a
personality matching osgenre. If osgenre and signature are also None,
we use a local signature (using p0f_getlocalsigs). If signature is
specified (as a tuple), we use the signature.

For now, only TCP Syn packets are supported.
Some specifications of the p0f.fp file are not (yet) implemented."""
    pkt = pkt.copy()
    #pkt = pkt.__class__(str(pkt))
    while pkt.haslayer(IP) and pkt.haslayer(TCP):
        pkt = pkt.getlayer(IP)
        if isinstance(pkt.payload, TCP):
            break
        pkt = pkt.payload

    if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
        raise TypeError("Not a TCP/IP packet")

    if uptime is None:
        uptime = random.randint(120, 100 * 60 * 60 * 24 * 365)

    db = p0f_selectdb(pkt.payload.flags)
    if osgenre:
        pb = db.get_base()
        if pb is None:
            pb = []
        #pb = filter(lambda x: x[6] == osgenre, pb)
        pb = [x for x in pb if x[6] == osgenre]
        if osdetails:
            #pb = filter(lambda x: x[7] == osdetails, pb)
            pb = [x for x in pb if x[7] == osdetails]
    elif signature:
        pb = [signature]
    else:
        pb = p0f_getlocalsigs()[db]
    if db == p0fr_kdb:
        # 'K' quirk <=> RST+ACK
        if pkt.payload.flags & 0x4 == 0x4:
            #pb = filter(lambda x: 'K' in x[5], pb)
            pb = [x for x in pb if 'K' in x[5]]
        else:
            #pb = filter(lambda x: 'K' not in x[5], pb)
            pb = [x for x in pb if 'K' not in x[5]]
    if not pb:
        raise Kamene_Exception("No match in the p0f database")
    pers = pb[random.randint(0, len(pb) - 1)]

    # options (we start with options because of MSS)
    ## TODO: let the options already set if they are valid
    options = []
    if pers[4] != '.':
        for opt in pers[4].split(','):
            if opt[0] == 'M':
                # MSS might have a maximum size because of window size
                # specification
                if pers[0][0] == 'S':
                    maxmss = (2**16 - 1) / int(pers[0][1:])
                else:
                    maxmss = (2**16 - 1)
                # If we have to randomly pick up a value, we cannot use
                # kamene RandXXX() functions, because the value has to be
                # set in case we need it for the window size value. That's
                # why we use random.randint()
                if opt[1:] == '*':
                    options.append(('MSS', random.randint(1, maxmss)))
                elif opt[1] == '%':
                    coef = int(opt[2:])
                    options.append(
                        ('MSS', coef * random.randint(1, maxmss / coef)))
                else:
                    options.append(('MSS', int(opt[1:])))
            elif opt[0] == 'W':
                if opt[1:] == '*':
                    options.append(('WScale', RandByte()))
                elif opt[1] == '%':
                    coef = int(opt[2:])
                    options.append(
                        ('WScale',
                         coef * RandNum(min=1, max=(2**8 - 1) / coef)))
                else:
                    options.append(('WScale', int(opt[1:])))
            elif opt == 'T0':
                options.append(('Timestamp', (0, 0)))
            elif opt == 'T':
                if 'T' in pers[5]:
                    # FIXME: RandInt() here does not work (bug (?) in
                    # TCPOptionsField.m2i often raises "OverflowError:
                    # long int too large to convert to int" in:
                    #    oval = struct.pack(ofmt, *oval)"
                    # Actually, this is enough to often raise the error:
                    #    struct.pack('I', RandInt())
                    options.append(
                        ('Timestamp', (uptime, random.randint(1, 2**32 - 1))))
                else:
                    options.append(('Timestamp', (uptime, 0)))
            elif opt == 'S':
                options.append(('SAckOK', ''))
            elif opt == 'N':
                options.append(('NOP', None))
            elif opt == 'E':
                options.append(('EOL', None))
            elif opt[0] == '?':
                if int(opt[1:]) in TCPOptions[0]:
                    optname = TCPOptions[0][int(opt[1:])][0]
                    optstruct = TCPOptions[0][int(opt[1:])][1]
                    options.append(
                        (optname,
                         struct.unpack(
                             optstruct,
                             RandString(struct.calcsize(optstruct))._fix())))
                else:
                    options.append((int(opt[1:]), ''))
            ## FIXME: qqP not handled
            else:
                warning("unhandled TCP option " + opt)
            pkt.payload.options = options

    # window size
    if pers[0] == '*':
        pkt.payload.window = RandShort()
    elif pers[0].isdigit():
        pkt.payload.window = int(pers[0])
    elif pers[0][0] == '%':
        coef = int(pers[0][1:])
        pkt.payload.window = coef * RandNum(min=1, max=(2**16 - 1) / coef)
    elif pers[0][0] == 'T':
        pkt.payload.window = mtu * int(pers[0][1:])
    elif pers[0][0] == 'S':
        ## needs MSS set
        #MSS = filter(lambda x: x[0] == 'MSS', options)
        MSS = [x for x in options if x[0] == 'MSS']
        if not MSS:
            raise Kamene_Exception(
                "TCP window value requires MSS, and MSS option not set")
        pkt.payload.window = MSS[0][1] * int(pers[0][1:])
    else:
        raise Kamene_Exception('Unhandled window size specification')

    # ttl
    pkt.ttl = pers[1] - extrahops
    # DF flag
    pkt.flags |= (2 * pers[2])
    ## FIXME: ss (packet size) not handled (how ? may be with D quirk
    ## if present)
    # Quirks
    if pers[5] != '.':
        for qq in pers[5]:
            ## FIXME: not handled: P, I, X, !
            # T handled with the Timestamp option
            if qq == 'Z': pkt.id = 0
            elif qq == 'U': pkt.payload.urgptr = RandShort()
            elif qq == 'A': pkt.payload.ack = RandInt()
            elif qq == 'F':
                #if db == p0fo_kdb:
                #    pkt.payload.flags |= 0x20 # U
                #else:
                pkt.payload.flags |= RandChoice(8, 32, 40)  #P / U / PU
            elif qq == 'D' and db != p0fo_kdb:
                pkt /= conf.raw_layer(load=RandString(random.randint(
                    1, 10)))  # XXX p0fo.fp
            elif qq == 'Q':
                pkt.payload.seq = pkt.payload.ack
            #elif qq == '0': pkt.payload.seq = 0
        #if db == p0fr_kdb:
        # '0' quirk is actually not only for p0fr.fp (see
        # packet2p0f())
    if '0' in pers[5]:
        pkt.payload.seq = 0
    elif pkt.payload.seq == 0:
        pkt.payload.seq = RandInt()

    while pkt.underlayer:
        pkt = pkt.underlayer
    return pkt
Пример #25
0
 def start(self):
     if self.thread_lock.acquire(0):
         self.threadid = _thread.start_new_thread(self.run,())
     else:
         warning("Pipe engine already running")
Пример #26
0
def read_routes():
    if kamene.arch.SOLARIS:
        f=check_output(["netstat", "-rvn"], universal_newlines = True) # -f inet
    elif kamene.arch.FREEBSD:
        f=check_output(["netstat", "-rnW"], universal_newlines = True) # -W to handle long interface names
    else:
        f=check_output(["netstat", "-rn"], universal_newlines = True) # -f inet
    ok = False
    routes = []
    pending_if = []
    for l in f.split('\n'):
        l = l.strip()
        if l.find("----") >= 0: # a separation line
            continue
        if not ok:
            if_index = [ l.split().index(i) for i in ['Iface', 'Netif', 'Interface', 'Device'] if i in l.split()]
            if if_index:
                ok = True
                if_index = if_index[0]
            continue
        if not l:
            break
        if kamene.arch.SOLARIS:
            lspl = l.split()
            if len(lspl) == 10:
                dest,mask,gw,netif,mxfrg,rtt,ref,flg = lspl[:8]
            else: # missing interface
                dest,mask,gw,mxfrg,rtt,ref,flg = lspl[:7]
                netif=None
        else:
            rt = l.split()
            dest,gw,flg = rt[:3]
            netif = rt[if_index]
        if flg.find("Lc") >= 0:
            continue                
        if dest == "default":
            dest = 0
            netmask = 0
        else:
            if kamene.arch.SOLARIS:
                netmask = kamene.utils.atol(mask)
            elif "/" in dest:
                dest,netmask = dest.split("/")
                netmask = kamene.utils.itom(int(netmask))
            else:
                netmask = kamene.utils.itom((dest.count(".") + 1) * 8)
            dest += ".0"*(3-dest.count("."))
            dest = kamene.utils.atol(dest)
        if not "G" in flg:
            gw = '0.0.0.0'
        if netif is not None:
            ifaddr = kamene.arch.get_if_addr(netif)
            routes.append((dest,netmask,gw,netif,ifaddr))
        else:
            pending_if.append((dest,netmask,gw))

    # On Solaris, netstat does not provide output interfaces for some routes
    # We need to parse completely the routing table to route their gw and
    # know their output interface
    for dest,netmask,gw in pending_if:
        gw_l = kamene.utils.atol(gw)
        max_rtmask,gw_if,gw_if_addr, = 0,None,None
        for rtdst,rtmask,_,rtif,rtaddr in routes[:]:
            if gw_l & rtmask == rtdst:
                if rtmask >= max_rtmask:
                    max_rtmask = rtmask
                    gw_if = rtif
                    gw_if_addr = rtaddr
        if gw_if:
            routes.append((dest,netmask,gw,gw_if,gw_if_addr))
        else:
            warning("Did not find output interface to reach gateway %s" % gw)
            
    return routes
Пример #27
0
 def start(self):
     if self.thread_lock.acquire(0):
         self.threadid = _thread.start_new_thread(self.run, ())
     else:
         warning("Pipe engine already running")