中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用python實現一個nmap掃描工具

發布時間:2020-11-07 14:27:52 來源:億速云 閱讀:310 作者:Leah 欄目:開發技術

使用python實現一個nmap掃描工具?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

利用scapy包編寫一個簡易掃描工具,支持ARP、ICMP、TCP、UDP發現掃描,支持TCP SYN、UDP端口掃描,如下:

usage: python scan.py <-p ping掃描類型> <-s 端口發現類型> [-t target] [--port ports]

簡單掃描工具,可以進行存活掃描及端口掃描.
存活掃描包括:ARP掃描、ICMP掃描、TCP掃描、UDP掃描.
端口掃描包括:TCP SYN掃描、TCP ACK掃描、TCP FIN掃描.

optional arguments:
 -h, --help     show this help message and exit
 -v, --version   show program's version number and exit

target group:
 用于設置IP、PORT參數

 --target TARGET  target為IP或IP段,如192.168.1.1,192.168.1.x,或1
           92.168.1.1-254
 --port PORT    port為待掃描的端口,如21,80,...或21-80

ping group:
 用于開啟存活掃描相關選項

 -p         開啟存活掃描
 --ARP       啟動ARP掃描
 --ICMP       啟動ICMP掃描
 --TCP       啟動TCP掃描
 --UDP       啟動UDP掃描

port scan group:
 用于開啟端口掃描相關選項

 -s         開啟端口掃描
 --SYN       開啟SYN掃描
 --ACK       開啟ACK掃描
 --FIN       開啟FIN掃描
 --UPORT      開啟UDP端口掃描

utils group:
 用于開啟掃描過程中的一些實用選項

 --timeout TIMEOUT 設置發包超時時間,默認0.5秒
 --retry RETRY   設置發包重試次數,默認不重試

以上做為說明,祝好運!

一、發現掃描

1.首先進行ARP掃描

python scan.py -p --target 192.168.1.1-254 --ARP
[+]IP: 192.168.1.1 => MAC: 14:75:90:xx:xx:xx
[+]IP: 192.168.1.111 => MAC: c6:36:55:xx:xx:xx
[+]總共耗時9.84091806412秒.

通過retry參數增加發包嘗試次數,如下:

python scan.py -p --target 192.168.1.1-254 --ARP --retry 2
[+]IP: 192.168.1.1 => MAC: 14:75:90:xx:xx:xx
[+]IP: 192.168.1.111 => MAC: c6:36:55:xx:xx:xx
[+]IP: 192.168.1.102 => MAC: 58:1f:28:xx:xx:xx
[+]IP: 192.168.1.114 => MAC: 6c:8d:c1:xx:xx:xx
[+]IP: 192.168.1.103 => MAC: 84:38:38:xx:xx:xx
[+]總共耗時20.429942131秒.

2.使用ICMP掃描,若沒有指定任何掃描類型參數,默認會啟用ICMP掃描,如下:

python scan.py -p --target 192.168.1.1-254
[+]沒有指定任何ping掃描方式,默認選擇ICMP掃描
[+]IP:主機192.168.1.1 echo-reply.
[+]IP:主機192.168.1.111 echo-reply.
[+]總共耗時10.7177450657秒.

通過timeout參數,設置較長的超時,可以防止網絡狀況不好造成的丟包,如下:

python scan.py -p --target 192.168.1.1-254 --timeout 2
[+]沒有指定任何ping掃描方式,默認選擇ICMP掃描
[+]IP:主機192.168.1.1 echo-reply.
[+]IP:主機192.168.1.111 echo-reply.
[+]IP:主機192.168.1.114 echo-reply.
[+]總共耗時10.7566649914秒.

3.使用TCP掃描

python scan.py -p --target 192.168.1.100-120 --TCP --timeout 1
[+]請稍等,時間較長!
[!]掃描... 192.168.1.100
[!]掃描... 192.168.1.101
[!]掃描... 192.168.1.102
[!]掃描... 192.168.1.103
[!]掃描... 192.168.1.104
[!]掃描... 192.168.1.105
[!]掃描... 192.168.1.106
[!]掃描... 192.168.1.107
[!]掃描... 192.168.1.108
[!]掃描... 192.168.1.109
[!]掃描... 192.168.1.110
[!]掃描... 192.168.1.111
[!]掃描... 192.168.1.112
[!]掃描... 192.168.1.113
[!]掃描... 192.168.1.114
[!]掃描... 192.168.1.115
[!]掃描... 192.168.1.116
[!]掃描... 192.168.1.117
[!]掃描... 192.168.1.118
[!]掃描... 192.168.1.119
[!]掃描... 192.168.1.120
[+]正在處理掃描信息.
====================
[+]主機 192.168.1.102 在線.
[+]主機 192.168.1.103 在線.
[+]主機 192.168.1.111 在線.
[+]主機 192.168.1.114 在線.
[+]總共耗時16.4359779358秒.

4.使用UDP掃描

python scan.py -p --target 192.168.1.100-120 --UDP --retry 3
[+]請稍等,時間較長!
[!]掃描... 192.168.1.100
[!]掃描... 192.168.1.101
[!]掃描... 192.168.1.102
[!]掃描... 192.168.1.103
[!]掃描... 192.168.1.104
[!]掃描... 192.168.1.105
[!]掃描... 192.168.1.106
[!]掃描... 192.168.1.107
[!]掃描... 192.168.1.108
[!]掃描... 192.168.1.109
[!]掃描... 192.168.1.110
[!]掃描... 192.168.1.111
[!]掃描... 192.168.1.112
[!]掃描... 192.168.1.113
[!]掃描... 192.168.1.114
[!]掃描... 192.168.1.115
[!]掃描... 192.168.1.116
[!]掃描... 192.168.1.117
[!]掃描... 192.168.1.118
[!]掃描... 192.168.1.119
[!]掃描... 192.168.1.120
[+]正在處理掃描信息.


====================
[+]主機 192.168.1.102 在線.
[+]主機 192.168.1.103 在線.
[+]主機 192.168.1.111 在線.
[+]主機 192.168.1.114 在線.
[+]總共耗時33.5198891163秒.

二、端口掃描

1、TCP SYN端口掃描,不設置端口參數,則默認掃描1-1024端口

python scan.py --target 192.168.1.110-115 -s --SYN
[+]沒有指定任何掃描端口,默認掃描1-1024
[!]掃描... 192.168.1.110
[!]掃描... 192.168.1.111
[!]掃描... 192.168.1.112
[!]掃描... 192.168.1.113
[!]掃描... 192.168.1.114
[!]掃描... 192.168.1.115
[+]正在處理掃描信息.


====================
[+]主機 192.168.1.111 開放的TCP端口有:[80]
[+]總共耗時165.125555992秒.

掃描指定端口:

python scan.py --target 192.168.1.1-254 -s --SYN --port 80 --timeout 1
[!]掃描... 192.168.1.1
[!]掃描... 192.168.1.2
[!]掃描... 192.168.1.3
[!]掃描... 192.168.1.4
...
[!]掃描... 192.168.1.253
[!]掃描... 192.168.1.254
[+]正在處理掃描信息.


====================
[+]主機 192.168.1.111 開放的TCP端口有:[80]
[+]主機 192.168.1.1 開放的TCP端口有:[80]
[+]總共耗時9.72222185135秒.

2、掃描UDP端口

python scan.py --target 192.168.1.1 -s --UPORT --timeout 1
[+]沒有指定任何掃描端口,默認掃描1-1024
[!]掃描... 192.168.1.1
[+]正在處理掃描信息.
====================
[+]主機 192.168.1.1 開放的UDP端口有:[520]
[+]總共耗時27.4742250443秒.

也可同時進行發現掃描與端口掃描,如下:

python scan.py --target 192.168.1.1-254 -p --ARP -s --SYN --port 80 --timeout 1 --retry 2
[+]IP: 192.168.1.1 => MAC: 14:75:90:xx:xx:xx
[+]IP: 192.168.1.102 => MAC: 58:1f:28:xx:xx:xx
[+]IP: 192.168.1.114 => MAC: 6c:8d:c1:xx:xx:xx
[+]IP: 192.168.1.103 => MAC: 84:38:38:xx:xx:xx
[+]IP: 192.168.1.101 => MAC: 5c:f7:e6:xx:xx:xx
[!]掃描... 192.168.1.1
[!]掃描... 192.168.1.2
...
[!]掃描... 192.168.1.253
[!]掃描... 192.168.1.254
[+]正在處理掃描信息.


====================
[+]主機 192.168.1.1 開放的TCP端口有:[80]
[+]主機 192.168.1.111 開放的TCP端口有:[80]
[+]總共耗時45.2775988579秒.

OK,最后附上源碼:

import argparse
import re
import time
import threading
from scapy.all import *

import logging
logging.getLogger('scapy.runtime').setLevel(logging.ERROR)


class Discovery_Scan(object):
  '''
  說明:用于發現掃描
  '''

  def __init__(self,args,timeout=0.5,retry=0):
    self.targets = parse_target(args)
    self.timeout = timeout
    self.retry = retry

  def arp_scan(self,pdst):
    #ARP發現掃描
    ans = sr1(ARP(pdst=pdst),timeout=self.timeout,retry=self.retry,verbose=False)
    if ans:
      if ans[ARP].op == 2:  #操作碼為2是is-at,是ARP響應
        print '[+]IP: %s => MAC: %s' % (pdst,ans[ARP].hwsrc)

  def icmp_scan(self,dst):
    #ICMP發現掃描
    ans = sr1(IP(dst=dst)/ICMP(),timeout=self.timeout,retry=self.retry,verbose=False)
    if ans:
      if ans[ICMP].type == 0: #ICMP type為0表示是ICMP echo-reply
        print '[+]IP:主機%s echo-reply.' % dst

  tcp_info = {}
  def tcp_scan(self,dst,port):
    #TCP SYN,發送TCP SYN包,有響應表示端口開放
    ans,unans = sr(IP(dst=dst)/TCP(sport=RandShort(),dport=port,flags='S'),
            timeout=self.timeout,retry=self.retry,verbose=False)
    if ans.res:
      if ans.res[0][0][IP].dst not in Discovery_Scan.tcp_info:
        Discovery_Scan.tcp_info[ans.res[0][0][IP].dst] = True

  udp_info = {}
  def udp_scan(self,dst,port):
    #UDP,發送UDP包,有響應表示端口開放
    ans,uans = sr(IP(dst=dst)/UDP(sport=RandShort(),dport=port),
           timeout=self.timeout,retry=self.retry,verbose=False)
    if ans.res:
      if ans.res[0][0][IP].dst not in Discovery_Scan.udp_info:
        Discovery_Scan.udp_info[ans.res[0][0][IP].dst] = True

class Port_Scan(object):
  '''
  說明:用于進行端口掃描,判斷端口是否開放
  '''
  def __init__(self,args,timeout=0.5,retry=0):
    self.targets = parse_target(args)
    self.timeout = timeout
    self.retry = retry

  syn_port_dict = {}
  def syn_port_scan(self,dst,port):
    #TCP SYN端口掃描,若SYN包返回攜帶SYN、ACK(即TCP.flags=18)標志的包,則表明此端口打開。
    ans,uans = sr(IP(dst=dst)/TCP(sport=RandShort(),dport=port,flags='S'),
           timeout=self.timeout,retry=self.retry,verbose=False)
    if ans:
      first_respons_pkt = ans.res[0][1]
      if first_respons_pkt[TCP] and first_respons_pkt[TCP].flags == 18:
        if first_respons_pkt[IP].src not in Port_Scan.syn_port_dict:
          Port_Scan.syn_port_dict[first_respons_pkt[IP].src] = [first_respons_pkt[TCP].sport]
        else:
          Port_Scan.syn_port_dict[first_respons_pkt[IP].src].append(first_respons_pkt[TCP].sport)

  udp_port_dict = {}
  def udp_port_scan(self,dst,port):
    #UDP端口掃描,若UDP端口返回ICMP port-unreachable,則表示端口打開。(排除某些主機對任何UDP端口的探測都響應為ICMP port-unrechable)
    ans,uans = sr(IP(dst=dst)/UDP(sport=RandShort(),dport=port),
           timeout=self.timeout, retry=self.retry, verbose=False)
    if ans.res and ans.res[0][1].haslayer(UDPerror):
      first_respons_pkt = ans.res[0][1]
      if first_respons_pkt[IP].src not in Port_Scan.udp_port_dict:
        Port_Scan.udp_port_dict[first_respons_pkt[IP].src] = [first_respons_pkt[UDPerror].dport]
      else:
        Port_Scan.udp_port_dict[first_respons_pkt[IP].src].append(first_respons_pkt[UDPerror].dport)

def parse_opt():
  '''
  @說明:通過argparse模塊解析程序傳入的參數
  @return:args
  '''
  usage = 'python %(prog)s <-p ping掃描類型> <-s 端口發現類型> [-t target] [--port ports]'
  description = '簡單掃描工具,可以進行存活掃描及端口掃描.\n' \
         '存活掃描包括:ARP掃描、ICMP掃描、TCP掃描、UDP掃描.\n' \
         '端口掃描包括:TCP SYN掃描、TCP ACK掃描、TCP FIN掃描.'
  epilog = '以上做為說明,祝好運!'
  parser = argparse.ArgumentParser(usage=usage,description=description,epilog=epilog,version='v1.0')

  target_group = parser.add_argument_group('target group',description='用于設置IP、PORT參數')
  target_group.add_argument('--target',dest='target',action='store',
               help='target為IP或IP段,如192.168.1.1,192.168.1.x,或192.168.1.1-254')
  target_group.add_argument('--port',dest='port',action='store',
               help='port為待掃描的端口,如21,80,...或21-80')

  ping_group = parser.add_argument_group('ping group',description='用于開啟存活掃描相關選項')
  ping_group.add_argument('-p',dest='ping',action='store_true',help='開啟存活掃描')
  ping_group.add_argument('--ARP',dest='ARP',action='store_true',help='啟動ARP掃描')
  ping_group.add_argument('--ICMP',dest='ICMP',action='store_true',help='啟動ICMP掃描')
  ping_group.add_argument('--TCP',dest='TCP',action='store_true',help='啟動TCP掃描')
  ping_group.add_argument('--UDP',dest='UDP',action='store_true',help='啟動UDP掃描')

  port_scan_group = parser.add_argument_group('port scan group',description='用于開啟端口掃描相關選項')
  port_scan_group.add_argument('-s',dest='scan',action='store_true',help='開啟端口掃描')
  port_scan_group.add_argument('--SYN',dest='SYN',action='store_true',help='開啟SYN掃描')
  port_scan_group.add_argument('--ACK',dest='ACK',action='store_true',help='開啟ACK掃描')
  port_scan_group.add_argument('--FIN',dest='FIN',action='store_true',help='開啟FIN掃描')
  port_scan_group.add_argument('--UPORT', dest='UPORT', action='store_true', help='開啟UDP端口掃描')

  utils_group = parser.add_argument_group('utils group',description='用于開啟掃描過程中的一些實用選項')
  utils_group.add_argument('--timeout',dest='timeout',action='store',type=float,help='設置發包超時時間,默認0.5秒')
  utils_group.add_argument('--retry',dest='retry',action='store',type=int,help='設置發包重試次數,默認不重試')

  args = parser.parse_args()
  if not args.ping and not args.scan:
    print '[-]必須通過-p/-s選項開啟一種掃描'
    print '\n'
    parser.print_help()
    exit(1)
  elif not args.target:
    print '[-]必須通過--target選項指定掃描的對象'
    print '\n'
    parser.print_help()
    exit(1)
  if args.ping:
    if not args.ARP and not args.ICMP and not args.TCP and not args.UDP:
      args.ICMP = True #若沒有指定任何ping掃描方式,則默認選擇ICMP掃描
      print '[+]沒有指定任何ping掃描方式,默認選擇ICMP掃描'
  if args.scan:
    if not args.SYN and not args.ACK and not args.FIN and not args.UPORT:
      args.SYN = True  #若沒有指定任何端口掃描方式,則默認選擇SYN掃描
      print '[+]沒有指定任何端口掃描方式,默認選擇SYN掃描'
    if not args.port:
      args.port = '1-1024'  #若沒有指定任何掃描端口,則默認掃描1-1024
      print '[+]沒有指定任何掃描端口,默認掃描1-1024'

  return args

def parse_target(args):
  '''
  @說明:用于解析如'192.168.1.1,192.168.1.x,...或192.168.1.1-254'格式的IP為單獨的IP,用于解析如'21,80,...或21-80'格式的端口為單獨的端口
  @param: args,一個namespace對象
  @return: (ip_list,port_list)
  '''
  pattern1 = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'
  pattern2 = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}$'
  pattern3 = r'\d{1,5}$'
  pattern4 = r'\d{1,5}-\d{1,5}$'
  ip_list,port_list = None,None
  if args.target:
    if re.search(pattern1,args.target):
      ip_list = args.target.split(',')
    elif re.match(pattern2,args.target):
      _split = args.target.split('-')
      first_ip = _split[0]
      ip_split = first_ip.split('.')
      ipdot4 = range(int(ip_split[3]), int(_split[1]) + 1)
      ip_list = [ip_split[0] + '.' + ip_split[1] + '.' + ip_split[2] + '.' + str(p) for p in ipdot4]
    else:
      print '[-]target格式輸入有誤,請查看幫助!'
      exit(1)
  if args.port:
    if re.match(pattern4,args.port):
      _split = args.port.split('-')
      port_list = range(int(_split[0]),int(_split[1])+1)
    elif re.search(pattern3,args.port):
      port_list = args.port.split(',')
    else:
      print '[-]port格式輸入有誤,請查看幫助!'
      exit(1)
  return ip_list,port_list


def main():
  '''
  @說明:掃描的主程序,首先根據條件創建Ping掃描或端口掃描對象,然后調用相關的掃描方法進行掃描。
  '''
  args = parse_opt()
  if args.ping: #是否啟動Ping掃描
    if not args.timeout and not args.retry:
      obj_ping = Discovery_Scan(args)
    elif args.timeout and not args.retry:
      obj_ping = Discovery_Scan(args,timeout=args.timeout)
    elif not args.timeout and args.retry:
      obj_ping = Discovery_Scan(args,retry=args.retry)
    else:
      obj_ping = Discovery_Scan(args,args.timeout,args.retry)
    ip_list = obj_ping.targets[0]
    if ip_list:
      #ARP掃描
      if args.ARP:
        for pdst in ip_list:
          t = threading.Thread(target=obj_ping.arp_scan,args=(pdst,))
          t.start()
        while threading.activeCount() != 1:   #避免線程還沒有運行完就提前輸出不全的結果
          time.sleep(1)
      #ICMP掃描
      elif args.ICMP:
        for dst in ip_list:
          t = threading.Thread(target=obj_ping.icmp_scan,args=(dst,))
          t.start()
        while threading.activeCount() != 1:   #避免線程還沒有運行完就提前輸出不全的結果
          time.sleep(1)
      #TCP掃描
      elif args.TCP:
        port_list = [80,443,21,22,23,25,53,135,139,137,445,1158,1433,1521,3306,3389,7001,8000,8080,9090]
        print '[+]請稍等,時間較長!'
        for dst in ip_list:
          print '[!]掃描...',dst
          for port in port_list:
            t = threading.Thread(target=obj_ping.tcp_scan,args=(dst,port))
            t.start()

        print '[+]正在處理掃描信息.'
        while threading.activeCount() != 1:   #避免線程還沒有運行完就提前輸出不全的結果
          time.sleep(1)

        if not obj_ping.tcp_info:
          print '\n'
          print '=' * 20
          print '[+]未發現在線主機.'
        else:
          print '\n'
          print '=' * 20
          for ip_a in sorted(obj_ping.tcp_info.keys()):
            print '[+]主機 %s 在線.' % ip_a
      #UDP掃描
      elif args.UDP:
        port_list = [7,9.13,15,37,53,67,68,69,135,137,138,139,445,520]
        print '[+]請稍等,時間較長!'
        for dst in ip_list:
          print '[!]掃描...',dst
          for port in port_list:
            t = threading.Thread(target=obj_ping.udp_scan,args=(dst,port))
            t.start()

        print '[+]正在處理掃描信息.'
        while threading.activeCount() != 1:   #避免線程還沒有運行完就提前輸出不全的結果
          time.sleep(1)

        if not obj_ping.udp_info:
          print '\n'
          print '=' * 20
          print '[+]未發現在線主機.'
        else:
          print '\n'
          print '=' * 20
          for ip_a in sorted(obj_ping.udp_info.keys()):
            print '[+]主機 %s 在線.' % ip_a
  if args.scan:  #是否啟動端口掃描
    if not args.timeout and not args.retry:
      obj_port = Port_Scan(args)
    elif args.timeout and not args.retry:
      obj_port = Port_Scan(args,timeout=args.timeout)
    elif not args.timeout and args.retry:
      obj_port = Port_Scan(args,retry=args.retry)
    else:
      obj_port = Port_Scan(args,args.timeout,args.retry)

    ip_list,port_list = obj_port.targets
    if ip_list and port_list:
      if args.SYN:
        for dst in ip_list:
          print '[!]掃描...',dst
          for port in port_list:
            t = threading.Thread(target=obj_port.syn_port_scan,args=(dst,int(port)))
            t.start()

        print '[+]正在處理掃描信息.'
        while threading.activeCount() != 1:   #避免線程還沒有運行完就提前輸出不全的結果
          time.sleep(1)

        if not obj_port.syn_port_dict:
          print '\n'
          print '=' * 20
          print '[+]未發現開放TCP端口.'
        else:
          print '\n'
          print '=' * 20
          for k,v in obj_port.syn_port_dict.items():
            print '[+]主機 %s 開放的TCP端口有:%s' % (k,str(v))
      elif args.ACK:
        pass  #基本不能使用
      elif args.FIN:
        pass  #基本不能使用
      elif args.UPORT:
        for dst in ip_list:
          print '[!]掃描...',dst
          for port in port_list:
            t = threading.Thread(target=obj_port.udp_port_scan,args=(dst,int(port)))
            t.start()

        print '[+]正在處理掃描信息.'
        while threading.activeCount() != 1:   #避免線程還沒有運行完就提前輸出不全的結果
          time.sleep(1)

        if not obj_port.udp_port_dict:
          print '\n'
          print '=' * 20
          print '[+]未發現開放UDP端口.'
        else:
          print '\n'
          print '=' * 20
          for k,v in obj_port.udp_port_dict.items():
            print '[+]主機 %s 開放的UDP端口有:%s' % (k,str(v))

if __name__ == '__main__':
  try:
    start_time = time.time()
    main()
    stop_time = time.time()
    print '[+]總共耗時'+str(stop_time-start_time)+'秒.'
  except Exception,e:
    print '[-]執行出錯,具體錯誤見下面信息.'
    print e

看完上述內容,你們掌握使用python實現一個nmap掃描工具的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

凤庆县| 咸阳市| 翼城县| 乐清市| 方正县| 望奎县| 三明市| 临漳县| 麟游县| 寿光市| 茂名市| 沛县| 嘉峪关市| 安阳市| 丹棱县| 五大连池市| 旅游| 休宁县| 安宁市| 枞阳县| 象州县| 科技| 讷河市| 崇义县| 霞浦县| 睢宁县| 安徽省| 长子县| 阿拉善右旗| 杭锦后旗| 陵川县| 金堂县| 平顶山市| 灌云县| 启东市| 喀什市| 海丰县| 内丘县| 通江县| 军事| 青阳县|