掃描器篇(五)之scapy構造UDP數據包完成主機發現

udp協議掃描

  • 發現原理

    向目標主機發送一個,沒有開放的端口發送數據,目標主機會返回一個ICMP
    目標端口不可達的消息,通過該特徵可以對主機進行判斷是否在線
    
  • 注意事項

       如果目標主機端口不在線,或者在線且目標端口爲開放狀態,那麼發送出去的UDP數據包不會收到任何回覆
    
  • 判斷條件

       以返回包中的ip部分proto參數的值作爲判斷條件,確定目標主機是否返回ICMP消息,
       原理是ip包頭中的protocol部分用於標記上層協議類型,如果數值爲0x01的話表示ICMP
    

在這裏插入圖片描述

代碼部分

  • 數據包構造掃描部分
    • 通過python發包神器scapy構造UDP數據包
      
    • 端口一定要選擇沒有開放的,不然會掃描不到主機
      
def scan(ip):
    try:					# 端口要求一定是沒開放
      packet = IP(dst=ip)/UDP(dport=56789)
      result = sr1(packet,timeout=0.5,verbose=0)
      #result.show()

      if int(result[IP].proto) == 0x01: # 0x01 代表的ICMP字段值
          time.sleep(0.1)
          print(ip + ' ' + "on line")
    except:
        return
  • 參數獲取部分
    • 通過optparse模塊接收用戶提供的參數,判斷是掃描整個網段還是讀取ip地址文件
      
    • 獲取到地址後再通過Thread多線程去發送數據包
      

def main():
	# 生成幫助信息,以及接收用戶輸入的參數,並建立對象
    usage = "Usage: arp掃描.py -f <filename> -i <ip address>"
    parse = OptionParser(usage=usage)
    parse.add_option("-f", "--file", type="string", dest="filename", help="specify the IP address file")
    parse.add_option("-i", '--ip', type="string", dest="address", help="specify the IP address")
    (option, args) = parse.parse_args()
    filename = option.filename
    address = option.address
	# 判斷是不是地址文件
    if filename:
        if not os.path.exists(filename):	#判斷文件是否存在
            print("The file does not exist. Please enter it again")
            sys.exit()	
        with open(filename, "r") as f:	#讀取文件
            for i in f.readlines():
                ip = i.strip()
                t = Thread(target=scan, args=(ip,))
                t.start()
	# 判斷是不是整個網段
    if address:
        prefix = address.split(".")[0] + '.' + address.split(".")[1] + '.' + address.split(".")[2] + "."	# 將用戶輸入的地址以.作爲分隔符
        for i in range(0, 255):	
            ip = prefix + str(i)	#構造掃描整個網段所需ip
            t = Thread(target=scan, args=(ip,))
            t.start()

整體代碼

import os
import time
from optparse import OptionParser
from scapy.all import *


def scan(ip):
    try:
      packet = IP(dst=ip)/UDP(dport=56789)
      result = sr1(packet,timeout=0.5,verbose=0)
      #result.show()

      if int(result[IP].proto) == 0x01: # 0x01 代表的ICMP字段值
          time.sleep(0.1)
          print(ip + ' ' + "on line")
    except:
        return


def main():
	# 生成幫助信息,以及接收用戶輸入的參數,並建立對象
    usage = "Usage: arp掃描.py -f <filename> -i <ip address>"
    parse = OptionParser(usage=usage)
    parse.add_option("-f", "--file", type="string", dest="filename", help="specify the IP address file")
    parse.add_option("-i", '--ip', type="string", dest="address", help="specify the IP address")
    (option, args) = parse.parse_args()
    filename = option.filename
    address = option.address
	# 判斷是不是地址文件
    if filename:
        if not os.path.exists(filename):	#判斷文件是否存在
            print("The file does not exist. Please enter it again")
            sys.exit()
        with open(filename, "r") as f:		#讀取文件
            for i in f.readlines():
                ip = i.strip()
                t = Thread(target=scan, args=(ip,))
                t.start()
	# 判斷是不是整個網段
    if address:
        prefix = address.split(".")[0] + '.' + address.split(".")[1] + '.' + address.split(".")[2] + "."	# 將用戶輸入的地址以.作爲分隔符
        for i in range(0, 255):	
            ip = prefix + str(i)	#構造掃描整個網段所需ip
            t = Thread(target=scan, args=(ip,))
            t.start()


if __name__ == '__main__':
    main()

運行效果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章