Python 協議攻擊腳本(四): ARP掃描

ARP協議

地址解析協議,即ARP(Address Resolution Protocol),是根據IP地址獲取物理地址的一個TCP/IP協議主機發送信息時將包含目標IP地址的ARP請求廣播到網絡上的所有主機,並接收返回消息,以此確定目標的物理地址;

OP

操作類型:

  • 1 ARP請求
  • 2 ARP應答
  • 3 RARP請求
  • 4 RARP應答

數據包分析

ping局域網中的一個地址

mark

抓包,可以看到在尋找10.35.68.1是誰,並做出了答覆

mark

封裝爲Ether/ARP

Ether

  1. 源MAC本機MAC
  2. 目的MAC爲廣播地址ff:ff:ff:ff:ff:ff(ARP特性)

ARP:

  1. op1(ARP請求)
  2. 源MAC源IP本機MAC本機IP
  3. 目的MAC目的IP00:00:00:00:00:00目標機IP,

答覆包

mark

ARP:

  1. 獲取到10.35.68.1MAC並判斷它存活

  2. op2(ARP答覆)

編寫腳本

1.Scapy中ARP的請求和答覆

>>> ls(ARP)
hwtype     : XShortField                         = (1)
ptype      : XShortEnumField                     = (2048)
hwlen      : FieldLenField                       = (None)
plen       : FieldLenField                       = (None)
op         : ShortEnumField                      = (1)
hwsrc      : MultipleTypeField                   = (None)
psrc       : MultipleTypeField                   = (None)
hwdst      : MultipleTypeField                   = (None)
pdst       : MultipleTypeField                   = (None)
>>> arp = (Ether(dst='FF:FF:FF:FF:FF:FF')/ARP(op=1, pdst='10.35.68.1'))
>>> arp.show()
###[ Ethernet ]###
  dst= FF:FF:FF:FF:FF:FF
  src= a0:8c:fd:1b:cb:90
  type= 0x806
###[ ARP ]###
     hwtype= 0x1
     ptype= 0x800
     hwlen= None
     plen= None
     op= who-has
     hwsrc= a0:8c:fd:1b:cb:90
     psrc= 10.35.71.205
     hwdst= None
     pdst= 10.35.68.1

>>> pkt = srp1(arp)    #srp1() 發送二層包並接受第一個答覆包
Begin emission:
Finished sending 1 packets..
.*
Received 3 packets, got 1 answers, remaining 0 packets
>>> pkt.show()   #查看答覆包
###[ Ethernet ]###
  dst= a0:8c:fd:1b:cb:90
  src= 34:96:72:8a:6e:a2
  type= 0x806
###[ ARP ]###
     hwtype= 0x1
     ptype= 0x800
     hwlen= 6
     plen= 4
     op= is-at
     hwsrc= 34:96:72:8a:6e:a2
     psrc= 10.35.68.1
     hwdst= a0:8c:fd:1b:cb:90
     pdst= 10.35.71.205
###[ Padding ]###
        load= '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 
>>> pkt.getlayer('ARP').fields['hwsrc'] #獲取目標MAC地址
'34:96:72:8a:6e:a2'

2.demo

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from scapy.all import (
Ether,
ARP,
srp1)

def arp_request(ip_dst):

    pkt = Ether(dst='FF:FF:FF:FF:FF:FF')/
    	  ARP(op=1,hwdst='00:00:00:00:00:00',pdst=ip_dst)
    arp_rep = srp1(pkt,,timeout=3,verbose=False)

    if arp_rep:
        print('[+]',ip_dst,'-->MAC: ',arp_rep.hwsrc,'\n') ##掃描出的MAC地址

if __name__ == '__main__':
    arp_request('10.35.68.1')

運行結果

[+] 10.35.68.1 -->MAC:  34:96:72:8a:6e:a2 

3.完善代碼

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from scapy.all import (
Ether,
ARP,
srp1)
import ipaddress
import time
import threading
import argparse
import os
import sys

hwdst = '00:00:00:00:00:00'
dst= 'FF:FF:FF:FF:FF:FF'

def arp_request(ip_dst):
    hwdst = '00:00:00:00:00:00'
    mac_broad = 'FF:FF:FF:FF:FF:FF'    #廣播地址
    pkt = Ether(dst=mac_broad)/ARP(op=1, hwdst=hwdst, pdst=ip_dst)
    arp_rep = srp1(pkt,timeout=3, verbose=False)

    if arp_rep:
        print('[+]'+ip_dst,'-->MAC: ',arp_rep.hwsrc) ##掃描出的MAC地址

def arp_scan(network):
    begin = time.time()
    threads = []
    length = len(network)

    for ip in network:
        scan = threading.Thread(target=arp_request,args=(str(ip),))
        threads.append(scan)

    for i in range(length):
        threads[i].start()

    for i in range(length):
        threads[i].join()

    stop = time.time()
    print('[+]complete scan time cost:%.3fs'%(stop-begin)) #計算運行時間

def main():
    # Windows下注釋掉這段
    # 判斷是否爲root
    if os.getegid() != 0:
       print('[-]Need root user to run')
       sys.exit(1)

    parser = argparse.ArgumentParser()
    parser.add_argument('network',help='eg: 192.168.1.0/24')
    args = parser.parse_args()

    try:
        network = list(ipaddress.ip_network(args.network))
        arp_scan(network)

    except ValueError:
        parser.print_help()
    except KeyboardInterrupt:
        print('[-]Stop scan')

if __name__ == '__main__':
    main()

運行演示
mark

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