Byte-ul Posted September 13, 2014 Report Posted September 13, 2014 (edited) Packet injection is the process of interfering with an established network connection by constructing arbitrary protocol packets (TCP, UDP, ...) and send them out through raw socketsit's used widely in network penetration testing such as DDoS, TCP reset attacks, port scanning...A Packet is a combination of IP header, TCP/UDP header and data:Packet = IP Header + TCP/UDP Header + DataMost operating systems that implements socket API supports packet injection, especially those based on Berkeley Sockets. Microsoft limited raw sockets capabilities to packet sniffing, after Windows XP release. This tutorial is implemented on Unix-Like operating systems.TCP HeaderThe TCP protocol is the most used transport protocol in the world wide web, it provides a reliable, ordered and error-checked delivery of a stream of bytes between programs running on computers connected to network.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+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Source Port | Destination Port |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Sequence Number |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Acknowledgment Number |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Data | |U|A|P|R|S|F| || Offset| Reserved |R|C|S|S|Y|I| Window || | |G|K|H|T|N|N| |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Checksum | Urgent Pointer |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Options | Padding |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| data |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Sequence Number (32 bits): the sequence number of the first data byte in this segment. if the SYN flag is set, the sequence number should be the initial sequence number (ISN: usually 0), and the first data byte in the first data stream should be ISN+1 (1).Acknowledgment Number (32 bits): If the ACK flag is set, this field contains the value of the next sequence number the destination machine is expecting to receive.for every packet contains data is sent, an acknowledgment packet should be received, to acknowledge that the last packet is successfully received.Data Offset (4 bits): The length of TCP header by providing the number of 32-bit words. this indicates where the data begins.Reserved (6 bits): Usually cleared to zeroControl Bits (6 bits):ACK: Acknowledgment packetSYN: Request to establish a connectionRST: Request to reset connectionFIN: Request to interrupt (close) a connectionPSH: Informs TCP that data should be sent immediately (Useful in real-time applications)URG: Urgent Pointer field is significantWindow: The number of data bytes you can send before you should stop and wait for acknowledgementChecksum: used for error-checking of the header and dataUrgent Pointer: If the URG control flag is set, this field is an offset from the sequence number indicating the last urgent data byteThis feature is used when some information has to reach it's destination as soon as possible.Creating Raw SocketFor creating a socket capable of injecting manually crafted packet, we pass "SOCK_RAW" as a type of socket, and "IPPROTO_RAW" as the used protocol. The "IPPROTO_RAW" tells the kernel that we will provide the network layer (Internet Protocol) and the transfer layer (TCP/UDP Protocol)s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)Constructing the IP HeaderFor this purpose, we can write a simple class to deal with the IP Header structure:class ip(object): def __init__(self, source, destination): self.version = 4 self.ihl = 5 # Internet Header Length self.tos = 0 # Type of Service self.tl = 0 # total length will be filled by kernel self.id = 54321 self.flags = 0 # More fragments self.offset = 0 self.ttl = 255 self.protocol = socket.IPPROTO_TCP self.checksum = 0 # will be filled by kernel self.source = socket.inet_aton(source) self.destination = socket.inet_aton(destination) def pack(self): ver_ihl = (self.version << 4) + self.ihl flags_offset = (self.flags << 13) + self.offset ip_header = struct.pack("!BBHHHBBH4s4s", ver_ihl, self.tos, self.tl, self.id, flags_offset, self.ttl, self.protocol, self.checksum, self.source, self.destination) return ip_headerThe "pack" method packs the ip header elements and return it.ipobj = ip("127.0.0.1", "127.0.0.2") # Creating an ip object instance ipobj.source = "localhost" # Changing IP element value iph = ipobj.pack() # packing ip header elementsConstructing the TCP HeaderThis is a tcp class that allows us to easily manipulate the tcp header elements and pack them.class tcp(object): def __init__(self, srcp, dstp): self.srcp = srcp self.dstp = dstp self.seqn = 0 self.ackn = 0 self.offset = 5 # Data offset: 5x4 = 20 bytes self.reserved = 0 self.urg = 0 self.ack = 0 self.psh = 1 self.rst = 0 self.syn = 0 self.fin = 0 self.window = socket.htons(5840) self.checksum = 0 self.urgp = 0 self.payload = "" def pack(self, source, destination): data_offset = (self.offset << 4) + 0 flags = self.fin + (self.syn << 1) + (self.rst << 2) + (self.psh << 3) + (self.ack << 4) + (self.urg << 5) tcp_header = struct.pack('!HHLLBBHHH', self.srcp, self.dstp, self.seqn, self.ackn, data_offset, flags, self.window, self.checksum, self.urgp) #pseudo header fields source_ip = source destination_ip = destination reserved = 0 protocol = socket.IPPROTO_TCP total_length = len(tcp_header) + len(self.payload) # Pseudo header psh = struct.pack("!4s4sBBH", source_ip, destination_ip, reserved, protocol, total_length) psh = psh + tcp_header + self.payload tcp_checksum = checksum(psh) tcp_header = struct.pack("!HHLLBBH", self.srcp, self.dstp, self.seqn, self.ackn, data_offset, flags, self.window) tcp_header+= struct.pack('H', tcp_checksum) + struct.pack('!H', self.urgp) return tcp_headerAs we know, TCP is end-to-end reliable protocol. Reliability is provided by the checksum field which used to ensure that data reaches it's correct destination and is error-free. A checksum is 16 bits number calculated by summing the one's compliment of Pseudo header, tcp header and data.The pseudo header is a combination of 5 different fields that includes the source ip and destination ip: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+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Source IP address |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Destination IP address |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Reserved | Protocol | Total Length |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Source IP address (32 bits): Sender's IP addressDestination IP address (32 bits): Receiver's IP addressReserved (8 bits): Cleared to zerosProtocol (8 bits): Transport protocol (6 for TCP, 17 for UDP)Total Length (15 bits): size of tcp header and dataDuring the TCP header checksum calculation, the checksum field should be set to zero. Once it's value is calculated, it should be inserted into the field before sending the packet.Constructing the pseudo-header fields:#pseudo header fieldssource_ip = sourcedestination_ip = destinationreserved = 0protocol = socket.IPPROTO_TCPtotal_length = len(tcp_header) + len(self.payload)Packing the pseudo-header and combining it with TCP header and data:# Pseudo headerpsh = struct.pack("!4s4sBBH", source_ip, destination_ip, reserved, protocol, total_length)psh = psh + tcp_header + self.payloadThe checksum function:def checksum(data): s = 0 n = len(data) % 2 for i in range(0, len(data)-n, 2): s+= ord(data) + (ord(data[i+1]) << 8) if n: s+= ord(data[i+1]) while (s >> 16): print("s >> 16: ", s >> 16) s = (s & 0xFFFF) + (s >> 16) print("sum:", s) s = ~s & 0xffff return sPacket InjectionThis is an example of using ip and tcp classes to construct headers and injecting it:s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)src_host = "10.0.2.15"dest_host = socket.gethostbyname("www.reddit.com")data = "TEST!!"# IP Headeripobj = ip(src_host, dest_host)iph = ip_object.pack()# TCP Headertcpobj = tcp(1234, 80)tcpobj.data_length = len(data) # Used in pseudo headertcph = tcpobj.pack(ipobj.source, ipobj.destination)# Injectionpacket = iph + tcph + datas.send(packet, (dest_host, 0))Pinject.pyRunning the script:python pinject.py --src=10.0.2.15 --dst=www.reddit.com[+] Local Machine: 10.0.2.15[+] Remote Machine: 198.41.209.142[+] Raw scoket created[+] Data to inject: TEST!![+] Constructing IP Header[+] Constructing TCP Header[+] Packet Injected!Screenshot from Wireshark:Fork me on github:https://github.com/offensive-python/PinjectSource: TCP Packet Injection with Python | Python for Pentesting Edited September 13, 2014 by Byte-ul 1 Quote