def sendSYN(self, target, ethhead): """Method sending a given SYN packet to target. The SYN packet will be changed to not support TCPOPT_TIMESTAMP. """ eth = ethhead iphead = eth.child() tcphead = iphead.child() if target == TCPConnection.TAIL: out = TCPConnection.alt_stdout host = self.head # target == Connection.HEAD else: out = TCPConnection.stdout host = self.tail nop = ImpactPacket.TCPOption(ImpactPacket.TCPOption.TCPOPT_NOP) # If there is a Maximum Segment Size (MSS) give, we need to set it as # the upper threshold for the packet size. for option in tcphead.get_options(): if option.get_kind() == ImpactPacket.TCPOption.TCPOPT_MAXSEG: host.mss = option.get_mss() # We need to check the availiable options and only delete all # non MSS options. (TODO: Very bad practice. Do this properly!!) i = 0 for option in tcphead.get_options(): if option.get_kind() != ImpactPacket.TCPOption.TCPOPT_MAXSEG: # Bad practice, but seems like the only possible way. tcphead._TCP__option_list[i] = nop i += 1 # Recalculate the ipheader length iphead.set_ip_len(0) packet = encode(eth) if s.verbosity > 9: s.logfile.write("Syn packet sent: " + str(eth) + "\n") send(target, self, packet)
def build_reply(self, packet, path, personality, cb_ip_id, cb_tcp_seq, cb_tcp_ts): """Function creates a reply according to the personality of the device Args: packet : intercepted packet path : length of path in the virtual network personality : personality description of the device cb_ipid, cb_tcp_seq, cb_tcp_ts : callback functions for IP ID, TCP SEQ and TCP TS generation Return reply ip packet """ # fingerprint fields R, DF, T, TG, W, S, A, F, O, RD, Q & CC # tcp packet tcp_pkt = packet.child() reply_tcp = ImpactPacket.TCP() reply_tcp.set_th_sport(tcp_pkt.get_th_dport()) reply_tcp.set_th_dport(tcp_pkt.get_th_sport()) reply_tcp.set_th_flags(0) reply_tcp.auto_checksum = 1 # ip packet reply_ip = ImpactPacket.IP() reply_ip.set_ip_v(4) reply_ip.set_ip_p(6) reply_ip.set_ip_rf(False) reply_ip.set_ip_df(False) reply_ip.set_ip_mf(False) reply_ip.set_ip_src(packet.get_ip_dst()) reply_ip.set_ip_dst(packet.get_ip_src()) reply_ip.set_ip_id(cb_ip_id()) reply_ip.auto_checksum = 1 # check DF if 'DF' in personality: if personality['DF'] == 'N': reply_ip.set_ip_df(False) elif personality['DF'] == 'Y': reply_ip.set_ip_df(True) else: raise Exception('Unsupported Ti:DF=%s', personality['DF']) # check T ttl = 0x7f if 'T' in personality: try: ttl = personality['T'].split('-') # using minimum ttl ttl = int(ttl[0], 16) except BaseException: raise Exception('Unsupported Ti:T=%s', personality['T']) # check TG if 'TG' in personality: try: ttl = int(personality['TG'], 16) except BaseException: raise Exception('Unsupported Ti:TG=%s', personality['TG']) delta_ttl = ttl - path if delta_ttl < 1: logger.debug('Reply packet dropped: TTL reached 0 within virtual network.') return None reply_ip.set_ip_ttl(delta_ttl) # check W win = 0 if 'W' in personality: try: win = int(personality['W'], 16) except BaseException: raise Exception('Unsupported Ti:W=%s', personality['W']) reply_tcp.set_th_win(win) # check CC if 'CC' in personality: if personality['CC'] == 'N': reply_tcp.reset_ECE() reply_tcp.reset_CWR() elif personality['CC'] == 'Y': reply_tcp.set_ECE() reply_tcp.reset_CWR() elif personality['CC'] == 'S': reply_tcp.set_ECE() reply_tcp.set_CWR() elif personality['CC'] == 'O': reply_tcp.reset_ECE() reply_tcp.set_CWR() # check S if 'S' in personality: if personality['S'] == 'Z': reply_tcp.set_th_seq(0) elif personality['S'] == 'A': reply_tcp.set_th_seq(tcp_pkt.get_th_ack()) elif personality['S'] == 'A+': reply_tcp.set_th_seq(tcp_pkt.get_th_ack() + 1) elif personality['S'] == 'O': seq = cb_tcp_seq() reply_tcp.set_th_seq(seq) else: raise Exception('Unsupported Ti:S=%s', personality['S']) # check A if 'A' in personality: if personality['A'] == 'Z': reply_tcp.set_th_ack(0) elif personality['A'] == 'S': reply_tcp.set_th_ack(tcp_pkt.get_th_seq()) elif personality['A'] == 'S+': reply_tcp.set_th_ack(tcp_pkt.get_th_seq() + 1) elif personality['A'] == 'O': temp = random.randint(1, 10) reply_tcp.set_th_ack(temp) else: try: temp = int(personality['A'], 16) reply_tcp.set_th_ack(temp) except BaseException: raise Exception('Unsupported Ti:A=%s', personality['A']) # check O if 'O' in personality: options = personality['O'] i = 0 while i < len(options): opt = options[i] i += 1 if opt == 'L': reply_tcp.add_option(ImpactPacket.TCPOption(ImpactPacket.TCPOption.TCPOPT_EOL)) if opt == 'N': reply_tcp.add_option(ImpactPacket.TCPOption(ImpactPacket.TCPOption.TCPOPT_NOP)) if opt == 'S': reply_tcp.add_option(ImpactPacket.TCPOption(ImpactPacket.TCPOption.TCPOPT_SACK_PERMITTED)) if opt == 'T': opt = ImpactPacket.TCPOption(ImpactPacket.TCPOption.TCPOPT_TIMESTAMP) if options[i] == '1': ts = cb_tcp_ts() opt.set_ts(ts) if options[i + 1] == '1': opt.set_ts_echo(0xffffffff) reply_tcp.add_option(opt) i += 2 if opt == 'M': maxseg, i = self.get_value(options, i) reply_tcp.add_option(ImpactPacket.TCPOption(ImpactPacket.TCPOption.TCPOPT_MAXSEG, maxseg)) if opt == 'W': window, i = self.get_value(options, i) reply_tcp.add_option(ImpactPacket.TCPOption(ImpactPacket.TCPOption.TCPOPT_WINDOW, window)) # check F if 'F' in personality: if 'E' in personality['F']: reply_tcp.set_ECE() if 'U' in personality['F']: reply_tcp.set_URG() if 'A' in personality['F']: reply_tcp.set_ACK() if 'P' in personality['F']: reply_tcp.set_PSH() if 'R' in personality['F']: reply_tcp.set_RST() if 'S' in personality['F']: reply_tcp.set_SYN() if 'F' in personality['F']: reply_tcp.set_FIN() # check Q if 'Q' in personality: if 'R' in personality['Q']: reply_tcp.set_flags(0x800) if 'U' in personality['Q']: reply_tcp.set_th_urp(0xffff) # check RD if 'RD' in personality: try: crc = int(personality['RD'], 16) if crc != 0: data = 'TCP Port is closed\x00' data += self.compensate(data, crc) pkt_data = ImpactPacket.Data(data) reply_tcp.contains(pkt_data) except BaseException: raise Exception('Unsupported Ti:RD=%s', personality['RD']) reply_tcp.calculate_checksum() reply_ip.contains(reply_tcp) return reply_ip