ICMP python上格式错误的数据包

时间:2013-11-12 03:51:55

标签: python checksum packet icmp malformed

我如何创建一个框架icmp 我在python上标记malformet数据包

  1. 导入socket,struct,uuid,subprocess,fcntl,time,random

  2. 列出项目

  3. from binascii import hexlify,unhexlify from datetime import datetime     tarRed = raw_input('Ingrese nombre de Tarjeta de Red Utilizada:')     subprocess.call(['ifconfig',tarRed,'promisc'])pt = 0x0800 s =     socket.socket(socket.AF_PACKET,socket.SOCK_RAW,socket.htons(pt))     s.bind((tarRed,pt))     #GETCheck def getchecksum(ip_header,size):cksum = 0 pointer = 0而size> 1:cksum + = int((str(“%02x”%(ip_header [pointer],))     + str(“%02x”%(ip_header [pointer + 1],))),16)size - = 2指针+ = 2 #if size:#This表示标题为奇数的情况             #cksum + = int(ip_header [pointer])cksum =(cksum>> 16)+     (cksum& 0xffff)cksum + =(cksum>> 16)return(~cksum)&     0xFFFF def _checksum(data):#计算头总和         ip_header_sum = sum(struct.unpack_from(“6H”,data))#add carry         ip_header_sum =(ip_header_sum& 0xFFFF)+(ip_header_sum>> 8&     0xFFFF)ip_header_sum = ~ip_header_sum& 0xFFFF返回     ip_header_sum def i_checksum(checksum_packet):total = 0 num_words     = len(checksum_packet)/ 2表示struct.unpack中的块(“!%sH”%num_words,checksum_packet [0:num_words * 2]):total + = chunk if     len(checksum_packet)%2:total + = ord(checksum_packet [-1])<< 8         总计+ =总计>> 16返回(~total + 0xffff& 0xffff)

    def checksum(source_string):    sum = 0     countTo =
    (len(source_string)/2)*2    count = 0   while count<countTo:
                thisVal = ord(source_string[count + 1])*256 + ord(source_string[count])         sum = sum + thisVal         sum = sum &
    0xffffffff
                count = count + 2   if countTo<len(source_string):      sum = sum + ord(source_string[len(source_string) - 1])      sum = sum &
    0xffffffff  sum = (sum >> 16)  +  (sum & 0xffff)    sum = sum + (sum
    >> 16)  answer = ~sum   answer = answer & 0xffff    #answer = answer >> 8 | (answer << 8 & 0xff00)  return answer def
    checksuma(source_string):   sum = 0     countTo =
    (len(source_string)/2)*2    count = 0   while count<countTo:
                thisVal = ord(source_string[count + 1])*256 + ord(source_string[count])         sum = sum + thisVal         sum = sum &
    0xffffffff
                count = count + 2   if countTo<len(source_string):      sum = sum + ord(source_string[len(source_string) - 1])      sum = sum &
    0xffffffff  sum = (sum >> 16)  +  (sum & 0xffff)    sum = sum + (sum
    >> 16)  answer = ~sum   answer = answer & 0xffff    answer = answer >> 8 | (answer << 8 & 0xff00)   return answer def ultimo(str):
        csum = 0
        countTo = (len(str) / 2) * 2
        count = 0
    
        while count < countTo:
            thisVal = ord(str[count+1]) * 256 + ord(str[count])
            csum = csum + thisVal
            csum = csum & 0xffffffff
            count = count + 2
    
        if countTo < len(str):
            csum = csum + ord(str[len(str) - 1])
            csum = csum & 0xffffffff
    
        csum = (csum >> 16) + (csum & 0xffff)
        csum = csum + (csum >> 16)
        answer = ~csum
        answer = answer & 0xffff
        answer = answer >> 8 | (answer << 8 & 0xff00)
        return answer
    #GETCheck
    #MACs adst='ffffffffffff' mac_destino = unhexlify(adst) ma = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) info =
    fcntl.ioctl(ma.fileno(), 0x8927,  struct.pack('256s', tarRed[:15]))
    asrc = ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]
    sd = asrc.split(':') asrc = sd[0]+sd[1]+sd[2]+sd[3]+sd[4]+sd[5]
    mac_origen = unhexlify(asrc)
    #MACs cabEther = struct.pack('!6s6sh',mac_destino,mac_origen,pt)
    #datosIP
    #version = '4'
    #IHL = '5' tipoServicio = unhexlify('00') longitudT = struct.pack('!BB',00,24) identificador = struct.pack('!BB',00,01)
    flag_Pos = 0x4000 tiempoVida = 05 ptIP = unhexlify('01') SCC = 0
    #IPs ip = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) ipO= str( socket.inet_ntoa(fcntl.ioctl(ip.fileno(),0x8915,struct.pack('256s',
    tarRed[:15]))[20:24])) ipO1 = ipO.split('.') ipOr =
    struct.pack("!BBBB",int(ipO1[0]),int(ipO1[1]),int(ipO1[2]),int(ipO1[3]))
    ipD = raw_input('Ingrese la direccion IP destino:  ') ipD1 =
    ipD.split('.') ipDest =
    struct.pack("!BBBB",int(ipD1[0]),int(ipD1[1]),int(ipD1[2]),int(ipD1[3]))
    #IPs
    #datosIP cabIP = struct.pack('!1s1s2s2shB1sH4s4s',unhexlify('45'),tipoServicio,longitudT,identificador,flag_Pos,tiempoVida,ptIP,SCC,ipOr,ipDest)
    SCC = checksum(cabIP) cabIP =
    struct.pack('!1s1s2s2shB1sH4s4s',unhexlify('45'),tipoServicio,longitudT,identificador,flag_Pos,tiempoVida,ptIP,socket.htons(SCC),ipOr,ipDest)
    #datosIcmp tipo = 8 codigo = 0x00 check = 0x0000 identificador = int((id(1) * random.random()) % 65535) secuencia = 0x0000
    #datos = 'qwertyasdfghzxcvbn0102030405060708091011121314151617181920' datos =
    1 * 'Q'
    #datosIcmp cabIcmp = struct.pack('!bbHHh',tipo,0,0,identificador,1) my_checksum = ultimo(cabIcmp + datos) cabIcmp =
    struct.pack('!bbHHh',tipo,0,socket.htons(my_checksum),identificador,1)
    cabIcmp = cabIcmp + datos tiempo = datetime.now() print tiempo for i
    in range(15):   s.send(cabEther + cabIP + cabIcmp,0)
    

1 个答案:

答案 0 :(得分:3)

你的问题几乎无法理解。您似乎在询问如何创建ICMP ECHO数据包,因为您在列出的代码中创建的数据包被系统报告为格式错误。我会尝试回答为什么你的代码不起作用。

首先,您使用的套接字类型不正确。您需要输入类型1,而不是8.这可以通过第三个参数轻松完成:

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)

(请注意,您需要root或管理员权限才能进行此次调用。)

其次,在创建套接字后,您需要创建ICMP标头。 ICMP标头由以下结构组成:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 0 |     Type      |     Code      |          Checksum             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 4 |                         REST OF HEADER                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

注意第二个四个字节“REST OF HEADER”。第二组四个字节取决于前两个字节中的TYPE / CODE。例如,如果TYPE为0且CODE为0,则表示您正在处理回复应答,因此,后四个字节将变为2字节标识符和2字节<强>序列号字段,从偏移量4开始,到偏移量7结束,如图所示:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 0 |     Type      |     Code      |          Checksum             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 4 |           Identifier          |        Sequence Number        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 8 |     Data ...
   +-+-+-+-+-

要创建此标头,我将使用类型8,即回声请求结构(请注意,此创建中的字节4-5和6-7仅用于说明,通常这将是不同的值其他比零):

icmp = struct.pack(">BBHHH", 8, 0, 0, 0, 0)

在头的初始创建时,校验和为零。我们现在需要的是实际计算校验和(使用此零值),然后使用这个新的校验和值重新创建标头:

icmp = struct.pack(">BBHHH", 8, 0, cksum(icmp), 0, 0)

但这是你的代码再次错误的地方。 i_checksum()的实施是错误的。为了解决问题,我会留给你解决它。校验和称为1的补码,有很多关于它的在线文章,以及实现它的Linux系统上的C代码。

一旦你有了标题及其正确的校验和(很重要,因为你的系统不会发送数据包,如果不正确),你只需将它发送到某个地方:

s.sendto(icmp, (SOME_REMOTE_HOST, 0))

然后收到回复,如果有的话:

s.recvfrom(1500)

(注意我选择1500字节,因为那是IP帧的MTU,因此答案不可能大于此,尽管它肯定是可能的。)

并且在这一点上,你的代码完全失败 - 仅仅是因为你没有代码执行最后两个步骤,更不用说其他代码来处理如何处理回复和结构解析标题字段。

至于你定义的其他两个功能,它们很奇怪。其中一个似乎暗示它正在处理链接层字段 - 套接字从来就不是这样,因为套接字只处理IP层及以上 - 而另一个似乎是计算校验和的尝试...虽然不正确(再次)。

简而言之,正如 abarnert 所暗示的那样,请澄清(并添加更多)代码和您的问题。