Windows10 + Pythonでパケットを扱うライブラリを探してみたところ、Scapyが良さそうでした。
- Scapy - official site
- secdev/scapy: Scapy: the python-based interactive packet manipulation program & library - GitHub
そこで、Scapyをインストールしようとしたところ、いくつかハマったところがあったため、メモを残しておきます。
なお、本当はPython3で使いたかったのですが、後述の通り、今のところWindowsのPython3で使うのは難しそうでした。
そのため、今回はPython2系のScapyを使うことにしました。
長いので、以下目次です。
- 環境
- OK: Python2.7.11 + GitHubのScapy
- NG: Python2.7.11 + PyPIのScapy
- NG: Python3.5.1 + PyPIのscapy-python3(scapy3k)
環境
WindowsでScapyを使うには、WinPcapが必要そうでした。
WinPcap - Home
ただ、Windows10の場合、WinPcap for Windows 10(Win10Pcap)もありました。
Win10Pcap - WinPcap for Windows 10
ドキュメントを見ると、
などの記載があったため、今回はWin10Pcapを使うことにしました。
公式サイトより、Win10Pcap-v10.2-5002.msiをダウンロード・インストールします。インストール先はデフォルトのままで問題ないようです。
Win10Pcap ダウンロード - WinPcap for Windows 10
OK: Python2.7.11 + GitHubのScapy
Python2系のScapyをWindowsにインストールする方法は、いくつかのサイトで目にしました。
- Download and Installation — Scapy v2.1.1-dev documentation
- zlorb/scapy: Scapy Install for Windows with Python 2.7
ただ、現在のGitHubにあるソースコードからインストールすれば、dnetへの依存がなく、Scapyだけで動くようでした。
- python - Error getting Scapy to work on Windows: "'module' object has no attribute 'ex_name'" - Stack Overflow
- Windows: use Winpcap, drop DNET dependency by p-l- · Pull Request #1 · secdev/scapy
そこで、今回はGitHubからのインストールを試してみます。
# ディレクトリ作成 D:\Sandbox>mkdir scapy2_installation D:\Sandbox>cd scapy2_installation # virtualenv環境作成 D:\Sandbox\scapy2_installation>virtualenv -p c:\python27\python.exe env D:\Sandbox\scapy2_installation>env\Scripts\activate # GitHubからインストール (env) D:\Sandbox\scapy2_installation>pip install git+https://github.com/secdev/scapy.git ... Successfully installed scapy-2.3.2.dev0 # インストール結果の確認 (env) D:\Sandbox\scapy2_installation>pip list pip (7.1.2) scapy (2.3.2.dev0) setuptools (18.2) wheel (0.24.0)
以上で環境ができたため、Googleへpingを飛ばして実行確認します。
D:\Sandbox\scapy2_installation\runner.py
# -*- coding: utf-8 -*- from scapy.all import * # ICMPパケットの作成 request=IP(dst='www.google.com')/ICMP() request.show() # ICMPパケットの送出 response = sr1(request) # 結果の表示 response.show()
実行結果は以下の通りとなり、正しく動作していることが確認できました。
(env) D:\Sandbox\scapy2_installation>python runner.py
WARNING: No route found for IPv6 destination :: (no default route?)
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = icmp
chksum = None
src = 192.168.***.***
dst = Net('www.google.com')
\options \
###[ ICMP ]###
type = echo-request
code = 0
chksum = None
id = 0x0
seq = 0x0
Begin emission:
FATAL Bad Memory Block.
FATAL Bad Memory Block.
Finished to send 1 packets.
....*
Received 5 packets, got 1 answers, remaining 0 packets
###[ IP ]###
version = 4L
ihl = 5L
tos = 0x0
len = 28
id = 0
flags =
frag = 0L
ttl = 49
proto = icmp
chksum = 0x8f5
src = 216.58.221.164
dst = 192.168.***.***
\options \
###[ ICMP ]###
type = echo-reply
code = 0
chksum = 0x0
id = 0x0
seq = 0x0
ここまでで本題は終了ですが、試してみてダメだったパターンも以下に残しておきます。
NG: Python2.7.11 + PyPIのScapy
当初GitHubからのインストールを知らなかったため、前述のサイトを参考にPyPIのScapyをインストールしてみました。
zlorb/scapy: Scapy Install for Windows with Python 2.7
そのサイトには
Minimum requirement seems to be pywin32 and winpcap.
と書かれていたものの、pywin32無しでも行けないかなと思い、まずはScapyからインストールすることにしました。
D:\Sandbox>mkdir scapy2_ng D:\Sandbox>cd scapy2_ng D:\Sandbox\scapy2_ng>virtualenv -p c:\python27\python.exe env D:\Sandbox\scapy2_ng>env\Scripts\activate (env) D:\Sandbox\scapy2_ng>pip install scapy
この時点で上記で作ったPythonスクリプト(runner.py)を実行してみます。
(env) D:\Sandbox\scapy2_ng>python runner.py
Traceback (most recent call last):
File "runner.py", line 2, in <module>
from scapy.all import *
...
File "D:\Sandbox\scapy2_ng\env\lib\site-packages\scapy\arch\pcapdnet.py", line 30, in <module>
import pcapy as pcap
ImportError: No module named pcapy
pcapyパッケージが無さそうでした。
pcapyのインストール方法は、公式のGitHub Wikiに画像入りで案内がありました。
Compiling Pcapy on Windows Guide · CoreSecurity/pcapy Wiki
ただ、今回はvirtualenv + pipを使っているため、PyPIからインストールしてみます。
(env) D:\Sandbox\scapy2_ng>pip install pcapy
...
running build_ext
building 'pcapy' extension
error: Microsoft Visual C++ 9.0 is required (Unable to find vcvarsall.bat). Get it from http://aka.ms/vcpython27
Microsoft Visual C++ Compiler for Python 2.7がないため、ビルドできないようでした。
そこで、Download Microsoft Visual C++ Compiler for Python 2.7 from Official Microsoft Download Centerから(VCForPython27.msi)をダウンロード・インストールし、再度PyPIからインストールしてみます。
(env) D:\Sandbox\scapy2_ng>pip install pcapy ... pcapdumper.cc(11) : fatal error C1083: Cannot open include file: 'pcap.h': No such file or directory error: command 'C:\\Users\\think\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\VC\\Bin\\cl.exe' failed with exit status 2
pcap.hファイルが無いというエラーメッセージに変わりました。
調べてみたところ、以下のstackoverflowより、WinPcap Developer's Packがないことが分かりました。
python - trouble installing pcapy on windows 7 - cannot open include file: 'pcap.h' - Stack Overflow
そこで、Developer's Packを利用してインストールしてみます。
- 参考
# Developer's Packのダウンロード (env) D:\Sandbox\scapy2_ng>bitsadmin.exe /TRANSFER devpack http://www.winpcap.org/install/bin/WpdPack_4_1_2.zip D:\Sandbox\scapy2_ng\WpdPack_4_1_2.zip DISPLAY: 'devpack' TYPE: DOWNLOAD STATE: TRANSFERRED PRIORITY: NORMAL FILES: 1 / 1 BYTES: 775788 / 775788 (100%) Transfer complete. # PowerShellを経由したzipファイルの解凍 D:\Sandbox\scapy2_ng>powershell expand-archive D:\Sandbox\scapy2_ng\WpdPack_4_1_2.zip . # --global-optionによるDeveloper's Packを使ったインストール (env) D:\Sandbox\scapy2_ng>pip install pcapy --global-option=build_ext --global-option="-LD:\Sandbox\scapy2_ng\WpdPack\Lib" --global-option="-ID:\Sandbox\scapy2_ng\WpdPack\Include # 確認 (env) D:\Sandbox\scapy2_ng>pip list pcapy (0.10.10) pip (7.1.2) scapy (2.3.2) setuptools (18.2) wheel (0.24.0)
再度実行したところ、dnetが無いというエラーになりました。
(env) D:\Sandbox\scapy2_ng>python runner.py ... ImportError: No module named dnet
PyPIを見たところパッケージがありました。
dnet 1.12 : Python Package Index
そのため、pipでdnetをインストールしようとしたところ、エラーになりました。
(env) D:\Sandbox\scapy2_ng>pip install dnet Collecting dnet Could not find a version that satisfies the requirement dnet (from versions: ) No matching distribution found for dnet
GitHubを見たところ、releaseがありました。
dugsong/libdnet: Automatically exported from code.google.com/p/libdnet
そのため、releaseからインストールしてみましたが、
(env) D:\Sandbox\scapy2_ng>pip install https://github.com/dugsong/libdnet/archive/libdnet-1.12.zip
Collecting https://github.com/dugsong/libdnet/archive/libdnet-1.12.zip
Downloading https://github.com/dugsong/libdnet/archive/libdnet-1.12.zip
/ 1.1MB 312kB/s
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 18, in <module>
IOError: [Errno 2] No such file or directory: 'path\\to\\appdata\\local\\temp\\pip-u_j8nk-build\\setup.py'
setup.pyが無いようで、エラーとなりました。
自分でビルドするのは手間だったので、バイナリを配布しているところを探してみたところ、いくつかありました。
- Dirk Lossさんのツイート: "libdnet installer for #Python 2.7 on Windows: http://dirk-loss.de/scapy/dnet-1.12.win32-py2.7.exe #scapy"
- zlorb/scapy: Scapy Install for Windows with Python 2.7
配布されているバイナリに差がないか、fcivを使って調べてみます。
可用性とは、ファイル チェックサム整合性検証ユーティリティの説明
結果は、
# オリジナル C:\Users\think\Downloads>D:\PortableApps\fciv\fciv.exe C:\Users\think\Downloads\dnet-1.12.win32-py2.7.exe -sha1 // // File Checksum Integrity Verifier version 2.05. // 7635b04d8363a9fde19fd1548926318aee916337 c:\users\think\downloads\dnet-1.12.win32-py2.7.exe # GitHubの-2なし C:\Users\think\Downloads>D:\PortableApps\fciv\fciv.exe "C:\Users\think\Downloads\dnet-1.12.win32-py2.7 (1).exe" -sha1 // // File Checksum Integrity Verifier version 2.05. // 7635b04d8363a9fde19fd1548926318aee916337 c:\users\think\downloads\dnet-1.12.win32-py2.7 (1).exe # Githubの-2 C:\Users\think\Downloads>D:\PortableApps\fciv\fciv.exe C:\Users\think\Downloads\dnet-1.12.win32-py2.7-2.exe -sha1 // // File Checksum Integrity Verifier version 2.05. // 7635b04d8363a9fde19fd1548926318aee916337 c:\users\think\downloads\dnet-1.12.win32-py2.7-2.exe
と、いずれも同じようでした。
そのため、easy_installを使って、exe形式のパッケージをvirtualevn環境へインストールします。
# インストール (env) D:\Sandbox\scapy2_ng>easy_install http://dirk-loss.de/scapy/dnet-1.12.win32-py2.7.exe ...Finished processing dependencies for dnet==1.12 # 確認 (env) D:\Sandbox\scapy2_ng>pip list dnet (1.12) pcapy (0.10.10) pip (7.1.2) scapy (2.3.2) setuptools (18.2) wheel (0.24.0)
再度実行してみます。
(env) D:\Sandbox\scapy2_ng>python runner.py ... AttributeError: 'module' object has no attribute 'ex_name'
またエラーとなりました。
このエラー原因を探してみたところ、冒頭のstackoverflowにたどり着き、GitHubからインストールすれば良いということが分かりました。
NG: Python3.5.1 + PyPIのscapy-python3(scapy3k)
Python3でScapyを扱う方法がないかを探してみたところ、Scapyからforkしたscapy-python3(scapy3k)がありました。
phaethon/scapy: Network packet and pcap file crafting/sniffing/manipulation/visualization security tool (based on scapy) with python3 compatibility
いくつかの改善と互換性維持があり、OSのサポート状況については、
Currently, works on Linux, Darwin, Unix and co. Using python 3.4 on Ubuntu and FreeBSD for testing. Windows support in progress.
とのことでした。
試してみます。
# virtualenv準備
D:\Sandbox>mkdir scapy3k_ng
D:\Sandbox>cd scapy3k_ng
D:\Sandbox\scapy3k_ng>virtualenv -p c:\python35-32\python.exe env
D:\Sandbox\scapy3k_ng>env\Scripts\activate
# インストール
(env) D:\Sandbox\scapy3k_ng>pip install scapy-python3
(env) D:\Sandbox\scapy3k_ng>pip list
pip (7.1.2)
scapy-python3 (0.18)
setuptools (18.2)
wheel (0.24.0)
# 実行
(env) D:\Sandbox\scapy3k_ng>python runner.py
WARNING: Windows support for scapy3k is currently in testing. Sniffing/sending/receiving packets should be working with WinPcap driver and Powershell. Create issues at https://github.com/phaethon/scapy
Traceback (most recent call last):
File "runner.py", line 2, in <module>
from scapy.all import *
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\all.py", line 16, in <module>
from .arch import *
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\arch\__init__.py", line 88, in <module>
from .windows import *
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\arch\windows\__init__.py", line 198, in <module>
ifaces.load_from_powershell()
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\arch\windows\__init__.py", line 149, in load_from_powershell
for i in get_windows_if_list():
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\arch\windows\__init__.py", line 90, in get_windows_if_list
current_interface['name'] = value.decode('ascii')
UnicodeDecodeError: 'ascii' codec can't decode byte 0x83 in position 0: ordinal not in range(128)
エラーとなりました。
次に、現時点での最新コミットa7cd488b51e29c48430afffe4810aa13bffe62f7を指定してpipでインストールしてみます。
Install specific git commit with pip - Stack Overflow
# アンインストール (env) D:\Sandbox\scapy3k_ng>pip uninstall scapy-python3 ... Proceed (y/n)? y Successfully uninstalled scapy-python3-0.18 # インストール (env) d:\Sandbox\scapy3k_ng>pip install git+https://github.com/phaethon/scapy.git@a7cd488b51e29c48430afffe4810aa13bffe62f7 Collecting git+https://github.com/phaethon/scapy.git@a7cd488b51e29c48430afffe4810aa13bffe62f7 Cloning https://github.com/phaethon/scapy.git (to a7cd488b51e29c48430afffe4810aa13bffe62f7) to c:\users\think\appdata\local\temp\pip-8q2a980a-build Could not find a tag or branch 'a7cd488b51e29c48430afffe4810aa13bffe62f7', assuming commit. Installing collected packages: scapy-python3 Running setup.py install for scapy-python3 Successfully installed scapy-python3-0.18
ちなみに、メッセージの中にCould not find a tag or branch 'xxx', assuming commit.とありますが、該当commitでインストールされているようです。
試しにver0.9のコミットで試してみました。
# インストール (env) d:\Sandbox\scapy3k_ng>pip install git+https://github.com/phaethon/scapy.git@5ca348345d0c36dab8e853c34940b6f8851f3c30 ... Could not find a tag or branch '5ca348345d0c36dab8e853c34940b6f8851f3c30', assuming commit. ... Successfully installed scapy-python3-0.9 # 確認 (env) d:\Sandbox\scapy3k_ng>pip list ... scapy-python3 (0.9) ...
(env) d:\Sandbox\scapy3k_ng>python runner.py
WARNING: No route found for IPv6 destination :: (no default route?). This affects only IPv6
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = icmp
chksum = None
src = 192.168.10.101
dst = Net('www.google.com')
\options \
###[ ICMP ]###
type = echo-request
code = 0
chksum = None
id = 0x0
seq = 0x0
Begin emission:
WARNING: No route found (no default route?)
WARNING: No broadcast address found for iface lo0
ERROR: --- Error sending packets
Traceback (most recent call last):
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\arch\windows\__init__.py", line 325, in sndrcv
pks.send(p)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\arch\pcapdnet.py", line 398, in send
sx = bytes(cls()/x)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\packet.py", line 289, in __bytes__
return self.build()
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\packet.py", line 357, in build
p = self.do_build()
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\packet.py", line 346, in do_build
pkt = self.self_build()
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\packet.py", line 337, in self_build
p = f.addfield(self, p, val)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\fields.py", line 79, in addfield
return s+struct.pack(self.fmt, self.i2m(pkt,val))
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\layers\l2.py", line 95, in i2m
return MACField.i2m(self, pkt, self.i2h(pkt, x))
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\layers\l2.py", line 89, in i2h
x = conf.neighbor.resolve(pkt,pkt.payload)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\layers\l2.py", line 38, in resolve
return self.resolvers[k](l2inst,l3inst)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\layers\inet.py", line 739, in <lambda>
conf.neighbor.register_l3(Ether, IP, lambda l2,l3: getmacbyip(l3.dst))
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\layers\l2.py", line 73, in getmacbyip
nofilter=1)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\sendrecv.py", line 385, in srp1
a,b=srp(*args,**kargs)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\sendrecv.py", line 367, in srp
s = conf.L2socket(iface=iface, filter=filter, nofilter=nofilter, type=type)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\arch\pcapdnet.py", line 321, in __init__
self.ins = open_pcap(iface, 1600, 0, 100)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\arch\windows\__init__.py", line 225, in <lambda>
pcapdnet.open_pcap = lambda iface,*args,**kargs: _orig_open_pcap(pcap_name(iface),*args,**kargs)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\arch\pcapdnet.py", line 251, in <lambda>
open_pcap = lambda *args,**kargs: _PcapWrapper_pypcap(*args,**kargs)
File "D:\Sandbox\scapy3k_ng\env\lib\site-packages\scapy\arch\pcapdnet.py", line 215, in __init__
self.iface = create_string_buffer(device.encode('ascii'))
AttributeError: 'NoneType' object has no attribute 'encode'
.............................
Received 279 packets, got 0 answers, remaining 1 packets
Traceback (most recent call last):
File "runner.py", line 15, in <module>
response.show()
AttributeError: 'NoneType' object has no attribute 'show'
パケットは作れているようですが、パケット送信のところでエラーとなっているようです。
ワーニングでNo broadcast address found for iface lo0が出ていたので、
response = sr1(request, iface='???')
のようにインタフェースを指定した送信を試してみます。
Windowsにおけるネットワークインタフェース名が分からないため、netifacesパッケージを使って確認します。
Netifaces - Alastair’s Place
インタフェースを列挙するスクリプト
import netifaces ifs = netifaces.interfaces() for i in ifs: print("{interface}'s settings: {result}" .format(interface=i, result=netifaces.ifaddresses(i)))
を作り実行してみたところ、
(env) d:\Sandbox\scapy3k_ng>python nw_interface.py
{304C6D5B-xxx-xxx-xxx-xxx}'s settings: {-1000: [{'addr': '5c:xx:xx:xx:xx:xx'}], 2: [{'addr': '169.254.108.111'}], 23: [{'addr':'fe80::xxx'}]}
{5DC64577-xxx-xxx-xxx-xxx}'s settings: {-1000: [{'addr': '00:xx:xx:xx:xx:xx'}], 2: [{'addr': '169.254.95.112'}], 23: [{'addr':'fe80::xxx'}]}
{D492A34B-xxx-xxx-xxx-xxx}'s settings: {-1000: [{'addr': '00:xx:xx:xx:xx:xx'}], 2: [{'broadcast': '192.168.xxx.xxx', 'netmask':'255.255.255.0', 'addr': '192.168.xxx.xxx'}], 23: [{'addr': 'fe80::xxx'}]}
...
という結果を得ました。
ただ、ここで取得できたD492A34B-xxx-xxx-xxx-xxxの値をifaceへ渡してもエラーが出て動作しませんでした。
以上よりWindowsの場合ifaceに何を設定すればよいか分からなかったため、Python3でScapyを使うのは諦めました。