设为首页收藏本站

安而遇随-随遇而安

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1774|回复: 0

使用Python进行TCP数据包注入(伪造)

[复制链接]

 成长值: 50580

发表于 2014-8-19 13:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x

数据包注入是对已经建立的网络连接通过构建任意协议(TCP…UDP…)然后用原始套接字发送的方式进行妨碍的过程,这种方法被广泛使用在网络渗透测试中,比如DDOS,端口扫描等。

一个数据包由IP头部信息、TCP/UDP头部信息和数据构成:

  1. Packet = IP Header + TCP/UDP Header + Data
复制代码

大多数操作系统的socket API都支持包注入(尤其是基于Berkeley Sockets的),微软在windows xp之后为了避免包嗅探限制了原始套接字的能力。这篇文章只适用于UNIX/类UNIX系统。

TCP协议被广泛运用于互联网上的数据传输,它是一种面向连接(连接导向)的、可靠的、基于IP的传输层协议。

TCP的首部格式:

  1. 0                   1                   2                   3  
  2. 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
  3. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  4. |          Source Port          |       Destination Port        |
  5. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  6. |                        Sequence Number                        |
  7. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  8. |                    Acknowledgment Number                      |
  9. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  10. |  Data |           |U|A|P|R|S|F|                               |
  11. | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
  12. |       |           |G|K|H|T|N|N|                               |
  13. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  14. |           Checksum            |         Urgent Pointer        |
  15. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  16. |                    Options                    |    Padding    |
  17. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  18. |                             data                              |
  19. -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
复制代码

—Source Port是源端口,16位。

—Destination Port是目的端口,16位。

—Sequence Number是发送数据包中的第一个字节的序列号,32位。

—Acknowledgment Number是确认序列号,32位。

—Data Offset是数据偏移,4位,该字段的值是TCP首部(包括选项)长度乘以4。

—标志位: 6位,URG表示Urgent Pointer字段有意义:

ACK表示Acknowledgment Number字段有意义

PSH表示Push功能,RST表示复位TCP连接

SYN表示SYN报文(在建立TCP连接的时候使用)

FIN表示没有数据需要发送了(在关闭TCP连接的时候使用)

Window表示接收缓冲区的空闲空间,16位,用来告诉TCP连接对端自己能够接收的最大数据长度。

—Checksum是校验和,16位。

—Urgent Pointers是紧急指针,16位,只有URG标志位被设置时该字段才有意义,表示紧急数据相对序列号(Sequence Number字段的值)的偏移。

更多TCP协议的详细信息可以在网上轻易找到,在这里不再赘述。

为了建立一个可以自己构造数据的包,我们使用"SOCK_RAW"这种socket格式,使用"IPPROTO_RAW"协议,它会告诉系统我们将提供网络层和传输层。

  1. s = socket.socket(socket.AF_INET,socket.SOCK_RAW,)
复制代码
通过这个简单的类,我们可以进行IP头部信息构造
  1. class ip(object):
  2.     def __init__(self, source, destination):
  3.         self.version = 4
  4.         self.ihl = 5 # Internet Header Length
  5.         self.tos = 0 # Type of Service
  6.         self.tl = 0 # total length will be filled by kernel
  7.         self.id = 54321
  8.         self.flags = 0 # More fragments
  9.         self.offset = 0
  10.         self.ttl = 255
  11.         self.protocol = socket.IPPROTO_TCP
  12.         self.checksum = 0 # will be filled by kernel
  13.         self.source = socket.inet_aton(source)
  14.         self.destination = socket.inet_aton(destination)
  15.     def pack(self):
  16.         ver_ihl = (self.version << 4) + self.ihl
  17.         flags_offset = (self.flags << 13) + self.offset
  18.         ip_header = struct.pack("!BBHHHBBH4s4s",
  19.                     ver_ihl,
  20.                     self.tos,
  21.                     self.tl,
  22.                     self.id,
  23.                     flags_offset,
  24.                     self.ttl,
  25.                     self.protocol,
  26.                     self.checksum,
  27.                     self.source,
  28.                     self.destination)
复制代码
"pack"方法会对IP头部元素进行打包并返回它
  1. ipobj = ip("127.0.0.1", "127.0.0.2") # Creating an ip object instancei
  2. pobj.source = "localhost" # Changing IP element value
复制代码

构造TCP头部信息

TCP类允许我们轻易地操作TCP头部元素并打包它们

  1. class tcp(object):
  2.     def __init__(self, srcp, dstp):
  3.         self.srcp = srcp
  4.         self.dstp = dstp
  5.         self.seqn = 0
  6.         self.ackn = 0
  7.         self.offset = 5 # Data offset: 5x4 = 20 bytes
  8.         self.reserved = 0
  9.         self.urg = 0
  10.         self.ack = 0
  11.         self.psh = 1
  12.         self.rst = 0
  13.         self.syn = 0
  14.         self.fin = 0
  15.         self.window = socket.htons(5840)
  16.         self.checksum = 0
  17.         self.urgp = 0
  18.         self.payload = ""
  19.     def pack(self, source, destination):
  20.         data_offset = (self.offset << 4) + 0
  21.         flags = self.fin + (self.syn << 1) + (self.rst << 2) + (self.psh << 3) + (self.ack << 4) + (self.urg << 5)
  22.         tcp_header = struct.pack('!HHLLBBHHH',
  23.                      self.srcp,
  24.                      self.dstp,
  25.                      self.seqn,
  26.                      self.ackn,
  27.                      data_offset,
  28.                      flags,
  29.                      self.window,
  30.                      self.checksum,
  31.                      self.urgp)
  32.         #pseudo header fields
  33.         source_ip = source
  34.         destination_ip = destination
  35.         reserved = 0
  36.         protocol = socket.IPPROTO_TCP
  37.         total_length = len(tcp_header) + len(self.payload)
  38.         # Pseudo header
  39.         psh = struct.pack("!4s4sBBH",
  40.               source_ip,
  41.               destination_ip,
  42.               reserved,
  43.               protocol,
  44.               total_length)
  45.         psh = psh + tcp_header + self.payload
  46.         tcp_checksum = checksum(psh)
  47.         tcp_header = struct.pack("!HHLLBBH",
  48.                   self.srcp,
  49.                   self.dstp,
  50.                   self.seqn,
  51.                   self.ackn,
  52.                   data_offset,
  53.                   flags,
  54.                   self.window)
  55.         tcp_header+= struct.pack('H', tcp_checksum) + struct.pack('!H', self.urgp)
复制代码

我们知道,TCP协议是一种面向连接(连接导向)的、可靠的、基于IP的传输层协议,提供一种面向连接的、可靠的字节流服务,面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据包之前必须先建立一个TCP连接。

伪造的头部信息有五个不同的区域且包含了source ip和destination ip

  1. 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
  2. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  3. |                          Source IP address                    |
  4. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  5. |                        Destination IP address                 |
  6. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  7. |     Reserved  |   Protocol    |          Total Length         |
  8. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  9. •Source IP address (32 bits): 发送者的IP地址
  10. •Destination IP address (32 bits): 接受者的IP地址
  11. •Reserved (8 bits): 清零
  12. •Protocol (8 bits): 传输协议(6为TCP, 17为UDP)
复制代码

在TCP头部校验计算中,校验和字段必须清零。一旦值被计算出,在发送包之前必须插入字段中。

构造头部字段

  1. source_ip = source
  2. destination_ip = destination
  3. reserved = 0
  4. protocol = socket.IPPROTO_TCP
复制代码
打包伪造的头部并且将它插入TCP头部和数据中:
  1. # 伪造头部
  2. psh = struct.pack("!4s4sBBH",
  3.               source_ip,
  4.               destination_ip,
  5.               reserved,
  6.               protocol,
  7.               total_length)
  8. psh = psh + tcp_header + self.payload
复制代码
校验函数:
  1. def checksum(data):
  2.     s = 0
  3.     n = len(data) % 2
  4.     for i in range(0, len(data)-n, 2):
  5.         s+= ord(data[i]) + (ord(data[i+1]) << 8)
  6.     if n:
  7.         s+= ord(data[i+1])
  8.     while (s >> 16):
  9.         print("s >> 16: ", s >> 16)
  10.         s = (s & 0xFFFF) + (s >> 16)
  11.     print("sum:", s)
  12.     s = ~s & 0xffff
复制代码
一个小列子:
  1. s = socket.socket(socket.AF_INET,
  2.                   socket.SOCK_RAW,
  3.                   socket.IPPROTO_RAW)
  4. src_host = "10.0.2.15"
  5. dest_host = socket.gethostbyname("www.reddit.com")
  6. data = "TEST!!"
  7. # IP Header
  8. ipobj = ip(src_host, dest_host)
  9. iph = ip_object.pack()
  10. # TCP Header
  11. tcpobj = tcp(1234, 80)
  12. tcpobj.data_length = len(data)  # Used in pseudo header
  13. tcph = tcpobj.pack(ipobj.source,
  14.                    ipobj.destination)
  15. # Injection
  16. packet = iph + tcph + data
  17. Pinject.py
  18. Running the script:
  19. python pinject.py --src=10.0.2.15 --dst=www.reddit.com
  20. [+] Local Machine: 10.0.2.15
  21. [+] Remote Machine: 198.41.209.142
  22. [+] Raw scoket created
  23. [+] Data to inject: TEST!!
  24. [+] Constructing IP Header
  25. [+] Constructing TCP Heade
复制代码



项目地址:https://github.com/offensive-python/Pinject



来源:网络转载




[发帖际遇]: admin 捡了钱没交公 SB 降了 1 . 幸运榜 / 衰神榜
随遇而安
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表