标题：碎片攻击
基本信息
简介碎片攻击 (被动技能)
升级后可以增加迫击炮小队的攻击范围 
研究费用 研究建筑 研究需求 升级时间 
50 50 车间 车间城堡 (Castle) 40 秒. 
持续时间 施法间隔 魔法消耗 射程 作用范围 效果 
无 无 无 无 地面单位 增加攻击范围 
碎片攻击介绍范围10以内，受到全部溅射伤害，范围17.5以内受到一半溅射伤害，范围25以内受到四分之一溅射伤害
全部溅射伤害为25，一半溅射伤害为18，四分之一溅射伤害为12 .　
计算机的碎片攻击
1. 为什么存在IP碎片链路层具有最大传输单元MTU这个特性，它限制了数据帧的最大长度，不
同的网络类型都有一个上限值。以太网的MTU是1500，你可以用 netstat -i 命令查看
这个值。如果IP层有数据包要传，而且数据包的长度超过了MTU，那么IP层就要对数据
包进行分片（fragmentation）操作，使每一片的长度都小于或等于MTU。我们假设要传
输一个UDP数据包，以太网的MTU为1500字节，一般IP首部为20字节，UDP首部为8字节，
数据的净荷（payload）部分预留是1500-20-8=1472字节。如果数据部分大于1472字
节，就会出现分片现象。
IP首部包含了分片和重组所需的信息：
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |R|DF|MF| Fragment Offset
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|<-------------16-------------->|<--3-->|<---------13---------->|
Identification：发送端发送的IP数据包标识字段都是一个唯一值，该值
在分片时被复制到每个片中。
R：保留未用。
DF：Don‘t Fragment，“不分片”位，如果将这一比特置1 ，IP层将不对
数据报进行分片。
MF：More Fragment，“更多的片”，除了最后一片外，其他每个组成数
据报的片都要把该比特置1。
Fragment Offset：该片偏移原始数据包开始处的位置。偏移的字节数是
该值乘以8。
另外，当数据报被分片后，每个片的总长度值要改为该片的长度值。
每一IP分片都各自路由，到达目的主机后在IP层重组，请放心，首部中的
数据能够正确完成分片的重组。你不禁要问，既然分片可以被重组，那么所谓的碎片攻
击是如何产生的呢？
2. IP碎片攻击-=-=-=-=-=-=-=-=-=-=-=
IP首部有两个字节表示整个IP数据包的长度，所以IP数据包最长只能为
0xFFFF，就是65535字节。如果有意发送总长度超过65535的IP碎片，一些老的系统内核
在处理的时候就会出现问题，导致崩溃或者拒绝服务。另外，如果分片之间偏移量经过
精心构造，一些系统就无法处理，导致死机。所以说，漏洞的起因是出在重组算法上。
下面我们逐个分析一些著名的碎片攻击程序，来了解如何人为制造IP碎片来攻击系统。
3. ping o‘ death-=-=-=-=-=-=-=-=-=-=-=
ping o‘ death是利用ICMP协议的一种碎片攻击。攻击者发送一个长度超
过65535的Echo Request数据包，目标主机在重组分片的时候会造成事先分配的65535字
节缓冲区溢出，系统通常会崩溃或挂起。ping不就是发送ICMP Echo Request数据包的
吗？让我们尝试攻击一下吧！不管IP和ICMP首部长度了，数据长度反正是多多益善，就
65535吧，发送一个包：
# ping -c 1 -s 65535 192.168.0.1
Error: packet size 65535 is too large. Maximum is 65507
不走运，看来Linux自带的ping不允许我们做坏事。:(
65507是它计算好的：65535-20-8=65507。Win2K下的ping更抠门，数据只
允许65500大小。所以你必须找另外的程序来发包，但是目前新版本的操作系统已经搞
定这个缺陷了，所以你还是继续往下阅读本文吧。
顺便提一下，记得99年有“爱国主义黑客”（“红客”的前辈）发动全国
网民在某一时刻开始ping某美国站点，试图ping死远程服务器。这其实是一种ping
flood攻击，用大量的Echo Request包减慢主机的响应速度和阻塞目标网络，原理和
ping o‘ death是不一样的，这点要分清楚。
4. jolt2-=-=-=-=-=-=-=-=-=-=-=
jolt2.c是在一个死循环中不停的发送一个ICMP/UDP的IP碎片，可以使
Windows系统的机器死锁。我测试了没打SP的Windows 2000，CPU利用率会立即上升到
100%，鼠标无法移动。
我们用Snort分别抓取采用ICMP和UDP协议发送的数据包。
发送的ICMP包：
01/07-15:33:26.974096 192.168.0.9 -> 192.168.0.1
ICMP TTL:255 TOS:0x0 ID:1109 IpLen:20 DgmLen:29
Frag Offset: 0x1FFE Frag Size: 0x9
08 00 00 00 00 00 00 00 00 .........
发送的UDP包：
01/10-14:21:00.298282 192.168.0.9 -> 192.168.0.1
UDP TTL:255 TOS:0x0 ID:1109 IpLen:20 DgmLen:29
Frag Offset: 0x1FFE Frag Size: 0x9
04 D3 04 D2 00 09 00 00 61 ........a
从上面的结果可以看出：
* 分片标志位MF=0，说明是最后一个分片。
* 偏移量为0x1FFE，计算重组后的长度为 (0x1FFE * 8) + 29 = 65549 >
65535，溢出。
* IP包的ID为1109，可以作为IDS检测的一个特征。
* ICMP包：
类型为8、代码为0，是Echo Request；
校验和为0x0000，程序没有计算校验，所以确切的说这个ICMP包是非法
的。
* UDP包：
目的端口由用户在命令参数中指定；
源端口是目的端口和1235进行OR的结果；
校验和为0x0000，和ICMP的一样，没有计算，非法的UDP。
净荷部分只有一个字符‘a‘。
jolt2.c应该可以伪造源IP地址，但是源程序中并没有把用户试图伪装的
IP地址赋值给src_addr，不知道作者是不是故意的。
jolt2的影响相当大，通过不停的发送这个偏移量很大的数据包，不仅死
锁未打补丁的Windows系统，同时也大大增加了网络流量。曾经有人利用jolt2模拟网络
流量，测试IDS在高负载流量下的攻击检测效率，就是利用这个特性。
5. teardrop-=-=-=-=-=-=-=-=-=-=-=
teardrop也比较简单，默认发送两个UDP数据包，就能使某些Linux内核崩
溃。Snort抓取的结果如下：
第一个：
01/08-11:42:21.985853 192.168.0.9 -> 192.168.0.1
UDP TTL:64 TOS:0x0 ID:242 IpLen:20 DgmLen:56 MF
Frag Offset: 0x0 Frag Size: 0x24
A0 A8 86 C7 00 24 00 00 00 00 00 00 00 00 00 00
.....$..........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
................
00 00 00 00 ....
* MF=1，偏移量=0，分片IP包的第一个。
* 结构图：
|<-------20-------->|<------8------>|<---------------28---------------->|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP | UDP | Data
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
第二个：
01/08-11:42:21.985853 192.168.0.9 -> 192.168.0.1
UDP TTL:64 TOS:0x0 ID:242 IpLen:20 DgmLen:24
Frag Offset: 0x3 Frag Size: 0x4
A0 A8 86 C7 ....
* MF=0，偏移量=0x3，偏移字节数为 0x3 * 8 = 24，最后一个分片。
* 结构图：
|<-------20-------->|<--4-->|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP | Data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
如果修改源代码，第二片IP包的偏移量也可以为0x4，偏移字节数就是
0x4 * 8 = 32。
下面的结构图表示了接收端重组分片的过程，分别对应于偏移字节数为24
和32两种情况：
|<-------20-------->|<------8------>|<---------------28---------------->|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP | UDP | Data
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
| +-+-+-+-+
|<------------- 24 ------------->| Data |
| +-+-+-+-+
|<--4-->|
|
|
+-+-+-+-+
|<-------------------
32 ------------------>| Data |
|
+-+-+-+-+
|<--4-->|
可以看出，第二片IP包的偏移量小于第一片结束的位移，而且算上第二片
IP包的Data，也未超过第一片的尾部，这就是重叠现象（overlap）。老的Linux内核
（1.x - 2.0.x）在处理这种重叠分片的时候存在问题，WinNT/95在接收到10至50个
teardrop分片时也会崩溃。你可以阅读teardrop.c的源代码来了解如何构造并发送这种
数据包。
6. 如何阻止IP碎片攻击-=-=-=-=-=-=-=-=-=-=-=
* Windows系统请打上最新的Service Pack，目前的Linux内核已经不受影
响。
* 如果可能，在网络边界上禁止碎片包通过，或者用iptables限制每秒通
过碎片包的数目。
* 如果防火墙有重组碎片的功能，请确保自身的算法没有问题，否则被
DoS就会影响整个网络。
* Win2K系统中，自定义IP安全策略，设置“碎片检查”。