Index

1. はじめに

scapyは、パケットの作成、送信、解析を簡単に行うことが出来るpythonライブラリである。
これを使用すれば、レイヤ2からパケットを作成することができる。
また、pcapファイルなども簡単に解析することができる。
本稿では、パケットの作成、送信を行う。

https://github.com/secdev/scapy

scapyのインストール

python3

% pip3 install scapy

MacOSでは、以下も必要

% brew install libdnet

DebianやRed Hat系だと以下も必要

% sudo apt install tcpdump
% sudo yum install tcpdump

scapy起動

scapyは、pythonプログラム中でインポートする他にも、コマンドを打つことにより、pythonシェルで起動することが出来る。
尚、パケットを送信するには、root権限が必要になる。

pythonシェルで起動

% scapy

インポートして使用

スクリプトにインポートする場合は以下のようにする。

>>> from scapy.all import *

パケットの生成

scapyには、各プロトコルがクラスで定義されており、以下のようにすることによって、パケットを生成することが出来る。

>>> Ether()/IP(dst="192.168.1.1")/TCP(dport=80)
<Ether  type=0x800 |<IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=http |>>>

scapyが対応しているプロトコルは、ls関数で表示することが出来る。

>>> ls()
AH         : AH
ARP        : ARP
ASN1_Packet : None
BOOTP      : BOOTP
CookedLinux : cooked linux
DHCP       : DHCP options
...

また、各クラスがどのような値をとるかもls関数で調べることが出来る。

>>> ls(Ether)
dst        : DestMACField         = (None)
src        : SourceMACField       = (None)
type       : XShortEnumField      = (36864)
>>> 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      = ([])

パケットの送信

送信系関数

パケットを送信する関数は、主に以下がある。

名前 説明
send レイヤ3でパケットを送信する
sendp レイヤ2でパケットを送信する
sr レイヤ3でパケットを送信し、パケットを受信する
sr1 レイヤ3でパケットを送信し、最初のパケットのみを受信する
srp レイヤ2でパケットを送信し、パケットを受信する
srp1 レイヤ2でパケットを送信し、最初のパケットのみを受信する

その他の関数については、以下を参照。

[Scapy] send recv系 使い方まとめ

レイヤ3で送受信

send関数を使用して送信(受信はしない)

send関数を使用してicmpパケットを google.com に送信する。

send(IP(dst="google.com")/ICMP())
.
Sent 1 packets.

"Sent 1 packets." と言うメッセージを非表示にするには、verboseオプションをfalseに設定する。

>>> send(IP(dst="google.com")/ICMP(), verbose=False)

sr1関数を使用して送受信

send関数では、返信を受信しないので、sr1関数を使用して受信する。

>>> sr1(IP(dst="google.com")/ICMP(), verbose=False)
<IP  version=4 ihl=5 tos=0x0 len=28 id=0 flags= frag=0 ttl=49 proto=icmp chksum=0xb4a2 src=172.217.26.14 dst=192.168.77.175 options=[] |<ICMP  type=echo-reply code=0 chksum=0xffff id=0x0 seq=0x0 |<Padding  load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>>

受信したパケットを表示

showメソッドを使用することによって、パケットの中身を見やすく表示することが出来る。

>>> r = sr1(IP(dst="google.com")/ICMP(), verbose=False)
>>> r.show()
###[ IP ]###
  version   = 4
  ihl       = 5
  tos       = 0x0
  len       = 28
  id        = 0
  flags     =
  frag      = 0
  ttl       = 49
  proto     = icmp
  chksum    = 0xb4a2
  src       = 172.217.26.14
  dst       = 192.168.77.175
  \options   \
###[ ICMP ]###
     type      = echo-reply
     code      = 0
     chksum    = 0xffff
     id        = 0x0
     seq       = 0x0
###[ Padding ]###
        load      = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

また、以下のようにすることで、特定のプロトコルや値を表示することが出来る。

>>> r["IP"]
<IP  version=4 ihl=5 tos=0x0 len=28 id=0 flags= frag=0 ttl=49 proto=icmp chksum=0xb4a2 src=172.217.26.14 dst=192.168.77.175 options=[] |<ICMP  type=echo-reply code=0 chksum=0xffff id=0x0 seq=0x0 |<Padding  load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>>

>>> r["IP"].src
'172.217.26.14'

0件のコメント

コメントを残す

アバタープレースホルダー

メールアドレスが公開されることはありません。 が付いている欄は必須項目です