|
@@ -0,0 +1,150 @@
|
|
|
+"""
|
|
|
+Структура TCP сегмента:
|
|
|
+
|
|
|
+Слово 1
|
|
|
+
|
|
|
+ SRC (16 бит) номер порта источника
|
|
|
+ DST (16 бит) номер порта назначения
|
|
|
+
|
|
|
+Слово 2
|
|
|
+ SEQ (32 бита) позиционный номер, место первого байта данных сегмента в
|
|
|
+ потоке данных от источника до получателя.
|
|
|
+
|
|
|
+Слово 3
|
|
|
+ ACK (32 бита) квитанция
|
|
|
+
|
|
|
+Слово 4
|
|
|
+ LEN (4 бита) длина заголовка
|
|
|
+ reserv (6 бит)
|
|
|
+ FLAGS (6 бит) флаги
|
|
|
+ WND (16 бит) размер окна приема
|
|
|
+
|
|
|
+"""
|
|
|
+
|
|
|
+import socket
|
|
|
+import struct
|
|
|
+import array
|
|
|
+
|
|
|
+
|
|
|
+class TCPPacket:
|
|
|
+ _srcip = None
|
|
|
+ _dstip = None
|
|
|
+
|
|
|
+ SRC = 0 # номер порта источника
|
|
|
+ DST = 0
|
|
|
+ SEQ = 0 # позиционный номер
|
|
|
+ ACK = 0 # квитанция
|
|
|
+ LEN = 0 # длина заголовка
|
|
|
+
|
|
|
+ # flags
|
|
|
+ f_URG = 0
|
|
|
+ f_ACK = 0
|
|
|
+ f_PSH = 0
|
|
|
+ f_RST = 0
|
|
|
+ f_SYN = 0
|
|
|
+ f_FIN = 0
|
|
|
+
|
|
|
+ WND = 0 # размер окна приема
|
|
|
+ CHK = 0 # контрольная сумма
|
|
|
+ URG = 0 # указатель границы срочный данных
|
|
|
+ OPT = '' # опции
|
|
|
+ DATA = "" # данные
|
|
|
+
|
|
|
+
|
|
|
+ def __init__(self) -> None:
|
|
|
+ print("Create TCP packet instance")
|
|
|
+
|
|
|
+
|
|
|
+ def set_data(self, data):
|
|
|
+ self.DATA = data
|
|
|
+
|
|
|
+
|
|
|
+ def set_ip(self, src, dst):
|
|
|
+ self._srcip = src
|
|
|
+ self._dstip = dst
|
|
|
+
|
|
|
+
|
|
|
+ def to_hex_string(self):
|
|
|
+
|
|
|
+ tcp_flags = self.f_FIN + (self.f_SYN << 1) + (self.f_RST << 2) + \
|
|
|
+ (self.f_PSH << 3) + (self.f_ACK << 4) + (self.f_URG << 5)
|
|
|
+
|
|
|
+ header = struct.pack('!HHLLBBHHH', self.SRC, self.DST, self.SEQ, self.ACK,
|
|
|
+ (self.LEN << 4) + 0, tcp_flags, self.WND, self.CHK, self.URG)
|
|
|
+
|
|
|
+ # calculate data length
|
|
|
+ data_len = 0
|
|
|
+ if(self.DATA != None):
|
|
|
+ data_len = len(self.DATA)
|
|
|
+
|
|
|
+ # create pseudo TCP packet
|
|
|
+ psh = struct.pack('!4s4sBBH',
|
|
|
+ socket.inet_aton(self._srcip), # type: ignore
|
|
|
+ socket.inet_aton(self._dstip), 0, # type: ignore
|
|
|
+ socket.IPPROTO_TCP,
|
|
|
+ len(header) + data_len)
|
|
|
+
|
|
|
+ psh = psh + header + bytes(self.DATA, 'utf-8')
|
|
|
+
|
|
|
+ crc = self.crc(psh)
|
|
|
+
|
|
|
+ return struct.pack('!HHLLBBH', self.SRC, self.DST, self.SEQ, self.ACK, \
|
|
|
+ (self.LEN << 4) + 0, tcp_flags, self.WND) + \
|
|
|
+ struct.pack('H', crc) + struct.pack('!H', self.URG) + \
|
|
|
+ bytes(self.DATA, 'utf-8')
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ def crc(self, data: bytes):
|
|
|
+ if len(data)%2 != 0:
|
|
|
+ data += b'\0'
|
|
|
+
|
|
|
+ res = sum(array.array("H", data))
|
|
|
+ res = (res >> 16) + (res & 0xffff)
|
|
|
+ res += res >> 16
|
|
|
+
|
|
|
+ return (~res) & 0xffff
|
|
|
+
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def get_falgs_from_byte(data):
|
|
|
+ flags = [0,0,0,0,0,0]
|
|
|
+
|
|
|
+ flags[0] = (data >> 5) & 1
|
|
|
+ flags[1] = data >> 4 & 1
|
|
|
+ flags[2] = data >> 3 & 1
|
|
|
+ flags[3] = data >> 2 & 1
|
|
|
+ flags[4] = data >> 1 & 1
|
|
|
+ flags[5] = data & 1
|
|
|
+
|
|
|
+ return (flags[0], flags[1], flags[2], flags[3], flags[4], flags[5])
|
|
|
+
|
|
|
+
|
|
|
+ def __str__(self):
|
|
|
+ s = ""
|
|
|
+ s += "TCP Segment"
|
|
|
+ s += "\tSource Port: {}, Destination Port: {}\n".format(self.SRC, self.DST)
|
|
|
+ s += "\tSequence: {}, Acknowledgement: {}\n".format(self.SEQ, self.ACK)
|
|
|
+ s += "\tFlags\n"
|
|
|
+ s += "\t\tURG: {}, ACK: {}, PSH: {}\n".format(self.f_URG, self.f_ACK, self.f_PSH)
|
|
|
+ s += "\t\tRST: {}, SYN: {}, FIN: {}\n".format(self.f_RST, self.f_SYN, self.f_FIN)
|
|
|
+ s += "\tHeader Length: {}, Window Size: {}\n".format(self.LEN, self.WND)
|
|
|
+ # Other parameters
|
|
|
+ s += "Over parameters\n"
|
|
|
+ s += "\t\tSRC ip: {}, DST ip: {}\n".format(self._srcip, self._dstip)
|
|
|
+ return s
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def main():
|
|
|
+ pack = TCPPacket()
|
|
|
+ print(pack)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ main()
|
|
|
+
|
|
|
+
|