【转】关于Scapy
关于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
- >>> conf.verb=2
ython-pcapy
安装完毕后测试结果如下:
- walfred@walfred-VirtualBox:~/wmw/scapy/test$ sudo scapy
- Welcome to Scapy (2.2.0)
- >>> IP()
- <IP |>
- >>> target="www.baidu.com"
- >>> ip=IP(dst=target)
- >>> ip
- <IP dst=Net('www.baidu.com') |>
- >>> [p for p in ip]
- [<IP dst=180.97.33.107 |>]
- >>>
Scapy的使用特性
1、conf 变量保存了配置信息
- >>> conf
- ASN1_default_codec = <ASN1Codec BER[1]>
- AS_resolver = <scapy.as_resolvers.AS_resolver_multi instance at 0xb5fd4c0c>
- BTsocket = <BluetoothL2CAPSocket: read/write packets on a connected L2CAP ...
- L2listen = <L2ListenSocket: read packets at layer 2 using Linux PF_PACKET ...
- L2socket = <L2Socket: read/write packets at layer 2 using Linux PF_PACKET ...
- L3socket = <L3PacketSocket: read/write packets at layer 3 using Linux PF_P...
- auto_fragment = 1
- checkIPID = 0
- checkIPaddr = 1
- checkIPsrc = 1
- check_TCPerror_seqack = 0
- color_theme = <RastaTheme>
- commands = arpcachepoison : Poison target's cache with (your MAC,victim's ...
- debug_dissector = 0
- debug_match = 0
- default_l2 = <class 'scapy.packet.Raw'>
- emph = <Emphasize []>
- ethertypes = </etc/ethertypes/ ATMMPOA RAW_FR DNA_DL ATMFATE ATALK BPQ X25 P...
- 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 = </usr/wireshark/wireshark/manuf/ >
- mib = <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 = <Resolve []>
- padding = 1
- prog = display = 'display' dot = 'dot' hexedit = 'hexer' pdfreader = '...
- promisc = 1
- prompt = '>>> '
- protocols = </etc/protocols/ pim ip ax_25 esp tcp ah mpls_in_ip rohc ipv6_o...
- raw_layer = <class 'scapy.packet.Raw'>
- raw_summary = False
- readfunc = None
- resolve = <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 = </etcrvices-tcp/ kpop zabbix_trapper noclog svn cmip_man b...
- services_udp = </etcrvices-udp/ zabbix_trapper noclog cmip_man z3950 root...
- 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属性
- >>> conf.verb=2
2、数据操作
- >>> IP()
- <IP |>
- >>> test_ip=IP(dst="192.168.115.188")<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
- >>> test_ip.dst
- '192.168.115.188'
- >>> test_ip.ttl
- 64
- >>> test_ip.ttl=32 修改ttl值
- >>> test_ip
- <IP ttl=32 dst=192.168.115.188 |>
- >>> del(test_ip.ttl) 删除tt值
- >>> test_ip
- <IP dst=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
- <TCP flags=SA |>
- >>> test_tcp.flags=23
- >>> test_tcp
- <TCP flags=FSRA |>
- >>> i=IP(flags="DF+MF")
- >>> i.flags
- 3
- >>> i.flags=6
- >>> i
- <IP flags=DF+evil |>
- >>>
- >>> 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'
- >>> </div>
注:以下的“/”符号表示两个链路层的组合。这样</span><span style="font-size:18px;">下层可以层重载上一层的默认值或多个字段值。
- >>> IP()
- <IP |>
- >>>> IP()/TCP()
- <IP frag=0 proto=tcp |<TCP |>>
- >>>> IP(proto=55)/TCP()
- <IP frag=0 proto=55 |<TCP >>
- >>>> Ether()/IP()/TCP()
- <Ether type=IPv4 |<IP frag=0 proto=tcp |<TCP |>>>
- >>>> IP()/TCP()/"GET /HTTP/1.0\r\n\r\n" 数据部分可以直接使用字符串
- <IP frag=0 proto=tcp |<TCP |<Raw load='GET /HTTP/1.0\r\n\r\n' |>>>
- >>>> Ether()/IP()/UDP()
- <Ether type=IPv4 |<IP frag=0 proto=udp |<UDP |>>>
- >>>> Ether()/IP()/IP()/UDP()
- <Ether type=IPv4 |<IP frag=0 proto=ipencap |<IP frag=0 proto=udp |<UDP |>>>>
- >>> str(IP())
- 'E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01'
- >>> IP(_)
- <IP version=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 .C....@.px..s..a
- 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
- <Ether dst=00:03:0f:19:6a:49 src=08:00:27:fe:d8:12 type=IPv4 |<IP version=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=[] |<TCP sport=ftp_data dport=http
- seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0xb375 urgptr=0
- options=[] |<Raw load='GET /index.html HTTP/1.0 \n\n' |>>>>
- >>> c.hide_defaults() 如果觉得过于冗长,可以使用这个函数隐藏
- >>> c
- <Ether dst=00:03:0f:19:6a:49 src=08:00:27:fe:d8:12 type=IPv4 |<IP ihl=5L len=67
- frag=0 proto=tcp chksum=0x7078 src=192.168.115.198 dst=180.97.33.108 |<TCP
- dataofs=5L chksum=0xb375 options=[] |<Raw load='GET /index.html HTTP/1.0 \n\n' |
- >>>>
- >>> a=rdpcap("/mnt/share/test1.cap") 我使用的wireshark,保存成pcap的格式
- >>> a
- <test1.cap: TCP: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
- <IP dst=Net('www.baidu.com/30') |>
- >>> [p for p in a]
- [<IP dst=180.97.33.104 |>, <IP dst=180.97.33.105 |>, <IP dst=180.97.33.106 |>,
- <IP dst=180.97.33.107 |>]
- >>> b=IP(ttl=[1,2,(5,9)])
- >>> b
- <IP ttl=[1, 2, (5, 9)] |>
- >>> [p for p in b]
- [<IP ttl=1 |>, <IP ttl=2 |>, <IP ttl=5 |>, <IP ttl=6 |>, <IP ttl=7 |>, <IP
- ttl=8 |>, <IP ttl=9 |>]
- >>> c=TCP(dport=[80,443])
- >>> [p for p in a/c] 产生多个数据包
- [<IP frag=0 proto=tcp dst=180.97.33.104 |<TCP dport=http |>>, <IP frag=0
- proto=tcp dst=180.97.33.104 |<TCP dport=https |>>, <IP frag=0 proto=tcp
- dst=180.97.33.105 |<TCP dport=http |>>, <IP frag=0 proto=tcp dst=180.97.33.105 |
- <TCP dport=https |>>, <IP frag=0 proto=tcp dst=180.97.33.106 |<TCP dport=http |
- >>, <IP frag=0 proto=tcp dst=180.97.33.106 |<TCP dport=https |>>, <IP frag=0
- proto=tcp dst=180.97.33.107 |<TCP dport=http |>>, <IP frag=0 proto=tcp
- dst=180.97.33.107 |<TCP dport=https |>>]
- >>>
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()
- >>> 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
- <IP 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=[] |<ICMP type=echo-reply code=0 chksum=0x1826 id=0x0 seq=0x0 |<Raw load='test' |<Padding load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>>>
- >>> p.show()
- ###[ IP ]###
- 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\
- ###[ ICMP ]###
- type= echo-reply
- code= 0
- chksum= 0x1826
- id= 0x0
- seq= 0x0
- ###[ Raw ]###
- load= 'test'
- ###[ Padding ]###
- load= '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'