未加星标

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

字体大小 | |
[网络安全 所属分类 网络安全 | 发布者 店小二05 | 时间 2015 | 作者 moquns ] 0人收藏点击收藏

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

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

Packet=IPHeader+TCP/UDPHeader+Data

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

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

TCP的首部格式:

0123
01234567890123456789012345678901
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|SourcePort|DestinationPort|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|SequenceNumber|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|AcknowledgmentNumber|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Data||U|A|P|R|S|F||
|Offset|Reserved|R|C|S|S|Y|I|Window|
|||G|K|H|T|N|N||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Checksum|UrgentPointer|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Options|Padding|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|data|
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

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

s=socket.socket(socket.AF_INET,socket.SOCK_RAW,)

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

classip(object):
def__init__(self,source,destination):
self.version=4
self.ihl=5#InternetHeaderLength
self.tos=0#TypeofService
self.tl=0#totallengthwillbefilledbykernel
self.id=54321
self.flags=0#Morefragments
self.offset=0
self.ttl=255
self.protocol=socket.IPPROTO_TCP
self.checksum=0#willbefilledbykernel
self.source=socket.inet_aton(source)
self.destination=socket.inet_aton(destination)
defpack(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)

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

ipobj=ip("127.0.0.1","127.0.0.2")#Creatinganipobjectinstancei
pobj.source="localhost"#ChangingIPelementvalue

构造TCP头部信息

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

classtcp(object):
def__init__(self,srcp,dstp):
self.srcp=srcp
self.dstp=dstp
self.seqn=0
self.ackn=0
self.offset=5#Dataoffset:5x4=20bytes
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=""
defpack(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(&#039;!HHLLBBHHH&#039;,
self.srcp,
self.dstp,
self.seqn,
self.ackn,
data_offset,
flags,
self.window,
self.checksum,
self.urgp)
#pseudoheaderfields
source_ip=source
destination_ip=destination
reserved=0
protocol=socket.IPPROTO_TCP
total_length=len(tcp_header)+len(self.payload)
#Pseudoheader
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(&#039;H&#039;,tcp_checksum)+struct.pack(&#039;!H&#039;,self.urgp)

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

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

01234567890123456789012345678901
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|SourceIPaddress|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|DestinationIPaddress|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Reserved|Protocol|TotalLength|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ SourceIPaddress(32bits):发送者的IP地址
DestinationIPaddress(32bits):接受者的IP地址
Reserved(8bits):清零
Protocol(8bits):传输协议(6为TCP,17为UDP)

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

构造头部字段

source_ip=source
destination_ip=destination
reserved=0
protocol=socket.IPPROTO_TCP

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

#伪造头部
psh=struct.pack("!4s4sBBH",
source_ip,
destination_ip,
reserved,
protocol,
total_length)
psh=psh+tcp_header+self.payload

校验函数:

defchecksum(data):
s=0
n=len(data)%2
foriinrange(0,len(data)-n,2):
s+=ord(data[i])+(ord(data[i+1])<<8)
ifn:
s+=ord(data[i+1])
while(s>>16):
print("s>>16:",s>>16)
s=(s&0xFFFF)+(s>>16)
print("sum:",s)
s=~s&0xffff

一个小列子:

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!!"
#IPHeader
ipobj=ip(src_host,dest_host)
iph=ip_object.pack()
#TCPHeader
tcpobj=tcp(1234,80)
tcpobj.data_length=len(data)#Usedinpseudoheader
tcph=tcpobj.pack(ipobj.source,
ipobj.destination)
#Injection
packet=iph+tcph+data Pinject.py
Runningthescript:
pythonpinject.py--src=10.0.2.15--dst=www.reddit.com
[+]LocalMachine:10.0.2.15
[+]RemoteMachine:198.41.209.142
[+]Rawscoketcreated
[+]Datatoinject:TEST!!
[+]ConstructingIPHeader
[+]ConstructingTCPHeader

wireshark的截图:


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

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

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

本文网络安全相关术语:网络安全工程师 网络信息安全 网络安全技术 网络安全知识

分页:12
转载请注明
本文标题:使用Python进行TCP数据包注入(伪造)
本站链接:http://www.codesec.net/view/57748.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 网络安全 | 评论(0) | 阅读(1361)