0x01.Socket模块
安装socket模块
pip install socketssh
重要的函数(socket.py)
import socket
# --------------------------------------------------------
# s = socket.socket() #初始化tcp类型的socket
# print(s)
# s.bing(('127.0.0.1', 2345)) #初始化socket,bing((host,port))
# s.listen(5) #最大连接数
# s.connect(('127.0.0.1', 2345)) #客户端连接
# s.sendall(bytes("hello,my friend?", encoding="utf-8")) #发送字符到socket
# s.recv(1024) #接受数据,接受的长度
# ---------------------------------------------------------
服务端的编写(server.py)
import socket
# --------------------------------------------------------
# s = socket.socket() #初始化tcp类型的socket
# print(s)
# s.bing(('127.0.0.1', 2345)) #初始化socket,bing((host,port))
# s.listen(5) #最大连接数
# s.connect(('127.0.0.1', 2345)) #客户端连接
# s.sendall(bytes("hello,my friend?", encoding="utf-8")) #发送字符到socket
# s.recv(1024) #接受数据,接受的长度
# ---------------------------------------------------------
可能会出现的问题:客户端接收不到字符。
解决办法:发送的字符使用bytes函数转换
客户端的编写(client.py)
import socket
s2 = socket.socket()
s2.connect(('127.0.0.1',1234))
data = s2.recv(1024)
s2.close()
print('received:', repr(data))
0x02.python-nmap模块
安装python-nmap模块
pip install python-nmap
编写出一个自定义输出的扫描模块(基于 nmap)
import nmap
nm = nmap.PortScanner() #定义扫描类
ip = input('please input host_ip(eg:192.168.1.1, 192.168.1.1\\24):')
port = input('please input port(eg:80,1-1024,default:1-1024):')
if port == '':
port = '1-1024'
arguments = input('please input arguments(eg:-sP,-PR,-sS,-sT,-O,-sV,default:-sV):')
if arguments == '':
arguments = '-sV'
nm.scan(ip, port, arguments) #对指定目标进行扫描
for host in nm.all_hosts(): #对扫描的主机进行遍历
print("-"*100)
print(nm.command_line()) #显示扫描命令行
print('Host : %s (%s)'% (host,nm[host].hostname())) #输出扫描主机名
print('State : %s'% nm[host].state()) #输出主机登录状态
for proto in nm[host].all_protocols(): #对获取到的网络协议类型进行遍历
print("-"*100)
print('Protocol : %s' % proto) #输出协议类型
lport = nm[host][proto].keys() #获取TCP所有的端口号
for port in lport: #对端口号进行遍历
print('port : %s\t state : %s\t product : %s\t' % (port,nm[host][proto][port]['state'],nm[host][proto][port]['product']))
#食醋胡端口号,状态,产品信息
可能会出现的问题: 提示partially initialized module ‘nmap‘ has no attribute ‘PortScanner‘…
解决办法:传送门
0x03.Scapy模块
a.基本操作
scapy可以在kali中直接运行,采用命令行交互模式
┌──(root💀kali)-[~]
└─# scapy
INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().
aSPY//YASa
apyyyyCY//////////YCa |
sY//////YSpcs scpCY//Pp | Welcome to Scapy
ayp ayyyyyyySCP//Pp syY//C | Version 2.4.4
AYAsAYYYYYYYY///Ps cY//S |
pCCCCY//p cSSps y//Y | https://github.com/secdev/scapy
SPPPP///a pP///AC//Y |
A//A cyP////C | Have fun!
p///Ac sC///a |
P////YCpc A//A | Craft packets before they craft
scccccp///pSP///p p//Y | you.
sY/////////y caa S//P | -- Socrate
cayCyayP//Ya pY/Ya |
sY/PsY////YCc aC//Yp
sc sccaCY//PCypaapyCP//YSs
spCPY//////YPSps
ccaacs
using IPython 7.20.0
>>>
定义数据包
>>> ip=IP()
>>> ip
<IP |>
>>>
IP最重要的就是两个属性,一个src,一个dst
构造一个发往192.168.1.110的ip数据包
>>> ip=IP(dst="192.168.1.110")
>>> ip
<IP dst=192.168.1.110 |>
>>>
发给一个ip范围
>>> ip=IP(dst="192.168.1.1/24")
>>> ip
<IP dst=Net('192.168.1.1/24') |>
>>>
查看每一个数据包
>>> [p for p in ip]
[<IP dst=192.168.1.0 |>,
<IP dst=192.168.1.1 |>,
<IP dst=192.168.1.2 |>,
<IP dst=192.168.1.3 |>,
<IP dst=192.168.1.4 |>,
<IP dst=192.168.1.5 |>,
<IP dst=192.168.1.6 |>,
<IP dst=192.168.1.7 |>,
<IP dst=192.168.1.8 |>,
<IP dst=192.168.1.9 |>,
....
<IP dst=192.168.1.255 |>]
>>>
使用Ether命令够着ARP请求和答应包
>>> Ether(dst="ff:ff:ff:ff:ff:ff")
<Ether dst=ff:ff:ff:ff:ff:ff |>
scapy的分层通过符号“/”实现,一个数据包可以由多层协议组成,下面是构造一个Ether()/IP()/TCP()来完成一个数据包
>>> Ether()/IP()/TCP()
<Ether type=IPv4 |<IP frag=0 proto=tcp |<TCP |>>>
>>>
构造一个http数据包
IP()TCP()/“GET/HTTP/1.0/r/n/r/n”
使用ls查看类属性,例如Ether
>>> ls(Ether())
WARNING: Mac address to reach destination not found. Using broadcast.
dst : DestMACField = 'ff:ff:ff:ff:ff:ff' (None)
src : SourceMACField = '00:0c:29:0e:a4:2d' (None)
type : XShortEnumField = 36864 (36864)
>>>
ip属性,并对需要的属性进行设置
>>> IP(src="192.168.1.1",dst="192.168.1.110",ttl=64)
<IP ttl=64 src=192.168.1.1 dst=192.168.1.110 |>
>>>
b.发送接收函数
send()和sendp(),前者用来发送IP数据包,在第二层,后者用来发送Ether数据包,在第三层。
>>> send(IP(src="192.168.1.1",dst="192.168.1.110"))
.
Sent 1 packets.
>>> sendp(Ether(dst="ff:ff:ff:ff:ff:ff"))
.
Sent 1 packets.
发送成功会显示Sent 1 packets.
如果希望发送的内容是一个随机填充的数据包,而且要保证数据包的正确性,可以使用fuzz()函数,例如,构造一个发往192.168.1.1的TCP数据包
>>> send(IP(dst="192.168.1.1")/fuzz(TCP()))
.
Sent 1 packets.
>>>
三个接收发送数据包函数:
sr(),sr1(),srp(),其中sr()和sr1()用于第三层,ip或arp等,arp()用于第二层,Ether
构造一个向192.168.1.110发送一个ICMP数据包
>>> sr(IP(dst="192.168.1.110")/ICMP())
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
(<Results: TCP:0 UDP:0 ICMP:1 Other:0>,
<Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)
received表示收到的数据包个数,answers表示对应的应答数据包
sr()函数由两个返回值,一个是收到应答的包和对应的应答,一个是未收到应答的包
>>> ans,unans=sr(IP(dst="192.168.1.110")/ICMP())
Begin emission:
Finished sending 1 packets.
...*
Received 4 packets, got 1 answers, remaining 0 packets
>>> ans
<Results: TCP:0 UDP:0 ICMP:1 Other:0>
>>> unans
<Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>
>>>
>>>> ans.summary()
IP / ICMP 192.168.1.104 > 192.168.1.110 echo-request 0 ==> IP / ICMP 192.168.1.110 > 192.168.1.104 echo-reply 0 / Padding
>>> unans.summary()
>>>
使用summary可以查看包的内容
sr1()与sr()基本一样,但是只返回一个应答的包
>>> pr =sr1(IP(dst="192.168.1.110")/ICMP())
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
>>> pr
<IP version=4 ihl=5 tos=0x0 len=28 id=28518 flags= frag=0 ttl=128 proto=icmp chksum=0x4754 src=192.168.1.110 dst=192.168.1.104 |<ICMP type=echo-reply code=0 chksum=0xffff id=0x0 seq=0x0 |<Padding load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>>
>>>
一般可以使用sr1()函数来测试某个端口是否开放,采用半开扫描(SYN)
>>> sr1(IP(dst="192.168.1.110")/TCP(dport=445,flags="S"))
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
<IP version=4 ihl=5 tos=0x0 len=44 id=28550 flags=DF frag=0 ttl=128 proto=tcp chksum=0x71f src=192.168.1.110 dst=192.168.1.104 |<TCP sport=microsoft_ds dport=ftp_data seq=1137720698 ack=1 dataofs=6 reserved=0 flags=SA window=65392 chksum=0x9162 urgptr=0 options=[('MSS', 1460)] |<Padding load='\x00\x00' |>>>
>>>
445端口开放
>>> sr1(IP(dst="192.168.1.110")/TCP(dport=80,flags="S"))
Begin emission:
Finished sending 1 packets.
............................................................................................................
80端口未开放
c.sniff()函数
捕获的数据包不会实时显示,只有当使用Ctrl+C强制暂停,才会显示
>>> sniff()
^C<Sniffed: TCP:142 UDP:191 ICMP:0 Other:26>
使用参数过滤,例如指捕获192.168.1.110有关的数据包
>>> sniff(filter="host 192.168.1.110")
^C<Sniffed: TCP:17 UDP:7 ICMP:0 Other:0>
>>>
也可以用来指定协议,可以使用or和and
整合一下:
filter= 筛选ip和协议类型等
iface= 指定进行监听的网卡
count= 指定监听数据包的数量
下面构造一个监听192.168.1.110的3个icmp数据包,使用eth0网卡,由于基本没有人向目标发icmp数据包,要自己构建一个,ping即可
ping 192.168.1.110
>>> sniff(filter="host 192.168.1.110 and icmp",count=3,iface="eth0")
<Sniffed: TCP:0 UDP:0 ICMP:3 Other:0>
这时候,可以使用_来查看结果,并赋值给变量,查看内容
>>> _
<Sniffed: TCP:0 UDP:0 ICMP:3 Other:0>
>>> a=_
>>> a.summary()
Ether / IP / ICMP 192.168.1.104 > 192.168.1.110 echo-request 0 / Raw
Ether / IP / ICMP 192.168.1.110 > 192.168.1.104 echo-reply 0 / Raw
Ether / IP / ICMP 192.168.1.104 > 192.168.1.110 echo-request 0 / Raw
>>>
d.简单的任务实现
任务一:实现一次ACK类型的端口扫描,例如,对192.168.1.110的21,135,443,445端口是否屏蔽进行扫描,注意是屏蔽不是关闭,采用ACK模式扫描
>>> ans,unans=sr(IP(dst="192.168.1.110")/TCP(dport=[21,135,443,445],flags="A"
...: ))
Begin emission:
Finished sending 4 packets.
...............................................................................................................................................................................................................................................................................................................................................^C
正常应该会有包显示,但是本人这个一直无响应,判定为屏蔽状态
任务二:一个简单的端口扫描器
正常情况下,一个端口处于屏蔽状态,那么它不会产生任何响应报文,如果开放,那么当它收到syn数据包后,会回应个一个ack数据包,反之,端口处于关闭状态时,收到一个syn数据包后,会回应一个rst数据包。(使用fuzz()填充数据包,否则可能端口不响应)
>>> ans,unans=sr(IP(dst="192.168.1.1")/fuzz(TCP(dport=[80],flags="S")))
Begin emission:
Finished sending 1 packets.
..*
Received 3 packets, got 1 answers, remaining 0 packets
接下来,如果r[TCP].flags18,则表示返回数据包的值为0x012(SYN,ACK),为开放状态,如果r[TCP].flags20则表示关闭,数值为0x014(RST,ACK)
>>> for s,r in ans:
...: if r[TCP].flags==18:
...: print("port 80 up")
...:
port 80 up