using System; using System.Net.Sockets; using System.Threading; using KaduhServer; namespace PatcherServer.FileCheck { public sealed class HackClient { public delegate void HackClientPass(HackClient pClient); public delegate void PassPacket(Packet pPacket, HackClient pClient); private LockFreeQueue mSendSegments = new LockFreeQueue(); private int mSending = 0; private short Key = 0; public DateTime Authenciated; public string Username = ""; public string OS = ""; public string GUID = ""; #region checks public bool gotPCInfo = false; public bool didFileCheck = false; #endregion public event HackClientPass OnDisconnect; public event PassPacket OnPacketReceived; public bool Disconnected = false; public Socket mSock; private byte[] pBuffer; public HackClient(Socket pSocket) { this.mSock = pSocket; SendHandShake(); RequestPCInfo(); BeginReceive(); } public string IP { get { return mSock.RemoteEndPoint.ToString().Split(':')[0]; } } public void SendHandShake() { Packet handShake = new Packet(0); Random keyGen = new Random(); Key = (short)keyGen.Next(0, 255); handShake.WriteShort(Key); mSock.Send(handShake.ToArray()); } private void BeginReceive() { if (!mSock.Connected) { Disconnect(); return; } mSock.BeginReceive(pBuffer = new byte[4], 0, 4, SocketFlags.None, new AsyncCallback(OnHeader), mSock); } void RequestPCInfo() { Packet pack = new Packet(1); SendPacket(pack); } private void OnHeader(IAsyncResult ar) { try { if (!mSock.Connected) { Disconnect(); return; } int len = mSock.EndReceive(ar); if (len <= 0) { Disconnect(); return; } if (!CheckPacket(pBuffer)) { Disconnect(); return; } int packLen = getPacketLength(pBuffer); mSock.BeginReceive(pBuffer = new byte[packLen], 0, packLen, SocketFlags.None, new AsyncCallback(OnData), mSock); } catch { Disconnect(); } } public void Disconnect() { if (Disconnected) return; if (OnDisconnect != null) OnDisconnect.Invoke(this); Disconnected = true; try { mSock.Shutdown(SocketShutdown.Both); } catch { Disconnect(); } } public void SendPacket(Packet pPacket) { try { if (!mSock.Connected) { Disconnect(); return; } byte[] toSend = new byte[pPacket.Length + 4]; Buffer.BlockCopy(GetHeader(pPacket.Length), 0, toSend, 0, 4); Buffer.BlockCopy(pPacket.ToArray(), 0, toSend, 4, pPacket.Length); mSendSegments.Enqueue(new ByteArraySegment(toSend)); if (Interlocked.CompareExchange(ref mSending, 1, 0) == 0) BeginSend(); } catch { } } private void BeginSend() { SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.Completed += (s, a) => EndSend(a); ByteArraySegment segment = mSendSegments.Next; args.SetBuffer(segment.Buffer, segment.Start, segment.Length); try { if (!mSock.SendAsync(args)) EndSend(args); } catch (ObjectDisposedException) { Disconnect(); } } private void EndSend(SocketAsyncEventArgs pArguments) { if (!mSock.Connected) { Disconnect(); return; } if (pArguments.BytesTransferred <= 0) { Disconnect(); return; } if (mSendSegments.Next.Advance(pArguments.BytesTransferred)) mSendSegments.Dequeue(); if (mSendSegments.Next != null) BeginSend(); else mSending = 0; } private void OnData(IAsyncResult ar) { try { if (!mSock.Connected) return; int len = mSock.EndReceive(ar); if (len <= 0) { Disconnect(); return; } Packet pack = new Packet(pBuffer, 0, pBuffer.Length); if (OnPacketReceived != null) OnPacketReceived.Invoke(pack, this); BeginReceive(); } catch { Disconnect(); } } private bool CheckPacket(byte[] packet) { int a = packet[0] ^ FileSecurity.Version[2]; int b = Key % 0x100; int c = packet[1] ^ FileSecurity.Version[3]; int d = 0; return (a == b && c == d); } public static int getPacketLength(byte[] packetHeader) { if (packetHeader.Length < 4) { return -1; } return (((int)(packetHeader[0] ^ packetHeader[2])) | (((int)(packetHeader[1] ^ packetHeader[3]) << 8) & 0xFF00)); } public byte[] GetHeader(int size) { byte[] header = new byte[4]; int a = FileSecurity.Version[3] * 0x100 + FileSecurity.Version[2]; a = a ^ (Key); int b = a ^ size; header[0] = Convert.ToByte(a % 0x100); header[1] = Convert.ToByte(a / 0x100); header[2] = Convert.ToByte(b % 0x100); header[3] = Convert.ToByte(b / 0x100); return header; } } }