http://blog.csdn.net/wang_walfred/article/details/40044141
关于Scapy
Scapy的是一个强大的交互式数据包处理程序(使用Python编写)。它能够伪造或者解码大量的网络协议数据包,能够发送、捕捉、匹配请求和回复包等等。它可以很容易地处理一些典型操作,比如端口扫描,tracerouting,探测,单元测试,攻击或网络发现(可替代hping,NMAP,arpspoof,ARP-SK,arping,tcpdump,tethereal,P0F等)。最重要的他还有很多更优秀的特性——发送无效数据帧、注入修改的802.11数据帧、在WEP上解码加密通道(VOIP)、ARP缓存攻击(VLAN)等,这也是其他工具无法处理完成的。
安装Scapy
这里我没有使用安装包进行安装,而是直接使用 命令 apt-get install python-scapy,根据提示安装相应的数据包,这里我使用的ubuntu 14.04,使用的安装包如下:
tcpreplay graphviz imagemagick python-gnuplot python-pyx ebtables python-visual sox xpdf gv hexer librsvg2-binp
ython-pcapy
安装完毕后测试结果如下:
- walfred@walfred-VirtualBox:~/wmw/scapy/test$ sudo scapy
- Welcome to Scapy (2.2.0)
- >>> IP()
-
- >>> target="www.baidu.com"
- >>> ip=IP(dst=target)
- >>> ip
-
- >>> [p for p in ip]
- []
- >>>
Scapy的使用特性
1、conf 变量保存了配置信息
- >>> conf
- ASN1_default_codec = 1]>
- AS_resolver = 0xb5fd4c0c>
- BTsocket =
- L2listen = 2 using Linux PF_PACKET ...
- L2socket = 2 using Linux PF_PACKET ...
- L3socket = 3 using Linux PF_P...
- auto_fragment = 1
- checkIPID = 0
- checkIPaddr = 1
- checkIPsrc = 1
- check_TCPerror_seqack = 0
- color_theme =
- commands = arpcachepoison : Poison target's cache with (your MAC,victim's ...
- debug_dissector = 0
- debug_match = 0
- default_l2 = <class 'scapy.packet.Raw'>
- emph =
- ethertypes =
- except_filter = ''
- extensions_paths = '.'
- histfile = '/home/walfred/.scapy_history'
- iface = 'eth0'
- iface6 = 'eth0'
- interactive = True
- interactive_shell = ''
- ipv6_enabled = True
- l2types = 0x1 <- Dot3 (802.3) 0x1 <-> Ether (Ethernet) 0xc -> IP (IP) 0x1...
- l3types = 0x3 -> IP (IP) 0x800 <-> IP (IP) 0x806 <-> ARP (ARP) 0x86dd <->...
- layers = Packet : None NoPayload : None Raw : Raw Padding : Padding ASN1...
- load_layers = ['l2', 'inet', 'dhcp', 'dns', 'dot11', 'gprs', 'hsrp', 'inet6'...
- logLevel = 20
- manufdb =
- mib =
- neighbor = Ether -> Dot1Q Ether -> IP Dot3 -> LLC Dot3 -> SNAP Dot3 -> IP ...
- netcache = arp_cache: 0 valid items. Timeout=120s in6_neighbor: 0 valid it...
- noenum =
- padding = 1
- prog = display = 'display' dot = 'dot' hexedit = 'hexer' pdfreader = '...
- promisc = 1
- prompt = '>>> '
- protocols =
- raw_layer = <class 'scapy.packet.Raw'>
- raw_summary = False
- readfunc = None
- resolve =
- route = Network Netmask Gateway Iface Output IP 127.0.0.0 255.0.0.0 0.0...
- route6 = Destination Next Hop iface src candidates 2400:dd01:3000:10::/6...
- services_tcp =
- services_udp =
- session = ''
- sniff_promisc = 1
- stats_classic_protocols = [<class 'scapy.layers.inet.TCP'>, <class 'scapy.la...
- stats_dot11_protocols = [<class 'scapy.layers.inet.TCP'>, <class 'scapy.laye...
- stealth = 'not implemented'
- temp_files = []
- teredoPrefix = '2001::'
- teredoServerPort = 3544
- use_dnet = False
- use_pcap = False
- verb = 1
- version = '2.2.0'
- warning_threshold = 5
- wepkey = ''
- >>>
更改这些配置信息也比较方便:比如修改verb属性
2、数据操作
- >>> IP()
-
- >>> test_ip=IP(dst="192.168.115.188")"font-family: Arial, Helvetica, sans-serif;">
- >>> test_ip.dst
- '192.168.115.188'
- >>> test_ip.ttl
- 64
- >>> test_ip.ttl=32 修改ttl值
- >>> test_ip
- 32 dst=192.168.115.188 |>
- >>> del(test_ip.ttl) 删除tt值
- >>> test_ip
- 192.168.115.188 |>
- >>> test_ip.ttl 恢复了默认的ttl值
- 64
- >>> test_tcp=TCP()
- >>> test_tcp.flags
- 2
- >>> test_tcp.flags="SA"
- >>> test_tcp.flags
- 18
- >>> test_tcp
-
- >>> test_tcp.flags=23
- >>> test_tcp
-
- >>> i=IP(flags="DF+MF")
- >>> i.flags
- 3
- >>> i.flags=6
- >>> i
-
- >>>
- >>> test_ip.src
- '192.168.115.198'
- >>> test_ip.dst
- '192.168.115.188'
- >>> del(test_ip.dst) 注意删除后的变化
- >>> test_ip.dst
- '127.0.0.1'
- >>> test_ip.src
- '127.0.0.1'
- >>> test_ip.dst="192.168.115.188" 重新设定目标地址
- >>> test_ip.src
- '192.168.115.198'
- >>>
注:以下的“/”符号表示两个链路层的组合。这样下层可以层重载上一层的默认值或多个字段值。
- >>> IP()
-
- >>>> IP()/TCP()
- 0 proto=tcp |>
- >>>> IP(proto=55)/TCP()
- 0 proto=55 |>
-
- >>>> Ether()/IP()/TCP()
- 0 proto=tcp |>>
- >>>> IP()/TCP()/"GET /HTTP/1.0\r\n\r\n" 数据部分可以直接使用字符串
- 0 proto=tcp |'GET /HTTP/1.0\r\n\r\n' |>>>
- >>>> Ether()/IP()/UDP()
- 0 proto=udp |>>
- >>>> Ether()/IP()/IP()/UDP()
- 0 proto=ipencap |0 proto=udp |>>>
-
-
- >>> str(IP())
- 'E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01'
- >>> IP(_)
- 4L ihl=5L tos=0x0 len=20 id=1 flags= frag=0L ttl=64 proto=hopopt
-
- chksum=0x7ce7 src=127.0.0.1 dst=127.0.0.1 |>
- >>> a=Ether()/IP(dst="www.baidu.com")/TCP()/"GET /index.html HTTP/1.0 \n\n"
- >>> hexdump(a)
- 0000 00 03 0F 19 6A 49 08 00 27 FE D8 12 08 00 45 00 ....jI..'.....E.
- 0010 00 43 00 01 00 00 40 06 70 78 C0 A8 73 C6 B4 61 [email protected]
- 0020 21 6C 00 14 00 50 00 00 00 00 00 00 00 00 50 02 !l...P........P.
- 0030 20 00 B3 75 00 00 47 45 54 20 2F 69 6E 64 65 78 ..u..GET /index
- 0040 2E 68 74 6D 6C 20 48 54 54 50 2F 31 2E 30 20 0A .html HTTP/1.0 .
- 0050 0A .
- >>> b=str(a)
- >>> b
- "\x00\x03\x0f\x19jI\x08\x00'\xfe\xd8\x12\x08\x00E\x00\x00C\x00\x01\x00\x00@\x06px
-
- \xc0\xa8s\xc6\xb4a!l\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\xb3u
-
- \x00\x00GET /index.html HTTP/1.0 \n\n"
- >>> c=Ether(b)
- >>> c
- 00:03:0f:19:6a:49 src=08:00:27:fe:d8:12 type=IPv4 |4L
-
- ihl=5L tos=0x0 len=67 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0x7078
-
- src=192.168.115.198 dst=180.97.33.108 options=[] |
-
- seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0xb375 urgptr=0
-
- options=[] |'GET /index.html HTTP/1.0 \n\n' |>>>>
-
- >>> c.hide_defaults() 如果觉得过于冗长,可以使用这个函数隐藏
- >>> c
- 00:03:0f:19:6a:49 src=08:00:27:fe:d8:12 type=IPv4 |5L len=67
-
- frag=0 proto=tcp chksum=0x7078 src=192.168.115.198 dst=180.97.33.108 |
-
- dataofs=5L chksum=0xb375 options=[] |'GET /index.html HTTP/1.0 \n\n' |
-
- >>>>
-
- >>> a=rdpcap("/mnt/share/test1.cap") 我使用的wireshark,保存成pcap的格式
- >>> a
- 13 UDP:53 ICMP:4 Other:3>
- >>> a[9].pdfdump(layer_shift=1)
- >>> a[9].psdump("/mnt/share/test1.eps",layer_shift=1)
- 如何产生多个数据包
- >>> a=IP(dst="www.baidu.com/30")
- >>> a
- 'www.baidu.com/30') |>
- >>> [p for p in a]
- [180.97.33.104 |>, 180.97.33.105 |>, 180.97.33.106 |>,
-
- 180.97.33.107 |>]
- >>> b=IP(ttl=[1,2,(5,9)])
- >>> b
- 1, 2, (5, 9)] |>
- >>> [p for p in b]
- [1 |>, 2 |>, 5 |>, 6 |>, 7 |>,
-
- ttl=8 |>, 9 |>]
- >>> c=TCP(dport=[80,443])
- >>> [p for p in a/c] 产生多个数据包
- [0 proto=tcp dst=180.97.33.104 |>, 0
-
- proto=tcp dst=180.97.33.104 |>, 0 proto=tcp
-
- dst=180.97.33.105 |>, 0 proto=tcp dst=180.97.33.105 |
-
- >, 0 proto=tcp dst=180.97.33.106 |
-
- >>, 0 proto=tcp dst=180.97.33.106 |>, 0
-
- proto=tcp dst=180.97.33.107 |>, 0 proto=tcp
-
- dst=180.97.33.107 |>]
- >>>
3、发送数据包
学习send/sendp/sr/sr1/srp 发送数据包函数使用
- >>> send(IP(dst="192.168.115.188")/ICMP()) send函数工作在第三层
- .
- Sent 1 packets.
- >>> sendp(Ether()/IP(dst="192.168.115.188",ttl=(1,4)),iface="eth0")
- ....
- Sent 4 packets.
- >>> sendp("hello ,i am walfred ",iface="eth0",loop=1,inter=0.2) sendp函数工作在第二层,你可以选择网卡和协议
- ..................................................................................................................................................................................................................................................................................................................................^C
- Sent 322 packets.
fuzz函数的作用:可以更改一些默认的不可以被计算的值(比如校验和checksums),更改的值是随机的,但是类型是符合字段的值的。比如下面的例子,结果如下图对比:
- >>> send(IP(dst="www.baidu.com")/UDP()/NTP(version=4),loop=2) 未使用fuzz()
>>> send(IP(dst="www.baidu.com")/fuzz(UDP()/NTP(version=4)),loop=2) 使用fuzz()
SR()函数用来来发送数据包和接收响应。该函数返回有回应的数据包和没有回应的数据包;该函数也算得上是scapy的核心了,他会返回两个列表数据,一个是answer list 另一个是unanswered list
- >>> sr(IP(dst="192.168.115.1")/TCP(dport=[21,22,23]))
- Begin emission:
- Finished to send 3 packets.
- ***
- Received 3 packets, got 3 answers, remaining 0 packets
- Results: TCP:3 UDP:0 ICMP:0 Other:0>, Unanswered: TCP:0 UDP:0 ICMP:0 Other:0
- >>> ans,unans=_ 这也是scapy的核心了
- >>> ans.show()
- 0000 IP / TCP 192.168.115.198:ftp_data > 192.168.115.1:ftp S ==> IP / TCP 192.168.115.1:ftp > 192.168.115.198:ftp_data RA / Padding
- 0001 IP / TCP 192.168.115.198:ftp_data > 192.168.115.1:ssh S ==> IP / TCP 192.168.115.1:ssh > 192.168.115.198:ftp_data RA / Padding
- 0002 IP / TCP 192.168.115.198:ftp_data > 192.168.115.1:telnet S ==> IP / TCP 192.168.115.1:telnet > 192.168.115.198:ftp_data SA / Padding
- >>>sr(IP(dst="192.168.115.1")/TCP(dport=[21,22,23]),inter=0.5,retry=-2,timeout=1) 网络环境不好时,也可以追加inter retry timeout等附加信息,
函数sr1()是sr()一个变种,只返回应答发送的分组(或分组集)。这两个函数发送的数据包必须是第3层数据包(IP,ARP等)。而函数SRP()位于第2层(以太网,802.3,等)。
- >>> p=sr1(IP(dst="192.168.115.188")/ICMP()/"test")
- Begin emission:
- .....Finished to send 1 packets.
- .*
- Received 7 packets, got 1 answers, remaining 0 packets
- >>> p
- 4L ihl=5L tos=0x0 len=32 id=26000 flags= frag=0L ttl=128 proto=icmp chksum=0x6c79 src=192.168.115.188 dst=192.168.115.198 options=[] |0 chksum=0x1826 id=0x0 seq=0x0 |'test' |'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>>>
- >>> p.show()
-
- version= 4L
- ihl= 5L
- tos= 0x0
- len= 32
- id= 26000
- flags=
- frag= 0L
- ttl= 128
- proto= icmp
- chksum= 0x6c79
- src= 192.168.115.188
- dst= 192.168.115.198
- \options\
-
- type= echo-reply
- code= 0
- chksum= 0x1826
- id= 0x0
- seq= 0x0
-
- load= 'test'
-
- load= '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'