Python进行TCP数据包注入(伪造)实例教程

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

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

<span class="setting">Packet = <span class="value">IP Header + TCP/UDP Header + Data</span></span>

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

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

TCP的首部格式:

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
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>
|          Source Port          |       Destination Port        |
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>
|                        Sequence Number                        |
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>
|                    Acknowledgment Number                      |
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>
|  Data |           |U|A|P|R|S|F|                               |
| Offset| Reserved  |R|C|S|S|Y|I|            Window             |
|       |           |G|K|H|T|N|N|                               |
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>
|           Checksum            |         Urgent Pointer        |
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>
|                    Options                    |    Padding    |
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>
|                             data                              |
<span class="deletion">-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-</span>

—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"协议,它会告诉系统我们将提供网络层和传输层。

<span class="keyword" style="font-weight: bold;">s</span> = <span class="keyword" style="font-weight: bold;">socket</span>.<span class="keyword" style="font-weight: bold;">socket</span>(<span class="keyword" style="font-weight: bold;">socket</span>.AF_INET,<span class="keyword" style="font-weight: bold;">socket</span>.SOCK_RAW,)

通过这个简单的类,我们可以进行IP头部信息构造

<span class="class" style="font-weight: bold; color: #445588;"><span class="keyword">class</span> <span class="title">ip</span><span class="params">(object)</span>:</span>
<span class="function"><span class="keyword" style="font-weight: bold;">def</span> <span class="title" style="font-weight: bold; color: #990000;">__init__</span><span class="params">(self, source, destination)</span>:</span>
self.version = <span class="number" style="color: #009999;">4</span>
self.ihl = <span class="number" style="color: #009999;">5</span> <span class="comment" style="font-style: italic; color: #999988;"># Internet Header Length</span>
self.tos = <span class="number" style="color: #009999;">0</span> <span class="comment" style="font-style: italic; color: #999988;"># Type of Service</span>
self.tl = <span class="number" style="color: #009999;">0</span> <span class="comment" style="font-style: italic; color: #999988;"># total length will be filled by kernel</span>
self.id = <span class="number" style="color: #009999;">54321</span>
self.flags = <span class="number" style="color: #009999;">0</span> <span class="comment" style="font-style: italic; color: #999988;"># More fragments</span>
self.offset = <span class="number" style="color: #009999;">0</span>
self.ttl = <span class="number" style="color: #009999;">255</span>
self.protocol = socket.IPPROTO_TCP
self.checksum = <span class="number" style="color: #009999;">0</span> <span class="comment" style="font-style: italic; color: #999988;"># will be filled by kernel</span>
self.source = socket.inet_aton(source)
self.destination = socket.inet_aton(destination)
<span class="function"><span class="keyword" style="font-weight: bold;">def</span> <span class="title" style="font-weight: bold; color: #990000;">pack</span><span class="params">(self)</span>:</span>
ver_ihl = (self.version << <span class="number" style="color: #009999;">4</span>) + self.ihl
flags_offset = (self.flags << <span class="number" style="color: #009999;">13</span>) + self.offset
ip_header = struct.pack(<span class="string" style="color: #dd1144;">"!BBHHHBBH4s4s"</span>,
ver_ihl,
self.tos,
self.tl,
self.id,
flags_offset,
self.ttl,
self.protocol,
self.checksum,
self.source,
self.destination)

"pack"方法会对IP头部元素进行打包并返回它

<span class="class" style="font-weight: bold; color: #445588;"><span class="keyword">class</span> <span class="title">tcp</span>(<span class="title">object</span>):</span>
<span class="function"><span class="keyword" style="font-weight: bold;">def</span> <span class="title" style="font-weight: bold; color: #990000;">__init__</span><span class="params">(<span class="keyword" style="font-weight: bold;">self</span>, srcp, dstp)</span>:</span>
<span class="keyword" style="font-weight: bold;">self</span>.srcp = srcp
<span class="keyword" style="font-weight: bold;">self</span>.dstp = dstp
<span class="keyword" style="font-weight: bold;">self</span>.seqn = <span class="number" style="color: #009999;">0</span>
<span class="keyword" style="font-weight: bold;">self</span>.ackn = <span class="number" style="color: #009999;">0</span>
<span class="keyword" style="font-weight: bold;">self</span>.offset = <span class="number" style="color: #009999;">5</span> <span class="comment" style="font-style: italic; color: #999988;"># Data offset: 5x4 = 20 bytes</span>
<span class="keyword" style="font-weight: bold;">self</span>.reserved = <span class="number" style="color: #009999;">0</span>
<span class="keyword" style="font-weight: bold;">self</span>.urg = <span class="number" style="color: #009999;">0</span>
<span class="keyword" style="font-weight: bold;">self</span>.ack = <span class="number" style="color: #009999;">0</span>
<span class="keyword" style="font-weight: bold;">self</span>.psh = <span class="number" style="color: #009999;">1</span>
<span class="keyword" style="font-weight: bold;">self</span>.rst = <span class="number" style="color: #009999;">0</span>
<span class="keyword" style="font-weight: bold;">self</span>.syn = <span class="number" style="color: #009999;">0</span>
<span class="keyword" style="font-weight: bold;">self</span>.fin = <span class="number" style="color: #009999;">0</span>
<span class="keyword" style="font-weight: bold;">self</span>.window = socket.htons(<span class="number" style="color: #009999;">5840</span>)
<span class="keyword" style="font-weight: bold;">self</span>.checksum = <span class="number" style="color: #009999;">0</span>
<span class="keyword" style="font-weight: bold;">self</span>.urgp = <span class="number" style="color: #009999;">0</span>
<span class="keyword" style="font-weight: bold;">self</span>.payload = <span class="string" style="color: #dd1144;">""</span>
<span class="function"><span class="keyword" style="font-weight: bold;">def</span> <span class="title" style="font-weight: bold; color: #990000;">pack</span><span class="params">(<span class="keyword" style="font-weight: bold;">self</span>, source, destination)</span>:</span>
data_offset = (<span class="keyword" style="font-weight: bold;">self</span>.offset << <span class="number" style="color: #009999;">4</span>) + <span class="number" style="color: #009999;">0</span>
flags = <span class="keyword" style="font-weight: bold;">self</span>.fin + (<span class="keyword" style="font-weight: bold;">self</span>.syn << <span class="number" style="color: #009999;">1</span>) + (<span class="keyword" style="font-weight: bold;">self</span>.rst << <span class="number" style="color: #009999;">2</span>) + (<span class="keyword" style="font-weight: bold;">self</span>.psh << <span class="number" style="color: #009999;">3</span>) + (<span class="keyword" style="font-weight: bold;">self</span>.ack << <span class="number" style="color: #009999;">4</span>) + (<span class="keyword" style="font-weight: bold;">self</span>.urg << <span class="number" style="color: #009999;">5</span>)
tcp_header = struct.pack(<span class="string" style="color: #dd1144;">'!HHLLBBHHH'</span>,
<span class="keyword" style="font-weight: bold;">self</span>.srcp,
<span class="keyword" style="font-weight: bold;">self</span>.dstp,
<span class="keyword" style="font-weight: bold;">self</span>.seqn,
<span class="keyword" style="font-weight: bold;">self</span>.ackn,
data_offset,
flags,
<span class="keyword" style="font-weight: bold;">self</span>.window,
<span class="keyword" style="font-weight: bold;">self</span>.checksum,
<span class="keyword" style="font-weight: bold;">self</span>.urgp)
<span class="comment" style="font-style: italic; color: #999988;">#pseudo header fields</span>
source_ip = source
destination_ip = destination
reserved = <span class="number" style="color: #009999;">0</span>
protocol = socket.<span class="constant">IPPROTO_TCP</span>
total_length = len(tcp_header) + len(<span class="keyword" style="font-weight: bold;">self</span>.payload)
<span class="comment" style="font-style: italic; color: #999988;"># Pseudo header</span>
psh = struct.pack(<span class="string" style="color: #dd1144;">"!4s4sBBH"</span>,
  source_ip,
  destination_ip,
  reserved,
  protocol,
  total_length)
psh = psh + tcp_header + <span class="keyword" style="font-weight: bold;">self</span>.payload
tcp_checksum = checksum(psh)
tcp_header = struct.pack(<span class="string" style="color: #dd1144;">"!HHLLBBH"</span>,
  <span class="keyword" style="font-weight: bold;">self</span>.srcp,
  <span class="keyword" style="font-weight: bold;">self</span>.dstp,
  <span class="keyword" style="font-weight: bold;">self</span>.seqn,
  <span class="keyword" style="font-weight: bold;">self</span>.ackn,
  data_offset,
  flags,
  <span class="keyword" style="font-weight: bold;">self</span>.window)
tcp_header+= struct.pack(<span class="string" style="color: #dd1144;">'H'</span>, tcp_checksum) + struct.pack(<span class="string" style="color: #dd1144;">'!H'</span>, <span class="keyword" style="font-weight: bold;">self</span>.urgp)

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

伪造的头部信息有五个不同的区域且包含了source ip和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
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>
|                          Source IP address                    |
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>
|                        Destination IP address                 |
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>
|     Reserved  |   Protocol    |          Total Length         |
<span class="addition">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span>

•Source IP address (32 bits): 发送者的IP地址
•Destination IP address (32 bits): 接受者的IP地址
•Reserved (8 bits): 清零
•Protocol (8 bits): 传输协议(6为TCP, 17为UDP)

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

构造头部字段

<span class="setting">source_ip = <span class="value">source</span></span>
<span class="setting">destination_ip = <span class="value">destination</span></span>
<span class="setting">reserved = <span class="value"><span class="number" style="color: #009999;">0</span></span></span>
<span class="setting">protocol = <span class="value">socket.IPPROTO_TCP</span></span>

打包伪造的头部并且将它插入TCP头部和数据中:

<span class="preprocessor" style="font-weight: bold; color: #999999;"># 伪造头部</span>
psh = <span class="keyword" style="font-weight: bold;">struct</span>.pack(<span class="string" style="color: #dd1144;">"!4s4sBBH"</span>,
source_ip,
destination_ip,
reserved,
protocol,
total_length)
psh = psh + tcp_header + self.payload

校验函数:

<span class="function"><span class="keyword" style="font-weight: bold;">def</span> <span class="title" style="font-weight: bold; color: #990000;">checksum</span><span class="params">(data)</span>:</span>
s = <span class="number" style="color: #009999;">0</span>
n = len(data) % <span class="number" style="color: #009999;">2</span>
<span class="keyword" style="font-weight: bold;">for</span> i <span class="keyword" style="font-weight: bold;">in</span> range(<span class="number" style="color: #009999;">0</span>, len(data)-n, <span class="number" style="color: #009999;">2</span>):
s+= ord(data[i]) + (ord(data[i+<span class="number" style="color: #009999;">1</span>]) << <span class="number" style="color: #009999;">8</span>)
<span class="keyword" style="font-weight: bold;">if</span> n:
s+= ord(data[i+<span class="number" style="color: #009999;">1</span>])
<span class="keyword" style="font-weight: bold;">while</span> (s >> <span class="number" style="color: #009999;">16</span>):
print(<span class="string" style="color: #dd1144;">"s >> 16: "</span>, s >> <span class="number" style="color: #009999;">16</span>)
s = (s & <span class="number" style="color: #009999;">0xFFFF</span>) + (s >> <span class="number" style="color: #009999;">16</span>)
print(<span class="string" style="color: #dd1144;">"sum:"</span>, s)
s = ~s & <span class="number" style="color: #009999;">0xffff</span>

一个小列子:

<span class="keyword" style="font-weight: bold;">s</span> = <span class="keyword" style="font-weight: bold;">socket</span>.<span class="keyword" style="font-weight: bold;">socket</span>(<span class="keyword" style="font-weight: bold;">socket</span>.AF_INET,
<span class="keyword" style="font-weight: bold;">socket</span>.SOCK_RAW,
<span class="keyword" style="font-weight: bold;">socket</span>.IPPROTO_RAW)
src_host = <span class="string" style="color: #dd1144;">"10.0.2.15"</span>
dest_host = <span class="keyword" style="font-weight: bold;">socket</span>.<span class="keyword" style="font-weight: bold;">gethostbyname</span>(<span class="string" style="color: #dd1144;">"www.reddit.com"</span>)
data = <span class="string" style="color: #dd1144;">"TEST!!"</span>
<span class="comment" style="font-style: italic; color: #999988;"># IP Header</span>
ipobj = ip(src_host, dest_host)
iph = ip_object.<span class="keyword" style="font-weight: bold;">pack</span>()
<span class="comment" style="font-style: italic; color: #999988;"># TCP Header</span>
tcpobj = tcp(<span class="number" style="color: #009999;">1234</span>, <span class="number" style="color: #009999;">80</span>)
tcpobj.data_length = len(data)  <span class="comment" style="font-style: italic; color: #999988;"># Used in pseudo header</span>
tcph = tcpobj.<span class="keyword" style="font-weight: bold;">pack</span>(ipobj.source,
ipobj.destination)
<span class="comment" style="font-style: italic; color: #999988;"># Injection</span>
packet = iph + tcph + data

Pinject.py
Running the script:
python pinject.py <span class="comment" style="font-style: italic; color: #999988;">--src=10.0.2.15 --dst=www.reddit.com</span>
[+] 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

wireshark的截图:

时间: 2024-09-19 20:38:52

Python进行TCP数据包注入(伪造)实例教程的相关文章

在linux下,python怎么才能抓到网卡上的所有TCP数据包?

问题描述 在linux下,python怎么才能抓到网卡上的所有TCP数据包? 网卡已经设置为混杂模式,能够收到mac不是本机mac的数据包,但是程序只能收到和本机ip一样的数据包,不能收到和本机ip不一样的数据包,求助.代码如下: sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP) packet_base = sock.recvfrom(1024)[0] print "receive a packet

sock-怎么用python和原始套接字发送一tcp数据包?

问题描述 怎么用python和原始套接字发送一tcp数据包? 这段代码直接把数据packet_base作为ip的载荷了,怎么才能是packet_base作为tcp的载荷呢?谢谢 sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP) sock.sendto(packet_base, 0, (IP_PACKET_IN, 12321)) sock.close() 解决方案 把你的代码修改成如下就是TCP啦:

原始套接字 tcp-用原始套接字发送TCP数据包,显示发送成功但是接收不到,求教

问题描述 用原始套接字发送TCP数据包,显示发送成功但是接收不到,求教 我需要自己构建IP数据包,在IP选项部分添加一些数据,因此用原始套接字发送TCP数据包,但是发送成功了,另一台主机接收不到,用的2003系统,不知道哪位好心人能帮助下,万分感激,谢谢 解决方案 你这个问题说的比较笼统,你是用的无连接发送吧,发送成功了,但是主机没收到,可能:1.IP包或者TCP包创建的有问题2.发送过程中,数据有丢失3.服务器的程序,在接受数据的程序上存在一些问题 解决方法:1.在客户端断点检测,查看IP和T

c#-C#网络编程使用SharpPcap.dll来抓取网络上的TCP数据包,怎么才能完整的还原抓取的数据?

问题描述 C#网络编程使用SharpPcap.dll来抓取网络上的TCP数据包,怎么才能完整的还原抓取的数据? 5C 如题,C#网络编sd程使用SharpPcap.dll来抓取网络上的TCP数据包,怎么才能完整的还原抓取的数据?我是要抓取特定的两台机器之间的数据传递,已知传递的数据包的组成规则,有这么几个问题:1.怎么才能完整的获取所有的数据包?2.获取的数据包需不需要考虑TCP数据包的重传或者错误传递的数据包? 谢谢. 解决方案 c# 使用sharppcap实现 网络抓包 使用SharpPCa

Wireshark抓包工具--TCP数据包seq ack等解读

1.Wireshark的数据包详情窗口,如果是用中括号[]括起来的,表示注释,在数据包中不占字节 2.在二进制窗口中,如"DD 3D",表示两个字节,一个字节8位 3.TCP数据包中,seq表示这个包的序号,注意,这个序号不是按1递增的,而是按tcp包内数据字节长度加上,如包内数据是21字节,而当前IP1发到IP2的包的seq是10的话,那下个IP1发到IP2的包的seq就是10+21=31 4.注意我们分析tcp包时,要以一个会话做为一个完整对象,即通讯只发生在两个IP之间,两个固定

求高手帮忙啊,服务器端怎么在python中定义和发送tcp数据包,谢谢啊

问题描述 请教高手指点,不甚感激!服务器和手机客户端通信,比如我定义的这个表,要进行socket通信users=Table('users',metadata,Column('user_id',Integer,primary_key=True),Column('nickname',String(40)),Column('sex',String),Column('age',Integer),Column('province',String),Column('city',String),Column(

tcprstat源码分析之tcp数据包分析

tcprstat是percona用来监测mysql响应时间的.不过对于任何运行在TCP协议上的响应时间,都可以用.本文主要做源码分析,如何使用tcprstat请大家查看博文<tcprstat分析服务的响应速度利器> tcprstat和tcpdump一样,使用libpcap库进行抓包,然后再通过程序对抓取的tcp包进行分析. tcprstat对tcp包分析的大概流程如下: <img src="http://www.bo56.com/wp-content/uploads/2014/

Python使用cookielib模块操作cookie的实例教程_python

cookielib是一个自动处理cookies的模块,如果我们在使用爬虫等技术的时候需要保存cookie,那么cookielib会让你事半功倍!他最常见的搭档模块就是python下的urllib和request. 核心类 1.Cookie该类实现了Netscape and RFC 2965 cookies定义的cookie标准,基本可以理解为某一条cookie数据. 部分代码如下,很多属性是不是很眼熟? self.domain_initial_dot = domain_initial_dot s

Python使用pyexiv2库操作图片的实例教程

pyexiv2是exiv2库的Python绑定,而exiv2是用于操作EXIF.IPTC和XMP图片元数据的C++程序库. 关于pyexiv2,请查看其官方网站:http://tilloy.net/dev/pyexiv2/ 目前pyexiv2貌似还没支持Python3,本文是用的 Python2.7 做的实验. 在Ubuntu中安装pyexiv2的命令为: apt-get install python-pyexiv2 在Python中使用pyexiv2主要需要注意一下几点即可: 1. impor