using System; using System.Linq; using System.IO; using System.Net; using System.Text; using System.Net.Sockets; using System.Threading; using System.Collections; using System.Collections.Generic; using System.Security.Cryptography; using System.Runtime.Serialization.Formatters.Binary; using System.Text.RegularExpressions; namespace _olbaid_websockets { class UnPack { byte [] buffer; public int position; public UnPack(byte[] b){ buffer = b; position = 0; } public uint w (){ uint num = 0; byte bite = 0; do { num*=128; bite = buffer[position++]; num+=(uint)(bite&0x7f); }while ((bite&0x80)>0); return num; } } class Client { private Socket client; private Thread thread; private Socket deliantraClient = null; private bool upgraded = false; private bool mask = true; private bool useHixie = false; Random r = new Random(); System.Text.UTF8Encoding encodingUTF8 = new System.Text.UTF8Encoding(); private byte[] buffer = new byte[4096*16]; private byte[] mergedBuffer = new byte[4096*32]; private int mergedBufferLength = 0; public bool IsBitSet(byte b, int pos) { return (b & (int)Math.Pow(2, pos)) > 0 ? true : false; } public static int getNSpaces (string s){ return (new String(s.Where( c=> c==' ').ToArray())).Length; } public static Int64 numbers(string s){ char[] nums = s.Where( c => Char.IsNumber(c)).ToArray(); Int64 ret = Int64.Parse(new String(nums)); return ret; } public static void setBytes(byte [] buffer,UInt16 val,int index){ for (int i=0;i<2;++i){ byte b = (byte)((val >> (3-i)*8)&0xff); buffer[index+i] = b; } } public static void setBytes(byte [] buffer,UInt32 val,int index){ for (int i=0;i<4;++i){ byte b = (byte)((val >> (3-i)*8)&0xff); buffer[index+i] = b; } } public static void setBytesR(byte [] buffer,UInt16 val,int index){ for (int i=1;i>=0;--i){ byte b = (byte)((val >> (3-i)*8)&0xff); buffer[index+i] = b; } } public static byte [] calcHixieResponse (string key1,string key2,byte [] l8b){ UInt64 numbers1 = (UInt64) numbers(key1); UInt64 numbers2 = (UInt64) numbers(key2); UInt64 spaces1 = (ulong)getNSpaces(key1); UInt64 spaces2 = (ulong)getNSpaces(key2); byte [] key = new byte [16]; Array.Clear(key,0,16); setBytes(key,(UInt32)(((numbers1/spaces1))),0); setBytes(key,(UInt32)(((numbers2/spaces2))),4); Array.Copy(l8b,0,key,8,8); MD5 md5Hash = MD5.Create(); return md5Hash.ComputeHash(key); } public static void setBytesR(byte [] buffer,UInt32 val,int index){ for (int i=3;i>=0;--i){ byte b = (byte)((val >> (3-i)*8)&0xff); buffer[index+i] = b; } } public void onReceivedClientData (IAsyncResult asyn){ Socket mySocket = (Socket)asyn.AsyncState; int bytesRead = mySocket.EndReceive(asyn); if (bytesRead==0){ Console.WriteLine ("Connection closed by socket {0}" , mySocket==client?" client " : " deliantra "); mySocket.Close(); if ((mySocket==client)&&(deliantraClient!=null)){ client = null; Console.WriteLine ("trying to close deliantraClient"); try { deliantraClient.Close(); deliantraClient = null; }catch (Exception ex){ } } return; } if (mySocket == client){ //deliantraClient.Send(buffer,bytesRead,0); Hashtable request = new Hashtable(); if (upgraded == false){ dump(buffer,bytesRead); string incoming = encodingUTF8.GetString(buffer,0,bytesRead); Console.WriteLine (incoming); string [] lines = incoming.Split(new string [] {"\n"},StringSplitOptions.RemoveEmptyEntries); for (int i = 1;i=3) request.Add(line[0].ToString().ToLower().Trim(),line[1] + ":" + line[2]); else if (line.Length>=2) request.Add(line[0].ToString().ToLower().Trim(),line[1]); } foreach (DictionaryEntry e in request){ Console.WriteLine(e.Key.ToString() + " : '" + e.Value.ToString() + "'"); } if (request["sec-websocket-key1"]!=null){ string key1 = "357184 636 L0"; key1 = request["sec-websocket-key1"].ToString().Trim(); string key2 = "U 4=> 9&6= 52OeA[8 #880"; key2 = request["sec-websocket-key2"].ToString().Trim(); byte [] l8b = new byte[8]; Array.Copy (buffer,bytesRead-8,l8b,0,8); dump(l8b,8); byte [] hixiResp = calcHixieResponse(key1,key2,l8b); string origin = (string) (request["origin"] != null ? request["origin"].ToString().Trim(): ""); //origin="http://localhost"; string host = (string) (request["host"] != null ? request["host"].ToString().Trim (): ""); string location = Regex.Match(incoming,@"(/[a-z]+)",RegexOptions.IgnoreCase).Value.ToString(); StringBuilder bResponse = new StringBuilder(); bResponse.Append("HTTP/1.1 101 WebSocket Protocol Handshake\r\n"); bResponse.Append( "Upgrade: WebSocket\r\n"); bResponse.Append("Connection: Upgrade\r\n"); bResponse.AppendFormat("Sec-WebSocket-Origin: {0}\r\n",origin); bResponse.Append( "Sec-WebSocket-Protocol: chat\r\n"); bResponse.AppendFormat("Sec-WebSocket-Location: ws://{0}{1}\r\n\r\n",host,location); byte [] data = encodingUTF8.GetBytes(bResponse.ToString()); byte [] result = new byte[data.Length+hixiResp.Length]; Array.Copy(data,0,result,0,data.Length); Array.Copy(hixiResp,0,result,data.Length,hixiResp.Length); client.Send(result,result.Length,SocketFlags.None); useHixie = true; upgraded = true; }else{ string key = ""; if (request["sec-websocket-key"]!=null){ Console.WriteLine("Key: " + request["sec-websocket-key"].ToString()); key = request["sec-websocket-key"].ToString().Trim(); }else{ key = ""; } if (request["sec-websocket-extensions"]!=null){ mask = false; } Console.WriteLine(key); //key+=Guid.NewGuid().ToString(); key+="258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; Console.WriteLine(key); SHA1 sha = new SHA1CryptoServiceProvider(); byte [] hash = sha.ComputeHash(encoding.GetBytes(key)); key = EncodeTo64(hash); Console.WriteLine(key); string response = "HTTP/1.1 101 Switching Protocols\n" + "Upgrade: websocket\n" + "Connection: Upgrade\n" //+ "Sec-WebSocket-Protocol: chat\r\n" + "Sec-WebSocket-Accept: " + key +"\n\n"; response = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" + "Upgrade: WebSocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: " +key + "\r\n\r\n"; client.Send(encoding.GetBytes(response)); upgraded = true; } deliantraClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); deliantraClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); IPEndPoint ipLocal = new IPEndPoint(IPAddress.Parse("194.126.175.156"), 13327); deliantraClient.Connect(ipLocal); deliantraClient.BeginReceive(buffer, 0, 4096, 0, new AsyncCallback(onReceivedClientData),deliantraClient); }else{ //dump (buffer,bytesRead); String msg = receiveMessage(buffer,bytesRead); Console.WriteLine(msg); Array.Copy(encodingUTF8.GetBytes(msg),0,buffer,2,bytesRead = encodingUTF8.GetBytes(msg).Length); buffer [0] = (byte)(bytesRead/256); buffer [1] = (byte)(bytesRead%256); deliantraClient.Send(buffer,0,bytesRead+2,0); //Console.WriteLine(encoding.GetString(unmaskedData,0,payloadLen)); //sendMessage("HELLO CRUEL WORLD"); } }else{ //client.Send(buffer,bytesRead,0); //dump (buffer,bytesRead); if (client == null){ deliantraClient.Close(); deliantraClient = null; return; } Array.Copy ( buffer,0,mergedBuffer,mergedBufferLength,bytesRead); mergedBufferLength += bytesRead; int index = 0; int len; byte [] tmpBuffer; while (index256*256+256){ bigger = true; }else if (len>125){ big = true; } byte [] buffer; if (bigger){ buffer = new byte[len+6+(mask?4:0)]; Array.Clear(buffer,0,len+6+(mask?4:0)); }else if (big){ buffer = new byte[len+4+(mask?4:0)]; Array.Clear(buffer,0,len+4+(mask?4:0)); }else{ buffer = new byte[len+2+(mask?4:0)]; Array.Clear(buffer,0,len+2+(mask?4:0)); } int optcode = 1; buffer[0] = (byte)(128 + optcode); int maskVal = 0; if (mask){ maskVal = 128; } if (bigger){ buffer[1] = (byte)(maskVal + 127); buffer[5] = (byte)(len%256); len/=256; buffer[4] = (byte)(len%256); len/=256; buffer[3] = (byte)(len%256); len/=256; buffer[2] = (byte)(len%256); }else if (big){ buffer[1] = (byte)(maskVal + 126); buffer[2] = (byte)(len/256); buffer[3] = (byte)(len%256); }else{ buffer[1] = (byte)(maskVal + len ); } if (mask){ byte [] maskKey = new byte[4]; r.NextBytes(maskKey); if (bigger){ Array.Copy(maskKey,0,buffer,6,4); }else if (big){ Array.Copy(maskKey,0,buffer,4,4); }else{ Array.Copy(maskKey,0,buffer,2,4); } if (bigger){ for (int i = 0 ; i256*256+256){ bigger = true; }else if (len>125){ big = true; } byte [] buffer; if (bigger){ buffer = new byte[len+6+(mask?4:0)]; Array.Clear(buffer,0,len+6+(mask?4:0)); }else if (big){ buffer = new byte[len+4+(mask?4:0)]; Array.Clear(buffer,0,len+4+(mask?4:0)); }else{ buffer = new byte[len+2+(mask?4:0)]; Array.Clear(buffer,0,len+2+(mask?4:0)); } int optcode = 1; buffer[0] = (byte)(128 + optcode); int maskVal = 0; if (mask){ maskVal = 128; } if (bigger){ buffer[1] = (byte)(maskVal + 127); buffer[5] = (byte)(len%256); len/=256; buffer[4] = (byte)(len%256); len/=256; buffer[3] = (byte)(len%256); len/=256; buffer[2] = (byte)(len%256); }else if (big){ buffer[1] = (byte)(maskVal + 126); buffer[2] = (byte)(len/256); buffer[3] = (byte)(len%256); }else{ buffer[1] = (byte)(maskVal + len ); } if (mask){ byte [] maskKey = new byte[4]; r.NextBytes(maskKey); if (bigger){ Array.Copy(maskKey,0,buffer,6,4); }else if (big){ Array.Copy(maskKey,0,buffer,4,4); }else{ Array.Copy(maskKey,0,buffer,2,4); } if (bigger){ for (int i = 0 ; i0&&offset%16==0){ Console.Write(encoding.GetString(b,offset-16,16)); Console.WriteLine(); } offset+=1; } Console.WriteLine(); } } }