《Python渗透测试编程技术:方法与实践》基础篇:信息收集

第五章、信息收集

信息收集是黑盒测试中最重要的一个阶段,这里的“信息”指的是目标网络、服务器、应用程序的所有信息。	对应于网络安全渗透测试中一个极为重要的学科——情报学。
信息收集的方式分为两种:被动扫描和主动扫描。被动扫描主要指的是在目标无法察觉的情况下进行的信息收集,kali中可以用maltego、recon-NG和shodan。相比被动扫描,主动扫描的范围小很多,一般都是针对目标发送特质的数据包然后根据目标的反应来获取一些信息,这种扫描的专业性更强,需要借助扫描工具,如nmap。
本章目标——使用python编程实现:
1、目标主机是否在线;
2、目标主机所在网络结构;
3、目标主机上开放的端口,如80、135、443等。
4、目标主机所使用的操作系统,例如window7、Linux2.6.18、Android 4.1.2等。
5、目标主机上所运行的服务以及版本,例如Apache httpd 2.2.14、OpenSSH 5.3pl等。

一、主机状态扫描
处于运行状态且网络功能正常的主机被称为活跃主机,反之称为非活跃主机。
1、基于ARP的活跃主机发现技术
ARP(地址解析协议):将IP地址解析为MAC地址,主要用于以太网中。因为主机在互联网中通信用的是IP地址,而在以太网中使用的硬件地址(MAC地址)。这个具体流程在网工知识点中有学过,所以就不赘述啦~


from scapy.all import srp,Ether,ARP
dst="192.168.88.1"
#产生一个ARP数据包
ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=dst),timeout=2)
for s,r in ans:
    print("Target is alive")
    #输出活跃主机的mac地址和Ip地址
    print(r.sprintf("%Ether.src% - %ARP.psrc%"))


/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/arpPing.py
Begin emission:
Finished sending 1 packets.
*
Received 1 packets, got 1 answers, remaining 0 packets
Target is alive
#mac地址,保护隐私我改了一下mac地址本身显示的内容
ff:80:58:c0:00:09 - 192.168.88.1

Process finished with exit code 0

还可以用nmap,见下面的代码,可以扫描一个网段的主机并打印出扫描的活跃主机的结果。dst="192.168.88.1"这样的单个ip的话,就是扫描单个主机是否为活跃主机,

import nmap
target="198.168.88.0/24"
nm = nmap.PortScanner()
nm.scan(target,arguments='-sn -PR')
for host in nm.all_hosts():
    print("---------------------------------------------")
    print('Host:%s(%s)' % (host,nm[host].hostname()))
    print('State : %s' % nm[host].state())

/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/arpPing2.py
---------------------------------------------
Host:198.168.88.0()
State : up
---------------------------------------------
Host:198.168.88.1()
State : up
---------------------------------------------
Host:198.168.88.10()
State : up
#中间我删掉了一些,节省文章篇幅,之前基础篇中就有这个结果
---------------------------------------------
Host:198.168.88.9()
State : up
---------------------------------------------
Host:198.168.88.90()
State : up
---------------------------------------------
Host:198.168.88.91()
State : up
---------------------------------------------
Host:198.168.88.92()
State : up
---------------------------------------------
Host:198.168.88.93()
State : up
---------------------------------------------
Host:198.168.88.94()
State : up
---------------------------------------------
Host:198.168.88.95()
State : up
---------------------------------------------
Host:198.168.88.96()
State : up
---------------------------------------------
Host:198.168.88.97()
State : up
---------------------------------------------
Host:198.168.88.98()
State : up
---------------------------------------------
Host:198.168.88.99()
State : up

Process finished with exit code 0


基于ARP的扫描很高效,但是只能扫描同一以太网内的主机,例如主机ip为192.168.1.130,子网掩码为255.255.255.0,就ARP的扫描范围仅为192.168.1.1~192.168.1.255。如果目标地址是192.168.169.100,则无法用ip为192.168.1.130的主机进行ARP扫描了。
2、基于ICMP的活跃主机发现技术
ICMP协议是TCP/IP协议族的网络层协议,用于IP主机、路由器之间传递控制消息,其提供了多种报文,这些报文可分为两个大类:查询报文和差错报文。查询报文有四种:响应请求或应答、时间戳请求或应答、地址掩码请求或应答、路由器询问或应答;实际应用中后三种成功率很低,所以书上以第一种为例讲解了ICMP报文。
利用ICMP实现活跃主机扫描程序,核心思想:产生一个ICMP请求,并监听这个请求,若是得到了回应就说明目标主机是活跃的。

from scapy.all import sr,IP,ICMP
target="192.168.66.1"
ans,unans=sr((IP(dst= target) / ICMP()),timeout=2)
for s,r in ans:
    print(r.sprintf("%IP.src% - is alive"))

#运行结果
/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/icmpPing.py
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
192.168.66.1 - is alive

Process finished with exit code 0

使用nmap,与前面基于ARP的基本一样,只需要把地址改为不同网段的,然后把scan()的参数改为arguments='-PE -sn'-PE表示使用ICMP协议,-sn表示只测试主机状态(这在本章实验中是为了加快扫描速度)。哈哈哈,我用百度域名尝试了一下,有结果诶,还挺好玩儿的。

import nmap
target ="www.baidu.com"
nm = nmap.PortScanner()
nm.scan(target,arguments='-PE -sn')
for host in nm.all_hosts():
    print("---------------------------------------------")
    print('Host:%s(%s)' % (host, nm[host].hostname()))
    print('State : %s' % nm[host].state())

#实验结果
/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/icmpPing2.py
---------------------------------------------
Host:14.215.177.38(www.baidu.com)
State : up

Process finished with exit code 0

3、基于TCP的活跃主机发现技术
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。“三次握手 SYN+ACK”、“四次挥手 FIN+ACK”。
scapy中TCP的参数最重要的就是sport(源端口)、dport(目的端口)和flags(标志位)。flags可能的值为SYN(建立连接)、FIN(关闭连接)、ACK(响应)、PSH(有DATA数据传输)、RST(连接重置)。

#用scapy——1
from scapy.all import sr,IP,TCP
targetIP="192.168.88.1"
targetPort = 80
ans,unans=sr((IP(dst= targetIP) / TCP(dport=targetPort,flags="S")), timeout=2)
for s,r in ans:
    print(r.sprintf("%IP.src% - is alive"))
#结果1——因为端口80没开,我昨天尝试过,但是我目前还不会开端口,所以我又用百度官网尝试了第二次
/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/tcpPing.py
Begin emission:
Finished sending 1 packets.
.
Received 1 packets, got 0 answers, remaining 1 packets

Process finished with exit code 0


#用scapy——2
from scapy.all import sr,IP,TCP
targetIP="www.baidu.com"
targetPort = 80
ans,unans=sr((IP(dst= targetIP) / TCP(dport=targetPort,flags="S")), timeout=2)
for s,r in ans:
    print(r.sprintf("%IP.src% - is alive"))
 #实验结果2
/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/tcpPing.py
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
14.215.177.38 - is alive

Process finished with exit code 0


#用nmap
import nmap
target ="192.168.88.1"
nm = nmap.PortScanner()
nm.scan(target,arguments='-sT')
for host in nm.all_hosts():
    print("---------------------------------------------")
    print('Host:%s(%s)' % (host, nm[host].hostname()))
    print('State : %s' % nm[host].state())

/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/tcpPing2.py
---------------------------------------------
Host:192.168.88.1()
State : up

Process finished with exit code 0

4、基于UDP的活跃主机发现技术
UDP(User Datagram Protocol,用户数据报协议)与TCP一样用于网络中处理数据包,是一种无连接的、不可靠的传输协议。基于UDP的活跃主机发现技术与基于TCP不同,因为UDP没有三次握手,当向目标主机发送一个UDP数据包之后,目标是不会回应任何UDP数据包的,但是,如果目标主机的目标端口是关闭的,会返回一个ICMP数据包(含义为UNreachable,不可达的)。
代码和前面差不多。只是scapy中用ans,unans=sr(IP(dst= “192.168.88.1”) / UDP(dport=6667))发送一个UDP数据包,nmap中参数“-PU”表示使用的是UDP协议。

二、端口扫描
如果把服务器比作一间房子,那么端口就是通向不同房间(服务)的门。正常情况下,端口只有开放(open)和关闭(closed)两种状态。但有时候会出现(filtered)状态,表示无法获悉目标端口的真实状态,这种状态往往是由包过滤机制造成的,过滤可能来自专业的防火墙设备,路由器规则或则主机上的软件防火墙。
判断一个端口的状态其实很复杂,Nmap中集成了很多种端口扫描的方法,如果你想要深入了解,可以参阅《诸神之眼——Nmap网络安全审计技术揭秘》(ISBN:987-7-302-47326-0,清华大学出版社)。
在这里只介绍两种最常用的方法:TCP全开扫描和TCP半开扫描。以scapy为例写代码,也可以用nmap的,读者可以自行尝试~
1、基于TCP全开的端口扫描技术
思想:如果目标端口开放,则收到主机端口发出的SYN请求之后,会返回一个“SYN+ACK”回应,表示愿意接受这次连接请求,然后主机再回应一个“ACK”,这样就成功地和目标端口建立了一个TCP连接。
但如果目标端口关闭,在收到主机发送的“SYN”请求之后,会返回一个“RST”回应,表示不接受此次请求,这样就中断了这次TCP连接。另外,当主机发送“SYN”后收不任何回应页数目标端口不开放的情况之一,可能的原因有:目标主机处于非活跃状态,或者一些网络设备屏蔽了某些端口的SYN请求。

#端口关闭
from scapy.all import *
dst_ip = "192.168.66.1"
src_port = RandShort()#产生一个随机数作为主机源端口号
dst_port = 80
#构造一个SYN请求数据包
pkt = IP(dst=dst_ip)/TCP(sport=src_port, dport=dst_port, flags="S")
resp=sr1(pkt, timeout=1) #timeout的作用是指定等待回应数据包的时间,如果不指定的话,在没有数据应答时会等很久。
#resp为监听到的应答
if(str(type(resp))=="<class 'NoneType'>"):    #这里是判断resp是否为空,将其转为字符串判断,若为空字符串,则说明resp原本为空。
    print("The port %s is Closed" %(dst_port) )
elif(resp.haslayer(TCP)): #判断resp是否使用了TCP协议,如果使用了,继续判断
    if(resp.getlayer(TCP).flags == 0x12):  #flags 标志为0x12表示resp为“SYN+ACK”类型的数据包
        seq1 = resp.ack
        ack1 = resp.seq+1
        pkt_rst = IP(dst=dst_ip)/TCP(sport=src_port, dport=dst_port, seq=seq1, ack=ack1, flags=0x10);
        send(pkt_rst)
        print("The port %s is Open" %(dst_port) )
    elif(resp.getlayer(TCP).flags == 0x14):  #flags 标志为0x14表示resp为“RST”类型的数据包
        print("The port %s is Closed" % (dst_port))
#运行结果
/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/PortScan.py
Begin emission:
Finished sending 1 packets.
.
Received 1 packets, got 0 answers, remaining 1 packets
The port 80 is Closed

Process finished with exit code 0


#对比一下端口打开的状态
from scapy.all import *
dst_ip = "www.baidu.com"
src_port = RandShort()
dst_port = 80
pkt = IP(dst=dst_ip)/TCP(sport=src_port, dport=dst_port, flags="S")
resp=sr1(pkt, timeout=1)
if(str(type(resp))=="<class 'NoneType'>"):
    print("The port %s is Closed" %(dst_port) )
elif(resp.haslayer(TCP)):
    if(resp.getlayer(TCP).flags == 0x12):
        seq1 = resp.ack
        ack1 = resp.seq+1
        pkt_rst = IP(dst=dst_ip)/TCP(sport=src_port, dport=dst_port, seq=seq1, ack=ack1, flags=0x10)
        send(pkt_rst)
        print("The port %s is Open" %(dst_port) )
    elif(resp.getlayer(TCP).flags == 0x14):
        print("The port %s is Closed" % (dst_port))
#结果
/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/PortScan.py
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
.
Sent 1 packets.
The port 80 is Open

Process finished with exit code 0

2、基于TCP半开的端口扫描技术
思想:如果目标端口是开放的,那么在接到主机端口发出的SYN请求之后就会返回一个“SYN+ACK”回应,表示愿意接受这次连接请求,然后主机不再回应“ACK”,而是发送一个“RST”中断这个连接请求,这样实际上没有建立完整的TCP连接,所以称为半开。 如果目标端口是关闭的,半开和全开没有区别。半开扫描中需要考虑目标端口为filtered状态的复杂情况。

from scapy.all import *
dst_ip = "192.168.88.1"
src_port = RandShort()
dst_port = 80
pkt = IP(dst=dst_ip)/TCP(sport=src_port, dport=dst_port, flags="S")
resp=sr1(pkt, timeout=1)
if(str(type(resp))=="<class 'NoneType'>"):
    print("The port %s is Closed" %(dst_port) )
elif(resp.haslayer(TCP)):
    if(resp.getlayer(TCP).flags == 0x12):
        print("The port %s is Open" %(dst_port) )
    elif(resp.getlayer(TCP).flags == 0x14):
        print("The port %s is Closed" % (dst_port))
elif(resp.haslayer(ICMP)):
    if(int(getlayer(ICMP).type)==3 and int(resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
    #表示收到了ICMP数据包,当TCP连接的数据包被屏蔽时,一般会返回code为[1,2,3,9,10,13]这6种情况的错误消息类型数据包
    #分别对应:主机不可达、协议不可达、端口不可达、目标网络被强制禁止、目标主机被强制禁止、受限过滤机制(通信被强制禁止)。
        print("The port %s is Filtered" % (dst_port))

#结果
/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/PortScanHalf.py
Begin emission:
Finished sending 1 packets.
.
Received 1 packets, got 0 answers, remaining 1 packets
The port 80 is Closed

Process finished with exit code 0

三、服务扫描
1、常见服务扫描方式
(1)最简单的:常见服务都会运行在指定端口,如ftp运行在21端口、http运行在80端口、Telnet运行在22端口… Nmap中nmap-services库提供了所有端口和服务的对应关系。
(2)抓取软件banner的方法。很多软件在连接之后会提供一个表明自己身份信息的banner,可以编写程序来抓取这个banner以读取目标软件的信息。
(3)最优秀的办法:向目标开放的端口发送探针数据包,然后根据返回的数据包与数据库中的记录进行对比,找出具体的服务信息。Nmap扫描工具采用的这种方法,它有一股强大的Nmap-service-probe数据库,包含了世界上大部分常见软件的信息。
2、抓取软件banner的方式
书上是在192.168.168.33上运行了软件FreeFloat FTP Server并开启了21端口,所以其target = "192.168.168.33"、port = 21;运行结果为“Port in21Service:220FreeFloat FTP Server(Version 1.00)”。
书上指出:这个程序还可以进一步完善,比如用正则表达式等,读者可自行完成。另外,由于这个程序需要依赖目标工具提供的信息,所以并不通用,例如在目标的80端口运行着另一款Easy File Sharing Web Server,这个程序就会失效,会一直没有反应。

import socket
target = "www.baidu.com"
port = 80
s=socket.socket()
s.connect((target, port))
s.send(b'11111111111111111111')
service = s.recv(1024).decode()
s.close()
print('Port in {}'.format(port)+'Service:{}'.format(service))

#结果
/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/ServiceScan.py
Port in 80Service:HTTP/1.1 400 Bad Request

Process finished with exit code 0

2、使用namp库
可能是因为我kali虚拟机没有开启服务,所以扫描出的结果为空。但程序是没问题的,照着书上敲的。书上是在目标上运行了Easy File Sharing Web Server,我就不搞了,之后肯定有实际的例子的。

import sys
import nmap
if len(sys.argv) !=3:
    print('Usage:ServiceScan <IP> \n eg:ServiceScan 192.168.1.1')
    sys.exit(1)
target = sys.argv[1]
#print(target)  #这两句打印是为了看这里有没有数据,刚开始是没有的
#后来我才知道,这个程序需要在终端打开运行,并在终端输入的时候跟上参数
#我这种笨笨的初学者总是会遇到这种傻傻的问题,没救了可能~
port = sys.argv[2]
#print(port)

nm = nmap.PortScanner()
nm.scan(target, port, "-sV")
for host in nm.all_hosts():
    for proto in nm[host].all_protocols():
        lport = list(nm[host][proto].keys())
        lport.sort()
        for port in lport:
            print('port: %s \t product: %s' %(port,nm[host][proto][port]['product']))

运行结果:
在这里插入图片描述
我这边把程序在终端打开的步骤:
在这里插入图片描述
四、操作系统扫描
被动方法:抓包工具收集流经网络的数据包,再从这些数据包中分析出目标主机的操作系统。
主动方法:向目标主机发送特定数据包,对目标主机做出的回应进行分析,就有可能得知目标主机的操作系统类型。特定数据包可以是正常的网络程序如Telnet、FTP等于主机交互的数据包,也可以是一些经过构造的正常或残缺的数据包。
(1)被动方法
p0f就是一个典型的被动扫描工具。如果kali里面没有p0f,可以用sudo apt-get install p0f 安装这个工具。

 
  #启动工具                                                                           
┌──(kaligan㉿studygan)-[~/Desktop]
└─$ sudo p0f
--- p0f 3.09b by Michal Zalewski <lcamtuf@coredump.cx> ---

[+] Closed 1 file descriptor.
[+] Loaded 322 signatures from '/etc/p0f/p0f.fp'.
[+] Intercepting traffic on default interface 'eth0'.
[+] Default packet filtering configured [+VLAN].
[+] Entered main event loop.

.-[ 192.168.88.129/36922 -> 192.168.66.1/80 (syn) ]-
|
| client   = 192.168.88.129/36922
| os       = Linux 2.2.x-3.x
| dist     = 0
| params   = generic
| raw_sig  = 4:64+0:0:1460:mss*44,10:mss,sok,ts,nop,ws:df,id+:0
|
`----

.-[ 192.168.88.129/36922 -> 192.168.66.1/80 (mtu) ]-
|
| client   = 192.168.88.129/36922
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/36922 -> 192.168.66.1/80 (syn+ack) ]-
|
| server   = 192.168.66.1/80
| os       = ???
| dist     = 0
| params   = none
| raw_sig  = 4:128+0:0:1460:mss*44,0:mss::0
|
`----

.-[ 192.168.88.129/36922 -> 192.168.66.1/80 (mtu) ]-
|
| server   = 192.168.66.1/80
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/36922 -> 192.168.66.1/80 (http request) ]-
|
| client   = 192.168.88.129/36922
| app      = Firefox 10.x or newer
| lang     = English
| params   = none
| raw_sig  = 1:Host,User-Agent,Accept=[text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8],Accept-Language=[en-US,en;q=0.5],Accept-Encoding=[gzip, deflate],Connection=[keep-alive],Upgrade-Insecure-Requests=[1]:Accept-Charset,Keep-Alive:Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
|
`----

.-[ 192.168.88.129/36922 -> 192.168.66.1/80 (http response) ]-
|
| server   = 192.168.66.1/80
| app      = Apache 2.x
| lang     = none
| params   = none
| raw_sig  = 1:Date,Server,X-Powered-By=[PHP/5.6.27],Keep-Alive=[timeout=5, max=100],Connection=[Keep-Alive],Transfer-Encoding=[chunked],Content-Type:Accept-Ranges:Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9
|
`----

.-[ 192.168.88.129/54638 -> 35.244.181.201/443 (syn) ]-
|
| client   = 192.168.88.129/54638
| os       = Linux 2.2.x-3.x
| dist     = 0
| params   = generic
| raw_sig  = 4:64+0:0:1460:mss*44,10:mss,sok,ts,nop,ws:df,id+:0
|
`----

.-[ 192.168.88.129/54638 -> 35.244.181.201/443 (mtu) ]-
|
| client   = 192.168.88.129/54638
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/54638 -> 35.244.181.201/443 (syn+ack) ]-
|
| server   = 35.244.181.201/443
| os       = ???
| dist     = 0
| params   = none
| raw_sig  = 4:128+0:0:1460:mss*44,0:mss::0
|
`----

.-[ 192.168.88.129/54638 -> 35.244.181.201/443 (mtu) ]-
|
| server   = 35.244.181.201/443
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/35272 -> 117.18.237.29/80 (syn) ]-
|
| client   = 192.168.88.129/35272
| os       = Linux 2.2.x-3.x
| dist     = 0
| params   = generic
| raw_sig  = 4:64+0:0:1460:mss*44,10:mss,sok,ts,nop,ws:df,id+:0
|
`----

.-[ 192.168.88.129/35272 -> 117.18.237.29/80 (host change) ]-
|
| client   = 192.168.88.129/35272
| reason   = tstamp port
| raw_hits = 0,1,1,1
|
`----

.-[ 192.168.88.129/35272 -> 117.18.237.29/80 (mtu) ]-
|
| client   = 192.168.88.129/35272
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/35272 -> 117.18.237.29/80 (syn+ack) ]-
|
| server   = 117.18.237.29/80
| os       = ???
| dist     = 0
| params   = none
| raw_sig  = 4:128+0:0:1460:mss*44,0:mss::0
|
`----

.-[ 192.168.88.129/35272 -> 117.18.237.29/80 (mtu) ]-
|
| server   = 117.18.237.29/80
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/39544 -> 13.226.225.69/443 (syn) ]-
|
| client   = 192.168.88.129/39544
| os       = Linux 2.2.x-3.x
| dist     = 0
| params   = generic
| raw_sig  = 4:64+0:0:1460:mss*44,10:mss,sok,ts,nop,ws:df,id+:0
|
`----

.-[ 192.168.88.129/39544 -> 13.226.225.69/443 (mtu) ]-
|
| client   = 192.168.88.129/39544
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/39544 -> 13.226.225.69/443 (syn+ack) ]-
|
| server   = 13.226.225.69/443
| os       = ???
| dist     = 0
| params   = none
| raw_sig  = 4:128+0:0:1460:mss*44,0:mss::0
|
`----

.-[ 192.168.88.129/39544 -> 13.226.225.69/443 (mtu) ]-
|
| server   = 13.226.225.69/443
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/49094 -> 34.98.75.36/443 (syn) ]-
|
| client   = 192.168.88.129/49094
| os       = Linux 2.2.x-3.x
| dist     = 0
| params   = generic
| raw_sig  = 4:64+0:0:1460:mss*44,10:mss,sok,ts,nop,ws:df,id+:0
|
`----

.-[ 192.168.88.129/49094 -> 34.98.75.36/443 (mtu) ]-
|
| client   = 192.168.88.129/49094
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/49094 -> 34.98.75.36/443 (syn+ack) ]-
|
| server   = 34.98.75.36/443
| os       = ???
| dist     = 0
| params   = none
| raw_sig  = 4:128+0:0:1460:mss*44,0:mss::0
|
`----

.-[ 192.168.88.129/49094 -> 34.98.75.36/443 (mtu) ]-
|
| server   = 34.98.75.36/443
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/37000 -> 23.222.29.38/80 (syn) ]-
|
| client   = 192.168.88.129/37000
| os       = Linux 2.2.x-3.x
| dist     = 0
| params   = generic
| raw_sig  = 4:64+0:0:1460:mss*44,10:mss,sok,ts,nop,ws:df,id+:0
|
`----

.-[ 192.168.88.129/37000 -> 23.222.29.38/80 (host change) ]-
|
| client   = 192.168.88.129/37000
| reason   = tstamp port
| raw_hits = 0,2,2,2
|
`----

.-[ 192.168.88.129/37000 -> 23.222.29.38/80 (mtu) ]-
|
| client   = 192.168.88.129/37000
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/37000 -> 23.222.29.38/80 (syn+ack) ]-
|
| server   = 23.222.29.38/80
| os       = ???
| dist     = 0
| params   = none
| raw_sig  = 4:128+0:0:1460:mss*44,0:mss::0
|
`----

.-[ 192.168.88.129/37000 -> 23.222.29.38/80 (mtu) ]-
|
| server   = 23.222.29.38/80
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/54776 -> 13.227.74.100/443 (syn) ]-
|
| client   = 192.168.88.129/54776
| os       = Linux 2.2.x-3.x
| dist     = 0
| params   = generic
| raw_sig  = 4:64+0:0:1460:mss*44,10:mss,sok,ts,nop,ws:df,id+:0
|
`----

.-[ 192.168.88.129/54776 -> 13.227.74.100/443 (mtu) ]-
|
| client   = 192.168.88.129/54776
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

.-[ 192.168.88.129/54776 -> 13.227.74.100/443 (syn+ack) ]-
|
| server   = 13.227.74.100/443
| os       = ???
| dist     = 0
| params   = none
| raw_sig  = 4:128+0:0:1460:mss*44,0:mss::0
|
`----

.-[ 192.168.88.129/54776 -> 13.227.74.100/443 (mtu) ]-
|
| server   = 13.227.74.100/443
| link     = Ethernet or modem
| raw_mtu  = 1500
|
`----

打开p0f后一直是监听状态,可以按“ctrl+C”结束。
在这里插入图片描述
2、主动方法
osmatch是一个字典类型,包括‘accuracy’、‘line’、‘osclass’三个键。‘osclass’中包含了关键信息,它本身也是一个字典类型,包含了‘accuracy’(匹配度)、‘cpe’(通用平台枚举)、‘osfamily’(系统类别)、‘osgen’(第几代操作系统)、‘type’(设备类型)、‘vendor’(生产厂家)6个键。

import sys
import nmap

target = "192.168.66.1"
nm = nmap.PortScanner()
nm.scan(target, arguments="-O")
if 'osmatch' in nm[target]:
    for osmatch in nm[target]['osmatch']:
        print('Osmatch.name: {0}'.format(osmatch['name']))
        print('Osmatch.accuracy: {0}'.format(osmatch['accuracy']))
        print('Osmatch.line: {0}'.format(osmatch['line']))
        print('')
        if 'osclass' in osmatch:
            for osclass in osmatch['osclass']:
                print('Osclass.type: {0}'.format(osclass['type']))
                print('Osclass.vendor: {0}'.format(osclass['vendor']))
                print('Osclass.osfamily: {0}'.format(osclass['osfamily']))
                print('Osclass.osgen: {0}'.format(osclass['osgen']))
                print('Osclass.accuracy: {0}'.format(osclass['accuracy']))
                print('')
#运行结果
/root/PycharmProjects/socketProject/venv/bin/python /root/PycharmProjects/socketProject/OSScan.py
Osmatch.name: Microsoft Windows XP SP3
Osmatch.accuracy: 100
Osmatch.line: 85072

Osclass.type: general purpose
Osclass.vendor: Microsoft
Osclass.osfamily: Windows
Osclass.osgen: XP
Osclass.accuracy: 100

Osmatch.name: Microsoft Windows XP SP3 or Windows 7 or Windows Server 2012
Osmatch.accuracy: 100
Osmatch.line: 85385

Osclass.type: general purpose
Osclass.vendor: Microsoft
Osclass.osfamily: Windows
Osclass.osgen: XP
Osclass.accuracy: 100

Osclass.type: general purpose
Osclass.vendor: Microsoft
Osclass.osfamily: Windows
Osclass.osgen: 7
Osclass.accuracy: 100

Osclass.type: general purpose
Osclass.vendor: Microsoft
Osclass.osfamily: Windows
Osclass.osgen: 2012
Osclass.accuracy: 100


Process finished with exit code 0

猜你喜欢

转载自blog.csdn.net/weixin_49422491/article/details/125100499
今日推荐