1 ARP扫描

ARP报格式:

python ping 网络扫描_python

以太网首部:

字段            长度(Byte)          默认值                 备注
接收方MAC        6                                        广播时,为 ff-ff-ff-ff-ff-ff
发送方MAC        6        
Ethertype        2                 0x0806                0x0806是ARP帧的类型值

ARP包:

字段            长度(Byte)         默认值                  备注
硬件类型         2                  0x1                  以太网类型值
上层协议类型     2                  0x0800               上层协议为IP协议
MAC地址长度      1                  0x6                  以太网MAC地址长度为 6
IP地址长度       1                  0x4                  IP地址长度为 4
操作码           2                                       0x1表示ARP请求包,0x2表示应答包
发送方MAC        6        
发送方IP         4        
接收方MAC        6        
接收方IP         4        
填充数据         18      因为物理帧最小长度为64字节,前面的42字节再加上4个CRC校验字节,还差18个字节

来自:

python ping 网络扫描_python ping 网络扫描_02

ARP小工具实现:

仿造ARP包构造:

python ping 网络扫描_TCP_03

# -- coding:UTF-8 --
import logging
import sys
from scapy.all import *

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)#清除报错

def arp_request(ip_address,queue=None):
    result = srp(Ether(dst='FF:FF:FF:FF:FF:FF')
            /ARP(op=1,hwdst='00:00:00:00:00:00',pdst=ip_address),
            timeout=1,verbose=False)
    try:
        result_list = result[0].res #将响应的数据报对组成为一组清单
        #[0]为第一组相应的包
        if queue == None:
            return result_list[0][1].getlayer(ARP).fields['hwsrc']
            #[1]接受的包,[0]发送的包
        else:
            queue.put((ip_address,result_list[0][1].getlayer(ARP).fields['hwsrc']))
    except:
        return
if __name__ == "__main__":
    print(arp_request(sys.argv[1]))
# -- coding:UTF-8 --
import ipaddress
import logging
import sys
from arpRequest import arp_request
from multiprocessing import Process,Queue

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)#清除报错

def arp_scan(network):
    qyt_queue = Queue()
    net = ipaddress.ip_network(network.decode('gbk'))
    for ip in net:
        ip_addr = str(ip)
        arp_one = Process(target=arp_request,args=(ip_addr,qyt_queue))
        arp_one.start()
    time.sleep(2)
    ip_mac_list =[]
    while True:
        if qyt_queue.empty():
            break
        else:
            ip,mac = qyt_queue.get()
            ip_mac_list.append((ip,mac))
    return ip_mac_list

if __name__ =="__main__":
    active_ip_mac = arp_scan(sys.argv[1])
    print("活动的IP和MAC地址如下:")
    for ip,mac in active_ip_mac:
        print(ip,mac)

 结果:

python ping 网络扫描_网络_04

python ping 网络扫描_网络_05

python ping 网络扫描_开发语言_06

2 TCP端口扫描

1)全扫描

原理

扫描主机尝试与目标主机的某个端口建立正规的三次握手的连接,连接由系统调用connect()开始。如果端口开放,则连接将建立成功;否则,返回-1,则表示端口关闭。

技术特点

    优点:实现简单;对操作者的权限没有严格要求;扫描速度快。

    缺点:扫描方式不隐蔽;很容易被检测出来,且在日志文件中会有大量密集的连接和错误记录;容易被防火墙发现和屏蔽。

2)半扫描

原理:

扫描主机向目标主机的某个端口发送SYN数据段。如果应答是RST,那么,说明端口是关闭的,按照设定继续探听其他端口;如果应答中包含SYN和ACK,说明目标端口处于监听状态。由于SYN扫描时,全连接尚未建立,所以,这种技术通常被称为“半连接”扫描。

技术特点:

    优点:日志中对于扫描的记录量很少。

    缺点:在大部分操作系统中,发送主机需要构造适用于这种扫描的IP包,需要超级用户或者得到授权的用户才可以。

3)秘密扫描

原理:

使用FIN数据包探测端口:当一个FIN数据包到达一个关闭的端口,数据包会被丢掉,且返回一个RST数据包。当一个FIN数据包到达一个打开的端口,数据包只是简单丢掉(不返回RST数据包)。由于这种技术不包含标准的TCP三次握手协议的任何部分,所以无法被记录下来,所以叫秘密扫描。

技术特点:

优点:秘密扫描能躲避IDS、防火墙、包过滤器和日志审计,从而获取目标端口的开放或关闭的信息。

缺点:和SYN扫描类似,秘密扫描也需要构造自己的IP包,也需要权限。

python ping 网络扫描_TCP_07

 构造包的依据:

python ping 网络扫描_python ping 网络扫描_08

半扫描依据:

python ping 网络扫描_网络_09

python ping 网络扫描_python ping 网络扫描_10

 发送标志syn=1的包,0000 0000 0010,可以写成flags=2或flags='S',

判断收到的包是否为ack+syn,0000 0001 0010,即判断flafs==18.

# -- coding:UTF-8 --
import logging
import sys
from scapy.all import *

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)#清除报错

def tcp_scan(hostname,lport,hport):
    result = sr(IP(dst=hostname)
                /TCP(dport=(int(lport),int(hport)),flags=2),
                timeout=1,verbose=False)
    
    result_list = result[0].res

    for i in range(len(result_list)):
        if result_list[i][1].haslayer(TCP):
            TCP_Fields = result_list[i][1].getlayer(TCP).fields

            if TCP_Fields['flags'] == 18:
                print('*端口号:'+str(TCP_Fields['sport'])+'is open!')

if __name__ == "__main__":
    print('------------------------------------------')
    if len(sys.argv)<4:
        print('格式错误,请按以下格式输入:tcpScan.py IP startport endport')
	sys.exit(0)
    else:
        print('*正在扫描&'+sys.argv[1])
        print(tcp_scan(sys.argv[1],sys.argv[2],sys.argv[3]))

结果:

python ping 网络扫描_TCP_11

首先,ARP找到对方,然后发TCP包判断

python ping 网络扫描_网络_12

下面展示了不完整的三次握手过程!

python ping 网络扫描_TCP_13

3 NMAP Ping扫描

import nmap 
import sys

def nmap_ping(host):

    nm = nmap.PortScanner()
    result_raw = nm.scan(hosts=host,arguments ='-v -n -sn')
    host_list =[]
    for result in result_raw['scan'].values():
        if result['status']['state'] == 'up':
            host_list.append(result['addresses']['ipv4'])
    return host_list

if __name__ == "__main__":
    for host in nmap_ping(sys.argv[1]):
        print('%-20s %5s'% (host,'is up'))

python ping 网络扫描_python_14

 4 NMAP 全能扫描信息处理

效果:

python ping 网络扫描_TCP_15

源码:

# -- coding:UTF-8 --
import nmap
import sys

def nmapAscan(host):
    nm = nmap.PortScanner()
    raw_result = nm.scan(hosts=host,arguments ='-v -n -A')
    for host,result in raw_result['scan'].items():
        if result['status']['state'] == 'up' :
            print('#'*17 + 'Host:' + host + '#'*17)
            print('-'*20 + '操作系统猜测' + '-'*20)
            for os in result['osmatch']:
                print('操作系统为:'+ os['name'] + '准确度为:' + os['accuracy'])
            idno =1
            try:
                for port in result['tcp']:
                    try :
                        print('-'*17 + 'TCP服务详细信息' + '[' + str(idno) +']')
                        idno=idno+1
                        print('TCP端口号:' + str(port))
                        try:
                            print('状态:'+ result['tcp'][port]['state '])
                        except :
                            pass
                        try:
                            print('原因:'+ result['tcp' ][port]['reason'])
                        except :
                            pass
                        try:
                            print('额外信息:' + result['tcp'][port]['extrainfo'])
                        except :
                            pass
                        try:
                            print('名字:'+ result['tcp'][port]['name'])
                        except :
                            pass
                        try:
                            print('版本:'+ result['tcp'][port]['version'])
                        except :
                            pass
                        try:
                            print('产品:' + result['tcp'][port]['product'])
                        except :
                            pass
                        try:
                            print('CPE:'+ result['tcp'][port]['cpe'])
                        except :
                            pass
                        try:
                            print('脚本:'+ result['tcp'][port]['script'])
                        except :
                            pass
                    except:
                        pass
            except:
                pass