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を使うのは諦めました。