主动信息收集之端口扫描

一、端口扫描

端口对应网络服务及应用端程序

服务端程序的漏洞通过端口攻入

发现开放的端口

更具体的攻击面

注意,该阶段是针对存在的IP扫描的

二、UDP端口扫描

  • 假设ICMP port-unreachable响应代表端口关闭
  • 目标系统不响应ICMP port-unreachable时,可能产生误判
  • 完整的UPD应用层请求
  • 准确性高
  • 耗时巨大

1、Scapy UDP Scan

端口关闭: ICMP port-unreachable

端口开放:没有回包

了解每一种基于UDP的应用层包结构很有帮助(即可针对性扫描,但难度太大)

与三层相同的技术

误判

(1)Scapy

命令基本格式

sr1 (IP(dst="1.1.1.1")/UDP(dport= 53),timeout=1 ,verbose=1)

示例:

复制代码
┌──(root💀kali)-[/home/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   | We are in France, we say Skappee.
       scccccp///pSP///p          p//Y   | OK? Merci.
      sY/////////y  caa           S//P   |             -- Sebastien Chabal
       cayCyayP//Ya              pY/Ya   |
        sY/PsY////YCc          aC//Yp 
         sc  sccaCY//PCypaapyCP//YSs  
                  spCPY//////YPSps    
                       ccaacs         
                                       using IPython 7.22.0
>>> i=IP()
>>> u=UDP()
>>> iu=(i/u)
>>> iu.display()
###[ IP ]### 
  version= 4
  ihl= None
  tos= 0x0
  len= None
  id= 1
  flags= 
  frag= 0
  ttl= 64
  proto= udp
  chksum= None
  src= 127.0.0.1
  dst= 127.0.0.1
  \options\
###[ UDP ]### 
     sport= domain
     dport= domain        #默认53
     len= None
     chksum= None

>>> iu[IP].dst="10.10.10.129"   #目标机
>>> iu[UDP].dport=53         #指定想要测试的端口(个人目标机53未开放)
>>> iu.display()
###[ IP ]### 
  version= 4
  ihl= None
  tos= 0x0
  len= None
  id= 1
  flags= 
  frag= 0
  ttl= 64
  proto= udp
  chksum= None
  src= 10.10.10.135
  dst= 10.10.10.129
  \options\
###[ UDP ]### 
     sport= domain
     dport= domain
     len= None
     chksum= None

>>> a=sr1(iu)            #发包,注意一般是要加上timeout的,因为我的目标机上的53未开放,所以偷个懒没加
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
>>> a.display()
###[ IP ]### 
  version= 4
  ihl= 5
  tos= 0xc0
  len= 56
  id= 3785
  flags= 
  frag= 0
  ttl= 64
  proto= icmp
  chksum= 0x4221
  src= 10.10.10.129
  dst= 10.10.10.135
  \options\
###[ ICMP ]### 
     type= dest-unreach
     code= port-unreachable      #端口未开
     chksum= 0x2632
     reserved= 0
     length= 0
     nexthopmtu= 0
###[ IP in ICMP ]### 
        version= 4
        ihl= 5
        tos= 0x0
        len= 28
        id= 1
        flags= 
        frag= 0
        ttl= 64
        proto= udp
        chksum= 0x51b5
        src= 10.10.10.135
        dst= 10.10.10.129
        \options\
###[ UDP in ICMP ]### 
           sport= domain
           dport= domain
           len= 8
           chksum= 0xd658

>>> iu[UDP].dport=137        #测试开放开放端口137
>>> a2=sr1(iu,timeout=1,verbose=1)
Begin emission:
Finished sending 1 packets.

Received 1 packets, got 0 answers, remaining 1 packets      #注意这种情况,仅能得出目标端口“可能”是开放的
>>> 
复制代码

抓包截图

  • 53端口测试

  • 137端口测试

(2)Scapy脚本

./udp_ scan.py 1.1.1.1 1 100

 脚本待补……

2、Nmap

命令基本格式

nmap -sU 1.1.1.1 -p 起始端口号  终止端口号
nmap -iL iplist.txt -sU -p 1-200
  • 默认的1000个参数
  • ICMP host-unreachable

示例:

复制代码
┌──(root💀kali)-[/home/kali]
└─# nmap -sU 10.10.10.129 -p 53
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-28 20:41 EST
Nmap scan report for 10.10.10.129
Host is up (0.00044s latency).

PORT   STATE         SERVICE
53/udp open|filtered domain
MAC Address: 00:0C:29:DE:5D:BA (VMware)

Nmap done: 1 IP address (1 host up) scanned in 0.41 seconds
┌──(root💀kali)
-[/home/kali] └─# nmap -sU 10.10.10.129 -p 0-200 Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-28 20:40 EST Stats: 0:03:11 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 90.93% done; ETC: 20:43 (0:00:19 remaining) Stats: 0:03:11 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 91.43% done; ETC: 20:43 (0:00:18 remaining) Stats: 0:03:30 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 99.67% done; ETC: 20:43 (0:00:01 remaining) Stats: 0:03:32 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 99.99% done; ETC: 20:43 (0:00:00 remaining) Stats: 0:03:32 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 99.99% done; ETC: 20:43 (0:00:00 remaining) Stats: 0:03:33 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 99.99% done; ETC: 20:43 (0:00:00 remaining) Stats: 0:03:34 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 99.99% done; ETC: 20:43 (0:00:00 remaining) Stats: 0:03:43 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 99.99% done; ETC: 20:44 (0:00:00 remaining) Stats: 0:03:44 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 99.99% done; ETC: 20:44 (0:00:00 remaining) Stats: 0:03:44 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 99.99% done; ETC: 20:44 (0:00:00 remaining) Stats: 0:03:45 elapsed; 0 hosts completed (1 up), 1 undergoing UDP Scan UDP Scan Timing: About 99.99% done; ETC: 20:44 (0:00:00 remaining) Nmap scan report for 10.10.10.129 Host is up (0.00058s latency). Not shown: 199 closed ports PORT STATE SERVICE 137/udp open|filtered netbios-ns 138/udp open|filtered netbios-dgm MAC Address: 00:0C:29:DE:5D:BA (VMware) Nmap done: 1 IP address (1 host up) scanned in 228.15 seconds
复制代码

三、TCP端口扫描

  • 基于连接的协议
  • 三次握手
  • 隐蔽扫描(SYN)
  • 不建立完整连接(也就是说,src发完SYN,收到dst响应的SYN+ACK后不再发ACK)
  • 应用日志不记录扫描行为——隐蔽
  • 僵尸扫描
  • 图解扫描原理

  • 极度隐蔽
  • 实施条件苛刻
  • 可伪造源地址
  • 但难度越来越大,因为边界路由器基本都加入了防地址伪造的策略
  • 僵尸机选择
  • 闲置的系统
  • 系统使用递增的IPID(随机的无法实现)
  • 全连接扫描
  • 不隐蔽,容易触发网络层的入侵检测系统,自己的 IP 也会被记录。
  • 所有的TCP扫描方式
  • 都是基于三次握手的变化
  • 来判断目标端口状态

 1、隐蔽端口扫描

(1)Scapy

 示例(端口开放的情况):

复制代码
┌──(root💀kali)-[/home/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   | To craft a packet, you have to be a
       scccccp///pSP///p          p//Y   | packet, and learn how to swim in
      sY/////////y  caa           S//P   | the wires and in the waves.
       cayCyayP//Ya              pY/Ya   |        -- Jean-Claude Van Damme
        sY/PsY////YCc          aC//Yp    |
         sc  sccaCY//PCypaapyCP//YSs  
                  spCPY//////YPSps    
                       ccaacs         
                                       using IPython 7.22.0
>>> i=IP()
>>> t=TCP()
>>> it=(i/t)
>>> it.display()
###[ IP ]### 
  version= 4
  ihl= None
  tos= 0x0
  len= None
  id= 1
  flags= 
  frag= 0
  ttl= 64
  proto= tcp
  chksum= None
  src= 127.0.0.1
  dst= 127.0.0.1
  \options\
###[ TCP ]### 
     sport= ftp_data
     dport= http
     seq= 0
     ack= 0
     dataofs= None
     reserved= 0
     flags= S        #发的SYN包
     window= 8192
     chksum= None
     urgptr= 0
     options= []

>>> it[IP].dst="10.10.10.129"
>>> a=sr1(it)
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
>>> a.display()        #查看回包数据
###[ IP ]### 
  version= 4
  ihl= 5
  tos= 0x0
  len= 44
  id= 0
  flags= DF
  frag= 0
  ttl= 64
  proto= tcp
  chksum= 0x11b1
  src= 10.10.10.129
  dst= 10.10.10.135
  \options\
###[ TCP ]### 
     sport= http
     dport= ftp_data
     seq= 793215637
     ack= 1
     dataofs= 6
     reserved= 0
     flags= SA      #目标机回了个SYN+ACK数据包 =>端口是开着的
     window= 5840
     chksum= 0xa5e9
     urgptr= 0
     options= [('MSS', 1460)]
###[ Padding ]### 
        load= '\x00\x00'
复制代码

wireshark抓包分析

备注:SYN包是 scapy 发的,对于操作系统而言它并不知道,为此突然收到SYN+ACK包时,内核认为该包是个非法包,会直接回个RST包中断连接

 示例(端口关闭的情况):

复制代码
>>> it[TCP].dport=88
>>> a=sr1(it)
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
>>> a.display()
###[ IP ]### 
  version= 4
  ihl= 5
  tos= 0x0
  len= 40
  id= 0
  flags= DF
  frag= 0
  ttl= 64
  proto= tcp
  chksum= 0x11b5
  src= 10.10.10.129
  dst= 10.10.10.135
  \options\
###[ TCP ]### 
     sport= kerberos
     dport= ftp_data
     seq= 0
     ack= 1
     dataofs= 5
     reserved= 0
     flags= RA          #RST+ACK=>端口是关闭的
     window= 0
     chksum= 0x8648
     urgptr= 0
     options= []
###[ Padding ]### 
        load= '\x00\x00\x00\x00\x00\x00'
复制代码

wireshark抓包

(2)Scapy脚本

  •  tcp_scan.py
复制代码
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
import sys

if len(sys.argv)!=4:
    print("Usage - ./scapy.py  [Target-IP]  [First Port]  [Last Port]")
    print("Example - ./scapy.py  10.10.10.1  1  100")
    print("Example will TCP SYN scan ports 1 through 100 on 10.10.10.1")
    sys.exit()
    
ip=sys.argv[1]
start=int(sys.argv[2])
end=int(sys.argv[3])

for port in range(start,end):
    a=sr1(IP(dst=ip)/TCP(dport=port),timeout=1,verbose=0)
    if a==None:
        pass
    else:
        if int(a[TCP].flags==18):      #为什么=18,自己抓个回包,查看下flags(转为10进制)字段就明白了
            print(port)
        else :
            pass
复制代码

示例:

┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# python3 ./syn_scapy.py 10.10.10.129 1 100
21
22
80

 注意,有时会被防火墙屏蔽掉

(3)nmap

 示例:

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nmap -sS  10.10.10.129  -p 21,22,25,80,143 
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-28 21:35 EST
Nmap scan report for 10.10.10.129
Host is up (0.00035s latency).

PORT    STATE  SERVICE
21/tcp  open   ftp
22/tcp  open   ssh
25/tcp  closed smtp
80/tcp  open   http
143/tcp open   imap
MAC Address: 00:0C:29:DE:5D:BA (VMware)

Nmap done: 1 IP address (1 host up) scanned in 13.41 seconds
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nmap -sS  10.10.10.129  -p 1-100          
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-28 21:37 EST
Nmap scan report for 10.10.10.129
Host is up (0.00017s latency).
Not shown: 97 closed ports
PORT   STATE SERVICE
21/tcp open  ftp
22/tcp open  ssh
80/tcp open  http
MAC Address: 00:0C:29:DE:5D:BA (VMware)

Nmap done: 1 IP address (1 host up) scanned in 13.27 seconds
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nmap -sS  10.10.10.129  -p 22             
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-28 21:40 EST
Nmap scan report for 10.10.10.129
Host is up (0.0033s latency).

PORT   STATE SERVICE
22/tcp open  ssh
MAC Address: 00:0C:29:DE:5D:BA (VMware)

Nmap done: 1 IP address (1 host up) scanned in 13.36 seconds
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nmap -sS -iL ./iplist.txt -p 80,21,22,25 
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-28 21:43 EST
Nmap scan report for 10.10.10.129
Host is up (0.00038s latency).

PORT   STATE  SERVICE
21/tcp open   ftp
22/tcp open   ssh
25/tcp closed smtp
80/tcp open   http
MAC Address: 00:0C:29:DE:5D:BA (VMware)

Nmap done: 2 IP addresses (1 host up) scanned in 14.57 seconds
复制代码

(4)hping3

注意:hping3不做逆地址解析 

示例(基本用法):

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# hping3 10.10.10.129 --scan 80 -S
Scanning 10.10.10.129 (10.10.10.129), port 80
1 ports to scan, use -V to see all the replies
+----+-----------+---------+---+-----+-----+-----+
|port| serv name |  flags  |ttl| id  | win | len |
+----+-----------+---------+---+-----+-----+-----+
   80 http       : .S..A...  64     0  5840    46
All replies received. Done.
Not responding ports: 
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# hping3 10.10.10.129 --scan 80,21,22,25,443 -S
Scanning 10.10.10.129 (10.10.10.129), port 80,21,22,25,443
5 ports to scan, use -V to see all the replies
+----+-----------+---------+---+-----+-----+-----+
|port| serv name |  flags  |ttl| id  | win | len |
+----+-----------+---------+---+-----+-----+-----+
   21 ftp        : .S..A...  64     0  5840    46
   22 ssh        : .S..A...  64     0  5840    46
   80 http       : .S..A...  64     0  5840    46
All replies received. Done.
Not responding ports: 
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# hping3 10.10.10.129 --scan 100-200 -S        
Scanning 10.10.10.129 (10.10.10.129), port 100-200
101 ports to scan, use -V to see all the replies
+----+-----------+---------+---+-----+-----+-----+
|port| serv name |  flags  |ttl| id  | win | len |
+----+-----------+---------+---+-----+-----+-----+
  139 netbios-ssn: .S..A...  64     0  5840    46
  143 imap2      : .S..A...  64     0  5840    46
All replies received. Done.
Not responding ports: 
复制代码

示例(高级):

 扫描10.10.10.129的1-25端口,并欺骗 10.10.10.129 自己(10.10.10.135)是 10.10.10.140 

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# hping3 -c 25 -S --spoof 10.10.10.140 -p ++1  10.10.10.129      #-c:指定发包数 -S:指定包类型 --spoof ip1:欺骗对方放自己是ip1(即伪造自己的地址) -p ++1:端口号每次加 1
HPING 10.10.10.129 (eth0 10.10.10.129): S set, 40 headers + 0 data bytes
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=1 flags=RA seq=0 win=0 rtt=11.4 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=2 flags=RA seq=1 win=0 rtt=3.2 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=3 flags=RA seq=2 win=0 rtt=4.0 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=4 flags=RA seq=3 win=0 rtt=5.8 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=5 flags=RA seq=4 win=0 rtt=7.5 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=6 flags=RA seq=5 win=0 rtt=3.4 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=7 flags=RA seq=6 win=0 rtt=9.4 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=8 flags=RA seq=7 win=0 rtt=6.0 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=9 flags=RA seq=8 win=0 rtt=9.5 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=10 flags=RA seq=9 win=0 rtt=3.3 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=11 flags=RA seq=10 win=0 rtt=5.9 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=12 flags=RA seq=11 win=0 rtt=3.0 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=13 flags=RA seq=12 win=0 rtt=5.5 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=14 flags=RA seq=13 win=0 rtt=5.4 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=15 flags=RA seq=14 win=0 rtt=5.5 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=16 flags=RA seq=15 win=0 rtt=5.7 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=17 flags=RA seq=16 win=0 rtt=6.0 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=18 flags=RA seq=17 win=0 rtt=6.1 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=19 flags=RA seq=18 win=0 rtt=2.9 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=20 flags=RA seq=19 win=0 rtt=3.0 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=21 flags=SA seq=20 win=5840 rtt=4.0 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=22 flags=SA seq=21 win=5840 rtt=5.9 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=23 flags=RA seq=22 win=0 rtt=2.4 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=24 flags=RA seq=23 win=0 rtt=3.0 ms
len=46 ip=10.10.10.129 ttl=64 DF id=0 sport=25 flags=RA seq=24 win=0 rtt=2.2 ms

--- 10.10.10.129 hping statistic ---
25 packets transmitted, 25 packets received, 0% packet loss
round-trip min/avg/max = 2.2/5.2/11.4 ms
复制代码

wireshark抓包分析

 注意,欺骗完后在kali主机无法查扫描结果,只能登陆伪造的IP对应的主机查看或做端口镜像。

很神奇,这里 kali(10.10.10.135) 为什么能抓到 10.10.10.129 发往 10.10.10.140 的数据包???,没搞明白!!!原因:由于MAC没有伪造,又在同一局域网里所以依旧可以给Kali回包!

2、全连接端口扫描

(1)Scapy

  • Syn扫描不需要raw_packets
  • 内核认为syn/ack是非法包,直接发rst终断连接
  • 全连接扫描对scapy比较困难

注意,由第 2 点得出直接用Scapy是无法实现全连接扫描的,要想用scapy实现全连接端口扫描,就不能让内核往目标机发RST包,所以我们可用防火墙拦截内核发往目标机的RST包。

直接在scapy的操作与脚本的操作类似,此处不再单独演示,详见Scapy脚本处的分析:

(2)Scapy脚本

tcp_scan2.py

复制代码
#!/usr/bin/python
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

SYN=IP(dst="10.10.10.129")/TCP(dport=80,flags='S')

print("-- SENT --")
SYN.display()

print("\n\n-- RECEIVED --")
response=sr1(SYN,timeout=1,verbose=0)
response.display()

if int(response[TCP].flags==18):
    print("\n\n-- SENT --")
    A=IP(dst="10.10.10.129")/TCP(dport=80,flags='A',ack=(response[TCP].seq+1))
    A.display()
    print("\n\n-- RECEIVED --")
    response2=sr1(A,timeout=1,verbose=0)
    response2.display()
else:
    print("SYN-ACK not returned!")
复制代码

防火墙设置之前的测试(分析见注释):

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# python3 ./tcp_scan2.py                   
-- SENT --             #发包
###[ IP ]### 
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     = 
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = None
  src       = 10.10.10.135
  dst       = 10.10.10.129
  \options   \
###[ TCP ]### 
     sport     = ftp_data
     dport     = http
     seq       = 0
     ack       = 0
     dataofs   = None
     reserved  = 0
     flags     = S        #第一次握手包类型(SYN)
     window    = 8192
     chksum    = None
     urgptr    = 0
     options   = []



-- RECEIVED --           #收包
###[ IP ]### 
  version   = 4
  ihl       = 5
  tos       = 0x0
  len       = 44
  id        = 0
  flags     = DF
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = 0x11b1
  src       = 10.10.10.129
  dst       = 10.10.10.135
  \options   \
###[ TCP ]### 
     sport     = http
     dport     = ftp_data
     seq       = 418625511
     ack       = 1
     dataofs   = 6
     reserved  = 0
     flags     = SA          #第二次握手包类型(SYN+ACK)
     window    = 5840
     chksum    = 0x86eb
     urgptr    = 0
     options   = [('MSS', 1460)]
###[ Padding ]### 
        load      = '\x00\x00'



-- SENT --          #注意,该包是理论上的第三次握手包,实际上在第二次握手结束,发该包之前操作系统内核已经发了一个RST包给目标机中断连接,会导致src发完该包后会收到RST包(参见后面)
###[ IP ]### 
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     = 
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = None
  src       = 10.10.10.135
  dst       = 10.10.10.129
  \options   \
###[ TCP ]### 
     sport     = ftp_data
     dport     = http
     seq       = 0
     ack       = 418625512
     dataofs   = None
     reserved  = 0
     flags     = A            #第三次握手包类型(ACK)
     window    = 8192
     chksum    = None
     urgptr    = 0
     options   = []



-- RECEIVED --              #收包
###[ IP ]### 
  version   = 4
  ihl       = 5
  tos       = 0x0
  len       = 40
  id        = 0
  flags     = DF
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = 0x11b5
  src       = 10.10.10.129
  dst       = 10.10.10.135
  \options   \
###[ TCP ]### 
     sport     = http
     dport     = ftp_data
     seq       = 418625512
     ack       = 0
     dataofs   = 5
     reserved  = 0
     flags     = R          #注意,这是在 src 发完 ack 之后收到的,意味着 dst 认为收到的 ack 是个异常包,发个 rst 包来中断连接,原因如上述
     window    = 0
     chksum    = 0xb585
     urgptr    = 0
     options   = []
###[ Padding ]### 
        load      = '\x00\x00\x00\x00\x00\x00'
复制代码

wireshark抓包结果:

 防火墙设置:

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# iptables -L                          #查看防火墙已有规则
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
                                                                                                                                                                                      
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# iptables -A OUTPUT -p tcp --tcp-flags RST RST -d 10.10.10.129 -j DROP             #注意是 2 个RST
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# iptables -L                                                          
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       tcp  --  anywhere             10.10.10.129         tcp flags:RST/RST      #已被添加
复制代码

防火墙设置之后的测试:

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# python3 ./tcp_scan2.py 
-- SENT --
###[ IP ]### 
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     = 
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = None
  src       = 10.10.10.135
  dst       = 10.10.10.129
  \options   \
###[ TCP ]### 
     sport     = ftp_data
     dport     = http
     seq       = 0
     ack       = 0
     dataofs   = None
     reserved  = 0
     flags     = S
     window    = 8192
     chksum    = None
     urgptr    = 0
     options   = []



-- RECEIVED --
###[ IP ]### 
  version   = 4
  ihl       = 5
  tos       = 0x0
  len       = 44
  id        = 0
  flags     = DF
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = 0x11b1
  src       = 10.10.10.129
  dst       = 10.10.10.135
  \options   \
###[ TCP ]### 
     sport     = http
     dport     = ftp_data
     seq       = 2643752577
     ack       = 1
     dataofs   = 6
     reserved  = 0
     flags     = SA
     window    = 5840
     chksum    = 0x43b0
     urgptr    = 0
     options   = [('MSS', 1460)]
###[ Padding ]### 
        load      = '\x00\x00'



-- SENT --
###[ IP ]### 
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     = 
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = None
  src       = 10.10.10.135
  dst       = 10.10.10.129
  \options   \
###[ TCP ]### 
     sport     = ftp_data
     dport     = http
     seq       = 0
     ack       = 2643752578
     dataofs   = None
     reserved  = 0
     flags     = A
     window    = 8192
     chksum    = None
     urgptr    = 0
     options   = []



-- RECEIVED --
###[ IP ]### 
  version   = 4
  ihl       = 5
  tos       = 0x0
  len       = 40
  id        = 0
  flags     = DF
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = 0x11b5
  src       = 10.10.10.129
  dst       = 10.10.10.135
  \options   \
###[ TCP ]### 
     sport     = http
     dport     = ftp_data
     seq       = 2643752578
     ack       = 1
     dataofs   = 5
     reserved  = 0
     flags     = A            #成功!
     window    = 5840
     chksum    = 0x5b6d
     urgptr    = 0
     options   = []
###[ Padding ]### 
        load      = '\x00\x00\x00\x00\x00\x00'
复制代码

wireshark抓包结果:

(3)nmap

 示例:

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nmap -sT 10.10.10.129 -p 80               
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-29 01:41 EST
Nmap scan report for 10.10.10.129
Host is up (0.00070s latency).

PORT   STATE SERVICE
80/tcp open  http
MAC Address: 00:0C:29:DE:5D:BA (VMware)

Nmap done: 1 IP address (1 host up) scanned in 0.38 seconds
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nmap -sT 10.10.10.129 -p 80,21,22,25
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-29 01:41 EST
Nmap scan report for 10.10.10.129
Host is up (0.00083s latency).

PORT   STATE  SERVICE
21/tcp open   ftp
22/tcp open   ssh
25/tcp closed smtp
80/tcp open   http
MAC Address: 00:0C:29:DE:5D:BA (VMware)

Nmap done: 1 IP address (1 host up) scanned in 0.26 seconds
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nmap -sT 10.10.10.129 -p 1-100      
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-29 01:41 EST
Nmap scan report for 10.10.10.129
Host is up (0.0012s latency).
Not shown: 97 closed ports
PORT   STATE SERVICE
21/tcp open  ftp
22/tcp open  ssh
80/tcp open  http
MAC Address: 00:0C:29:DE:5D:BA (VMware)

Nmap done: 1 IP address (1 host up) scanned in 0.28 seconds
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nmap -sT -iL ./iplist.txt  10.10.10.129 -p 1-100 
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-29 01:42 EST
Nmap scan report for 10.10.10.129
Host is up (0.00089s latency).
Not shown: 97 closed ports
PORT   STATE SERVICE
21/tcp open  ftp
22/tcp open  ssh
80/tcp open  http
MAC Address: 00:0C:29:DE:5D:BA (VMware)

Nmap scan report for 10.10.10.2
Host is up (0.0024s latency).
Not shown: 99 closed ports
PORT   STATE SERVICE
53/tcp open  domain
MAC Address: 00:50:56:F0:F4:B1 (VMware)

Nmap done: 2 IP addresses (2 hosts up) scanned in 0.30 seconds
复制代码

wireshark抓包结果:

以 "nmap -sT 10.10.10.129 -p 80,21,22,25"为例:

(4)dmitry

  • 功能简单,使用也简单
  • 默认150个常用端口

帮助信息(help):

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# dmitry -h
Deepmagic Information Gathering Tool
"There be some deep magic going on"

dmitry: invalid option -- 'h'
Usage: dmitry [-winsepfb] [-t 0-9] [-o %host.txt] host
  -o     Save output to %host.txt or to file specified by -o file
  -i     Perform a whois lookup on the IP address of a host
  -w     Perform a whois lookup on the domain name of a host
  -n     Retrieve Netcraft.com information on a host
  -s     Perform a search for possible subdomains
  -e     Perform a search for possible email addresses
  -p     Perform a TCP port scan on a host
* -f     Perform a TCP port scan on a host showing output reporting filtered ports
* -b     Read in the banner received from the scanned port
* -t 0-9 Set the TTL in seconds when scanning a TCP port ( Default 2 )
*Requires the -p flagged to be passed
复制代码

示例:

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# dmitry -p 10.10.10.129                                                             1 ⨯
Deepmagic Information Gathering Tool
"There be some deep magic going on"

ERROR: Unable to locate Host Name for 10.10.10.129
Continuing with limited modules
HostIP:10.10.10.129
HostName:

Gathered TCP Port information for 10.10.10.129
---------------------------------

 Port           State

21/tcp          open
22/tcp          open
80/tcp          open
139/tcp         open
143/tcp         open

Portscan Finished: Scanned 150 ports, 144 ports were in state closed


All scans completed, exiting
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# dmitry -p 10.10.10.129 -o test
Deepmagic Information Gathering Tool
"There be some deep magic going on"

Writing output to 'test.txt'

ERROR: Unable to locate Host Name for 10.10.10.129
Continuing with limited modules
HostIP:10.10.10.129
HostName:

Gathered TCP Port information for 10.10.10.129
---------------------------------

 Port           State

21/tcp          open
22/tcp          open
80/tcp          open
139/tcp         open
143/tcp         open

Portscan Finished: Scanned 150 ports, 144 ports were in state closed

zsh: segmentation fault  dmitry -p 10.10.10.129 -o test
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# more test.txt                                                                    139 ⨯
ERROR: Unable to locate Host Name for 10.10.10.129
Continuing with limited modules
HostIP:10.10.10.129
HostName:

Gathered TCP Port information for 10.10.10.129
---------------------------------

 Port           State
21/tcp          open
22/tcp          open
80/tcp          open
139/tcp         open
143/tcp         open

Portscan Finished: Scanned 150 ports, 144 ports were in state closed
复制代码

wireshark抓包结果:

(5)nc

 示例 (nc的详细使用单独介绍,此处仅简单演示下):

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nc -nv -w 1 -z 10.10.10.129 1-100
(UNKNOWN) [10.10.10.129] 80 (http) open
(UNKNOWN) [10.10.10.129] 22 (ssh) open
(UNKNOWN) [10.10.10.129] 21 (ftp) open
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# for x in $(seq 10 30);do nc -nv -w 1 -z 10.10.10.129 $x;done | grep open             
(UNKNOWN) [10.10.10.129] 10 (?) : Connection refused
(UNKNOWN) [10.10.10.129] 11 (systat) : Connection refused
(UNKNOWN) [10.10.10.129] 12 (?) : Connection refused
(UNKNOWN) [10.10.10.129] 13 (daytime) : Connection refused
(UNKNOWN) [10.10.10.129] 14 (?) : Connection refused
(UNKNOWN) [10.10.10.129] 15 (netstat) : Connection refused
(UNKNOWN) [10.10.10.129] 16 (?) : Connection refused
(UNKNOWN) [10.10.10.129] 17 (qotd) : Connection refused
(UNKNOWN) [10.10.10.129] 18 (?) : Connection refused
(UNKNOWN) [10.10.10.129] 19 (chargen) : Connection refused
(UNKNOWN) [10.10.10.129] 20 (ftp-data) : Connection refused
(UNKNOWN) [10.10.10.129] 21 (ftp) open
(UNKNOWN) [10.10.10.129] 22 (ssh) open
(UNKNOWN) [10.10.10.129] 23 (telnet) : Connection refused
(UNKNOWN) [10.10.10.129] 24 (?) : Connection refused
(UNKNOWN) [10.10.10.129] 25 (smtp) : Connection refused
(UNKNOWN) [10.10.10.129] 26 (?) : Connection refused
(UNKNOWN) [10.10.10.129] 27 (?) : Connection refused
(UNKNOWN) [10.10.10.129] 28 (?) : Connection refused
(UNKNOWN) [10.10.10.129] 29 (?) : Connection refused
(UNKNOWN) [10.10.10.129] 30 (?) : Connection refused
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# for x in $(seq 1 140);do nc -nv -w 1 -z 10.10.10.$x 80;done                        
(UNKNOWN) [10.10.10.1] 80 (http) : Connection timed out
(UNKNOWN) [10.10.10.2] 80 (http) : Connection refused
 ………………………………
(UNKNOWN) [10.10.10.128] 80 (http) : Connection timed out
(UNKNOWN) [10.10.10.129] 80 (http) open
(UNKNOWN) [10.10.10.130] 80 (http) : Connection timed out
 ……………………………………
(UNKNOWN) [10.10.10.140] 80 (http) : Connection timed out
复制代码

3、僵尸扫描

原理参见前面描述

实验环境

 kali(攻击者,10.10.10.135),win2008(僵尸机,10.10.10.140),OWASP_0.94(目标机,10.10.10.129)

(1)Scapy

 示例(结合上面的原理图理解):

复制代码
┌──(root💀kali)-[/home/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.22.0
>>> i=IP()
>>> t=TCP()
>>> rz=(i/t)            #发往僵尸机的数据包
>>> rt=(i/t)            #发往目标机的数据包
>>> rz[IP].dst="10.10.10.140"
>>> rz[TCP].dport=445
>>> rz[TCP].flags="SA"
>>> rt[IP].src="10.10.10.140"  #注意此处在伪造地址
>>> rt[IP].dst="10.10.10.129"
>>> rt[TCP].dport=22        #探测目标机的22端口
>>> rt[TCP].flags="S"
>>> rz.display()          #发往僵尸机数据包的最终设置
###[ IP ]### 
  version= 4
  ihl= None
  tos= 0x0
  len= None
  id= 1
  flags= 
  frag= 0
  ttl= 64
  proto= tcp
  chksum= None
  src= 10.10.10.135
  dst= 10.10.10.140
  \options\
###[ TCP ]### 
     sport= ftp_data
     dport= microsoft_ds
     seq= 0
     ack= 0
     dataofs= None
     reserved= 0
     flags= SA
     window= 8192
     chksum= None
     urgptr= 0
     options= []

>>> rt.display()          #发往目标机数据包的最终设置
###[ IP ]### 
  version= 4
  ihl= None
  tos= 0x0
  len= None
  id= 1
  flags= 
  frag= 0
  ttl= 64
  proto= tcp
  chksum= None
  src= 10.10.10.140
  dst= 10.10.10.129
  \options\
###[ TCP ]### 
     sport= ftp_data
     dport= ssh
     seq= 0
     ack= 0
     dataofs= None
     reserved= 0
     flags= S
     window= 8192
     chksum= None
     urgptr= 0
     options= []

>>> az1=sr1(rz)
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
>>> at=sr1(rt)
Begin emission:
Finished sending 1 packets.
...*
Received 4 packets, got 1 answers, remaining 0 packets
>>> az2=sr1(rz)
Begin emission:
Finished sending 1 packets.
*
Received 1 packets, got 1 answers, remaining 0 packets
>>> az1.display()          #第一次收到僵尸机的回包
###[ IP ]### 
  version= 4
  ihl= 5
  tos= 0x0
  len= 40
  id= 152               #注意此时 ipid=152
  flags= DF
  frag= 0
  ttl= 128
  proto= tcp
  chksum= 0xd111
  src= 10.10.10.140
  dst= 10.10.10.135
  \options\
###[ TCP ]### 
     sport= microsoft_ds
     dport= ftp_data
     seq= 0
     ack= 0
     dataofs= 5
     reserved= 0
     flags= R
     window= 0
     chksum= 0x84e9
     urgptr= 0
     options= []
###[ Padding ]### 
        load= '\x00\x00\x00\x00\x00\x00'

>>> az2.display()        #第二次收到僵尸机的回包
###[ IP ]### 
  version= 4
  ihl= 5
  tos= 0x0
  len= 40
  id= 154              #注意此时 ipid=154=az1[IP].id + 2 ,所以得出目标机 22 端口是开着的!
  flags= DF
  frag= 0
  ttl= 128
  proto= tcp
  chksum= 0xd10f
  src= 10.10.10.140
  dst= 10.10.10.135
  \options\
###[ TCP ]### 
     sport= microsoft_ds
     dport= ftp_data
     seq= 0
     ack= 0
     dataofs= 5
     reserved= 0
     flags= R
     window= 0
     chksum= 0x84e9
     urgptr= 0
     options= []
###[ Padding ]### 
        load= '\x00\x00\x00\x00\x00\x00'

>>> 
复制代码

 wireshark抓包结果:

(2)python脚本实现扫描:

 zombie.py

复制代码
#!/usr/bin/python
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

def ipid(zombie):#判断能否作为僵尸机使用,zombie 僵尸机IP
    reply1 = sr1(IP(dst=zombie)/TCP(flags="SA"),timeout=2,verbose=0)#仅接收一个应答数据包
    send(IP(dst=zombie)/TCP(flags="SA"),verbose=0)#只发包,而不收包
    reply2 = sr1(IP(dst=zombie)/TCP(flags="SA"),timeout=2,verbose=0)
    #通过接收到的ipid评判是否适合做僵尸机
    if reply2[IP].id == (reply1[IP].id+2):
        print("IPID sequence is incremental and target appears to be idle. ZOMBIE LOCATED")#ipid是递增的,并且目标机似乎是空闲的
        response = input("Do you want to use this zombie to perform a scan? (Y or N):")
        if response == "Y":
            target = input("Enter the IP address of the target system   : ")
            zombiescan(target,zombie)
    else:
        print("Either the IPID sequence is not increnental or the target is not idle. NOT A G00D Z0MBIE")
    
def zombiescan(target,zombie):
    print("\nScanning target "+ target+" with zombie "+ zombie)
    print("\n--------0pen Ports on Target--------\n")
    for port in range(1,200):        #根据自己的需求设置
        try:
            start_val = sr1(IP(dst=zombie)/TCP(flags="SA",dport=port),timeout=2,verbose=0)
            send(IP(src=zombie,dst=target)/TCP(flags="S",dport=port),verbose=0)
            end_val = sr1(IP(dst=zombie)/TCP(flags="SA"),timeout=2,verbose=0)
            if end_val[IP].id == (start_val[IP].id + 2):
                print(port)
        except:
            pass
    
print("----------Zombie Scan Suite----------\n")
print("1 - Identify Zombie Host\n")
print("2 - Perform Zombie Scan\n")
ans = input("Select an option (1 or 2):")
if ans == "1":
    zombie=input("Enter IP address to test IPID sequence: ")
    ipid(zombie)
else:
    if ans == "2":
        zombie = input("Enter IP address for zombie system: ")
        target = input("Enter IP address for scan target: ")
        zombiescan(target,zombie)
复制代码

脚本演示:

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# python3 ./zombie.py
----------Zombie Scan Suite----------

1 - Identify Zombie Host

2 - Perform Zombie Scan

Select an option (1 or 2):1          #如果已有僵尸机可直接选择 2
Enter IP address to test IPID sequence: 10.10.10.140      #僵尸机地址
IPID sequence is incremental and target appears to be idle. ZOMBIE LOCATED      #可做僵尸机
Do you want to use this zombie to perform a scan? (Y or N):Y    #是否选用该僵尸机
Enter the IP address of the target system   : 10.10.10.129    #要扫描的目标机

Scanning target 10.10.10.129 with zombie 10.10.10.140

--------0pen Ports on Target--------

21
22
80
139
143
复制代码

wireshark抓包:

(3)nmap

 示例:

复制代码
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nmap -p445 10.10.10.140 --script=ipidseq.nse          #发现僵尸机
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-29 03:16 EST
Nmap scan report for 10.10.10.140
Host is up (0.00088s latency).

PORT    STATE SERVICE
445/tcp open  microsoft-ds
MAC Address: 00:0C:29:F6:B3:C1 (VMware)

Host script results:
|_ipidseq: Incremental!

Nmap done: 1 IP address (1 host up) scanned in 1.37 seconds
                                                                                           
┌──(root💀kali)-[/home/kali/Desktop/Tools]
└─# nmap 10.10.10.129 -sI 10.10.10.140 -Pn -p 0-200         #利用僵尸机扫描目标
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-29 03:16 EST
Idle scan using zombie 10.10.10.140 (10.10.10.140:80); Class: Incremental
Nmap scan report for 10.10.10.129
Host is up (0.048s latency).
Not shown: 196 closed|filtered ports
PORT    STATE SERVICE
21/tcp  open  ftp
22/tcp  open  ssh
80/tcp  open  http
139/tcp open  netbios-ssn
143/tcp open  imap
MAC Address: 00:0C:29:DE:5D:BA (VMware)

Nmap done: 1 IP address (1 host up) scanned in 3.98 seconds
复制代码

 

posted @   z9m8r8  阅读(404)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示