# rawsock.py # python raw socket sample, (c) awarenetwork.org # only works with the raw socket patch and only # on windows 2003 server edition or other windows # Versions that support raw sockets. from types import * from socket import * from struct import * from random import randrange as Random FIN = 0x01 SYN = 0x02 RST = 0x04 PSH = 0x08 ACK = 0x10 URG = 0x20 PCK_TCP = "!HHLLBBHHH" PCK_PSEUDO = "!LLxBH" PCK_IP4 = "!BxHHHBBHLL" PCK_ICMP = "!BBHL" # IP Version 4 declarations PRE_ROUTINE = 0x0 PRE_PRIORITY = 0x1 PRE_IMMEDIATE = 0x2 PRE_FLASH = 0x3 PRE_FLASH_OVERRIDE = 0x4 PRE_CRITICAL = 0x5 PRE_INTERNETWORK = 0x6 PRE_NETWORK_CONTROL = 0x7 TOS_DEFAULT = 0x0 TOS_MONETARY = 0x1 TOS_RELIABILITY = 0x2 TOS_THROUGHPUT = 0x4 TOS_DELAY = 0x8 TOS_SECURITY = 0xF def dbg_if_types(): for i in globals().keys(): if (str(i)[0:4]=="IFF_"): print str(i).ljust(20),":",str(globals()[i]).rjust(2) def dbg_if_info(t): if (IsPPP(t)): print "this is a PPP interface." elif (IsLoopback(t)): print "this is a loopback interface." else: print "this is an ethernet interface" def IsEthernet(interface): return not IsPPP(interface) and not IsLoopback(interface) def IsPPP(interface): return (interface&IFF_POINTTOPOINT!=0) def IsLoopback(interface): return (interface&IFF_LOOPBACK!=0) def EnsureInt(c): if (type(c)==StringType): return ord(c[0]) else: return int(c) def checksum(buffer): chk = 0; iter = 0 while (iter <= (len(buffer)-2)): chk += EnsureInt(buffer[iter]) << 8 chk += EnsureInt(buffer[iter+1]) iter += 2 if (iter!=len(buffer)): chk += EnsureInt(buffer[iter]) chk = (chk>>0x10)+(chk&0xFFFF) chk += (chk>>0x10) return ((~chk)&0xFFFF); def HexStr(s,o=8,p=True): s = str(s) ret = "" prn = "\t" for i in xrange(len(s)): chr = ord(s[i]) h = hex(chr)[2:].upper() if (len(h)==1): h = "0"+h ret += h+" " if (chr>=0x20)and(chr<=0x7E): prn+=s[i] else: prn += '.' if not (i+1) % o: if (p): ret += prn ret += "\n"; prn = "\t" if prn: ret += " " * ((o-(len(s)%o))*3) ret += prn return ret def inet_ntoa(ip): if (type(ip) != LongType) and (type(ip) != IntType): if (type(ip) == StringType): return ip else: return inet_ntoa(0) sip = "" ip = long(ip) ipt = 0L for i in range(24,-8,-8): ipn = (ip>>i)-ipt sip += str(ipn) if (i): sip += "." ipt += ipn ipt <<= 8 return sip def inet_addr(ip): if ip.count('.')==3 and ip.replace('.','').isdigit(): num = ip.split('.') for n in range(len(num)): num[n] = long(num[n]) if (num[n] > 255): return 0 return reduce(lambda x,y: (long(x)<<8)+long(y),num,0) return inet_addr(gethostbyname(ip)) class PacketException: def __init__(self, level, context): self.level = level self.context = context def __repr__(self): return self.context class ChecksumException(PacketException): def __init__(self, level, checksum, correct): PacketException.__init__(self,level, "Invalid Checksum (" + hex(checksum) + " instead of " + hex(correct)) self.checksum = checksum self.correct = correct class rawsocket(socket): def __init__(self, family=AF_INET, protocol = IPPROTO_IP): socket.__init__(self,family,SOCK_RAW,protocol) self.__port = 0 self.__addr = "" def eth0(self): for i in self.interfaces(): if IsEthernet(i[0]) and not IsLoopback(i[0]): return i[1] return None def ppp0(self): for i in self.interfaces(): if IsPPP(i[0]) and not IsLoopback(i[0]): return i[1] return None def create(self,ipaddress=None,port=0,recvall=1): self.__addr = ipaddress self.__port = port if not ipaddress: self.__addr = gethostbyname(gethostname()) self.bind((self.__addr,self.__port)) self.IpHeaderIncluded() self.ReceiveAllData(recvall) return self def bindlocal(self,port=0): return self.bind((gethostbyname(gethostname()),port)) def bindif(self,interface=None,port=0): if interface is None: interface = self.FindInterface() return self.bind((self.interfaces()[interface][1],port)) def IpHeaderIncluded(self,b=True): return self.setsockopt(IPPROTO_IP,IP_HDRINCL,int(b)) def ReceiveAllData(self,b=True): return self.ioctl(SIO_RCVALL, int(b)) class ipv4: def __init__(self, protocol=IPPROTO_TCP, payload=""): self.__dict__["Payload"] = payload self.__dict__["Identification"] = Random(0xFFFF) self.__dict__["TimeToLive"] = 200 self.__dict__["FragOffset"] = 0 self.__dict__["FragMF"] = False self.__dict__["FragDF"] = True self.__dict__["Protocol"] = protocol self.__dict__["DestinationIP"] = inet_ntoa(0) self.__dict__["SourceIP"] = inet_ntoa(0) self.__dict__["__checksum"] = 0 try : self.SourceIP = gethostbyname(gethostname()) except: pass def read(self, s): if (calcsize(PCK_IP4) > len(s)): raise PacketException(IPPROTO_IP, "Invalid buffer size for IPv4 header") raw = unpack(PCK_IP4, s[0:calcsize(PCK_IP4)]) if (raw[0]>>4 != 4): raise PacketException(IPPROTO_IP, "Invalid IPv4 header, Version identified as " + str(raw[0]>>4)) hl = (raw[0]-0x40)*4 self.Payload = s[hl:] self.Identification = raw[2] fflag = raw[3] >> 13 self.FragOffset = raw[3] - fflag self.FragMF = bool((fflag & 1)) self.FragDF = bool((fflag & 2)) self.TimeToLive = raw[4] self.Protocol = raw[5] self.__checksum = raw[6] self.SourceIP = inet_ntoa(raw[7]) self.DestinationIP = inet_ntoa(raw[8]) if (raw[1] != len(s)): raise PacketException(IPPROTO_IP, "Buffer length does not equal IP header length field") elif checksum(s[0:hl]): self.__dict__["__checksum"] = 0 self.__dict__["__checksum"] = checksum(self.__pack(False)) raise ChecksumException(IPPROTO_IP, self.__dict__["__checksum"], chk) else: return (raw[0]-0x40) def __setattr__(self, name, value): if (self.__dict__.has_key(name)): if (name == "Payload"): if (type(value) != StringType): value = str(value) elif ((name == "SourceIP") or (name == "DestinationIP")): value = inet_ntoa(value) elif ((name == "FragMF") or (name == "FragDF")): if (type(value) != BooleanType): value = bool(value) elif (name == "__checksum"): raise TypeError("Attempted access to private member variable of TCP instance") elif (type(value) != IntType): if (type(value) == LongType): value = value & 0xFFFFFFFFL value = int(value) else: raise TypeError("You can only assign integer values to TCP header fields") if ((((name == "TimeToLive") or (name == "Protocol")) and (value > 0xFF)) or ((name == "Identification") and (value > 0xFFFF)) or ((name == "FragOfffset") and (value > 0x1FFF))): raise PacketException(IPPROTO_IP, "Too large value for " + name + " field specified.") self.__dict__[name] = value def __pack(self, b=False): p = pack(PCK_IP4, 0x45, len(self), self.Identification, self.FragOffset + (int(self.FragMF) << 13) + (int(self.FragDF) << 14), self.TimeToLive, self.Protocol, self.__dict__["__checksum"], inet_addr(self.SourceIP), inet_addr(self.DestinationIP)) if b: p+=self.Payload; return p def AttachTCP(self,payload): self.Payload = str(payload.Pack(self.SourceIP, self.DestinationIP)) def Pack(self): self.__dict__["__checksum"] = 0 self.__dict__["__checksum"] = checksum(self.__pack()) return self.__pack(True) def __repr__(self): return HexStr(str(self)) def __str__(self): return self.Pack() def __len__(self): return 20 + len(self.Payload) class tcp: def __init__(self, payload=""): self.__dict__["__IP"] = (0,0) self.__dict__["SourcePort"] = 0 self.__dict__["DestinationPort"] = 0 self.__dict__["Sequence"] = Random(0xFFFFFFF) self.__dict__["Acknowledgement"] = 0 self.__dict__["Flags"] = 0 self.__dict__["Window"] = 0xFFFF self.__dict__["Urgent"] = 0 self.__dict__["Payload"] = payload self.__dict__["__checksum"] = 0 self.__dict__["__mss"] = "" def SetRoute(self, source, destination): self.__dict__["__IP"] = (inet_addr(source),inet_addr(destination)) def __setattr__(self, name, value): if (self.__dict__.has_key(name)): if (name == "Payload"): if (type(value) != StringType): value = str(value) elif (name == "__mss") or (name == "__checksum") or (name == "__IP"): raise TypeError("Attempted access to private member variable of TCP instance") elif (type(value) != IntType): if (type(value) == LongType): value = value & 0xFFFFFFFFL value = int(value) else: raise TypeError("You can only assign integer values to TCP header fields") if (name == "Flags"): if (value > 0x3F): raise PacketException(IPPROTO_TCP, "Too large value for flags field specified.") elif (name == "Urgent") or (name == "Window") or (name == "SourcePort") or (name == "DestinationPort"): if (value > 0xFFFF): raise PacketException(IPPROTO_TCP, "Too large value for " + name + " field specified.") self.__dict__[name] = value def EnableMSS(self, mss): self.__dict__["__mss"] = pack("!BBH", 2, 4, mss) def DisableMSS(self): self.__dict__["__mss"] = "" def read(self, s): if (calcsize(PCK_TCP) > len(s)): return 0 raw = unpack(PCK_TCP, s[0:calcsize(PCK_TCP)]) self.SourcePort = raw[0] self.DestinationPort = raw[1] self.Sequence = raw[2] self.Acknowledgement = raw[3] offset = raw[4] >> 4 self.Flags = raw[5] & 0x3F self.Window = raw[6] self.__checksum = raw[7] self.Urgent = raw[8] self.Payload = s[offset:] return offset def __pack(self): off = 80 if (self.__dict__["__mss"]): off += 16 p = pack(PCK_TCP, self.SourcePort, self.DestinationPort, self.Sequence, self.Acknowledgement, off, self.Flags & 0x3F, self.Window, self.__dict__["__checksum"], self.Urgent) p += self.__dict__["__mss"] p += self.Payload return p def Pack(self, source=None, destination=None): if (source and destination): self.SetRoute(source,destination) self.__dict__["__checksum"] = 0 pseudo = pack(PCK_PSEUDO, self.__dict__["__IP"][0], self.__dict__["__IP"][1], IPPROTO_TCP, len(self)) pseudo += self.__pack() self.__dict__["__checksum"] = checksum(pseudo) return self.__pack() def __repr__(self): return HexStr(str(self)) def __str__(self): return self.Pack() def __len__(self): return 20 + len(self.__dict__["__mss"])+ len(self.Payload) class icmp: def __init__(self): self.Code = 0 self.Type = 0 self.Payload = "" self.__checksum = 0 self.__data = "\x00\x00\x00\x00" def GetDWORD(self): return unpack("!L",self.__data)[0] def GetWORD(self): return unpack("!HH",self.__data) def GetBYTE(self): return unpack("!BBBB",self.__data) def read(self, s): if (calcsize(PCK_ICMP) > len(s)): raise PacketException(IPPROTO_ICMP, "Invalid buffer size for ICMP header") raw = unpack(PCK_ICMP, s[0:calcsize(PCK_ICMP)]) self.Payload = s[calcsize(PCK_ICMP):] self.Type = raw[0] self.Code = raw[1] chk = raw[2] self.create(raw[3]) self.Pack() if (chk != self.__checksum): raise ChecksumException(IPPROTO_ICMP, chk, self.__checksum) def create(self, valArray): if (type(valArray)!=IntType): if (type(valArray)==LongType): valArray = valArray & 0xFFFFFFFFL valArray = int(valArray) self.__data = pack("!L",valArray) return self elif type(valArray) == ListType: if (len(valArray)==2) or (len(valArray)==4): for i in valArray: if (i > (2**((6-len(valArray))*4)-1)): return None if (len(valArray)==2): self.__data = pack( "!HH", valArray[0],valArray[1]) else: self.__data = pack("!BBBB", valArray[0], valArray[1], valArray[2], valArray[3]) return self return None def MakeEcho(self, id, sequence, reply=False): if (reply): self.Type = 0 else: self.Type = 8 self.Code = 0 return self.create([id,sequence]) def __pack(self): p = pack(PCK_ICMP, self.Type, self.Code, self.__checksum, self.GetDWORD()) p += self.Payload return p def Pack(self): self.__checksum = 0 self.__checksum = checksum(self.__pack()) return self.__pack() def __repr__(self): return HexStr(str(self)) def __str__(self): return self.Pack() def __len__(self): return len(str(self))