/// <summary> /// Verifies whether the packet is valid or not through the HMAC hash /// </summary> /// <param name="packetBuffer">The packet data the way it was received</param> /// <param name="hmacKey"></param> public static bool CheckHmac(byte[] packetBuffer, byte[] hmacKey) { using (HMACMD5 hmac = new HMACMD5(hmacKey)) { // Gets the total data size from the packet buffer short totalSize = BitConverter.ToInt16(BitConverter.IsLittleEndian ? BytesUtil.ReadBytes(packetBuffer, 0, 2) : BytesUtil.ReadBytes(packetBuffer, 0, 2).Reverse().ToArray(), 0); short dataSize = (short)(totalSize - 2 - CryptoConstants.GC_HMAC_SIZE); byte[] computedHash = BytesUtil.ReadBytes(hmac.ComputeHash(packetBuffer, 2, dataSize), 0, CryptoConstants.GC_HMAC_SIZE); byte[] storedHash = BytesUtil.ReadBytes(packetBuffer, totalSize - CryptoConstants.GC_HMAC_SIZE, CryptoConstants.GC_HMAC_SIZE); // Compares both hashes to check the integrity for (int i = 0; i < computedHash.Length; i++) { if (computedHash[i] != storedHash[i]) { return(false); } } return(true); } }
/// <summary> /// Generates an HMAC hash to the encrypted packet data /// </summary> /// <param name="data">Packet data (excluding the packet size and the HMAC hash)</param> /// <param name="hmacKey">HMAC Key</param> internal static byte[] GenerateHmac(byte[] data, byte[] hmacKey) { using (HMACMD5 hmac = new HMACMD5(hmacKey)) { // Generates the hash, truncates it to 10 bytes (HMAC_SIZE) and returns it return(BytesUtil.ReadBytes(hmac.ComputeHash(data, 0, data.Length), 0, CryptoConstants.GC_HMAC_SIZE)); } }
/// <summary> /// Returns the compressed packet from the input data /// </summary> /// <param name="dataToCompress">Packet data to be compressed</param> public static byte[] CompressPacket(byte[] dataToCompress) { using (MemoryStream memoryStream = new MemoryStream()) { using (ZlibStream compressor = new ZlibStream(memoryStream, CompressionMode.Compress, CompressionLevel.Level1)) { compressor.Write(dataToCompress, 11, (dataToCompress.Length - 11)); } return(BytesUtil.ConcatBytes(BytesUtil.ReadBytes(dataToCompress, 0, 11), memoryStream.ToArray())); } }
/// <summary> /// Gets the received packet data and returns the decrypted data /// </summary> /// <param name="packetBuffer">The packet data the way it was received</param> /// <param name="key">DES Encryption Key</param> /// <param name="IV">Initialization vector</param> public static byte[] DecryptPacket(byte[] packetBuffer, byte[] key, bool isHaveLength = false) { if (!isHaveLength) { packetBuffer = BytesUtil.ConcatBytes(BitConverter.GetBytes((short)(2 + packetBuffer.Length)), packetBuffer); } byte[] IV = BytesUtil.ReadBytes(packetBuffer, 8, 8); using (DESCryptoServiceProvider desProvider = new DESCryptoServiceProvider()) { desProvider.Mode = CipherMode.CBC; desProvider.Padding = PaddingMode.None; using (ICryptoTransform decryptor = desProvider.CreateDecryptor(key, IV)) { byte[] rawData = decryptor.TransformFinalBlock(packetBuffer, 16, packetBuffer.Length - CryptoConstants.GC_HMAC_SIZE - 16); return(rawData); //return BytesUtil.ReadBytes(rawData, 0, (rawData.Length - (rawData[rawData.Length - 1] + 2))); } } }
/*public void LoadSkilltree(ClientSession cs) * { * DataSet ds3 = new DataSet(); * Database.Query(ref ds3, "SELECT * FROM `skilltree` WHERE `LoginUI` = '{0}'", cs.LoginUID); * Array.Resize(ref skillinfo, ds3.Tables[0].Rows.Count); * for (int i = 0; i < skillinfo.Length; i++) * { * skillinfo[i].charindex =Convert.ToByte(ds3.Tables[0].Rows[i]["charindex"].ToString()); * LogFactory.GetLog("SKILL").LogInfo("CHARID: " + skillinfo[i].charindex); * skillinfo[i].ui1 = Convert.ToByte(ds3.Tables[0].Rows[i]["ui1"].ToString()); * LogFactory.GetLog("SKILL").LogInfo("CHARID: " + skillinfo[i].ui1); * skillinfo[i].ui2 = Convert.ToInt32(ds3.Tables[0].Rows[i]["ui2"].ToString()); * LogFactory.GetLog("SKILL").LogInfo("CHARID: " + skillinfo[i].ui2); * } * }*/ public void OnSetSkill(ClientSession cs, InPacket ip) { int unknown1 = ip.ReadInt(); int LoginUID = ip.ReadInt(); int UnknownCharNum = ip.ReadInt(); /* * for(int i = 0; i < UnknownCharNum; i++) * { * int c = ip.ReadByte(); * byte u1= ip.ReadByte(); // ??? * int u2 = ip.ReadInt(); // ??? * * LogFactory.GetLog("MAIN").LogInfo(" {0} / {1} / {2}", c, u1, u2); * } */ int CharNum = ip.ReadInt(); for (int i = 0; i < CharNum; i++) { int CharType = ip.ReadByte(); ip.ReadByte(); // ? ip.ReadInt(); // ? 00 00 00 02 ip.ReadInt(); // ? 00 00 00 00 int SkillCount = ip.ReadInt(); LogFactory.GetLog("MAIN").LogInfo(" CHARID :{0} / SKILLID: {1}", CharType, SkillCount); int CharPos = findCharIndex(CharType); if (CharPos != -1) { Array.Resize(ref MyChar[CharPos].EquipSkill, SkillCount); for (int j = 0; j < SkillCount; j++) { ip.ReadInt(); // ? 00 00 00 00 int SkillGruop = ip.ReadInt(); int SkillID = ip.ReadInt(); MyChar[CharPos].EquipSkill[j].SkillGroup = SkillGruop; MyChar[CharPos].EquipSkill[j].SkillID = SkillID; } } ip.ReadInt(); // 00 00 00 01 ip.ReadInt(); // 00 00 00 00 } using (OutPacket oPacket = new OutPacket(GameOpcodes.EVENT_SET_SKILL_BROAD)) { oPacket.WriteInt(0); byte[] data = ip.ToArray(); data = BytesUtil.ReadBytes(data, 4, data.Length - 4); oPacket.WriteBytes(data); /* * oPacket.WriteInt(0); * oPacket.WriteInt(cs.LoginUID); * oPacket.WriteHexString("00 00 00 0B 00 00 00 00 00 00 01 00 00 00 00 00 02 00 00 00 00 00 05 00 00 00 00 00 0A FF 00 00 00 00 0A 00 00 00 00 00 0D 00 00 00 00 00 0E 00 00 00 00 00 0F 00 00 00 00 00 11 00 00 00 00 00 12 00 00 00 00 00"); * oPacket.WriteInt(MyChar.Length); * for (int i = 0; i < MyChar.Length; i++) * { * oPacket.WriteByte((byte)MyChar[i].CharType); * oPacket.WriteByte(0); * oPacket.WriteInt(2); * oPacket.WriteInt(0); * * oPacket.WriteInt(MyChar[i].skillinfo.Length); * for (int j = 0; j < MyChar[i].skillinfo.Length; j++) * { * oPacket.WriteInt(0); * oPacket.WriteInt(MyChar[i].skillinfo[j].SkillGroup); * oPacket.WriteInt(MyChar[i].skillinfo[j].SkilliD); * } * * oPacket.WriteInt(1); * oPacket.WriteInt(0); * } * /* * oPacket.WriteInt(0); // ?? * oPacket.WriteInt(LoginUID); * * oPacket.WriteInt(MyChar.Length); * for (int i = 0; i < MyChar.Length; i++) * { * oPacket.WriteByte((byte)i); // 캐릭터 번호 * oPacket.WriteByte(0); // ??? * oPacket.WriteInt(); // ??? * } * * oPacket.WriteInt(MyChar.Length); * for (int i = 0; i < MyChar.Length; i++) * { * oPacket.WriteByte((byte)MyChar[i].CharType); * oPacket.WriteByte(0); * oPacket.WriteInt(2); * oPacket.WriteInt(0); * * oPacket.WriteInt(MyChar[i].EquipSkill.Length); * for (int j = 0; j < MyChar[i].EquipSkill.Length; j++) * { * oPacket.WriteInt(0); * oPacket.WriteInt(MyChar[i].EquipSkill[j].SkillGroup); * oPacket.WriteInt(MyChar[i].EquipSkill[j].SkillID); * } * * oPacket.WriteInt(1); * oPacket.WriteInt(0); * } */ oPacket.CompressAndAssemble(cs.CRYPT_KEY, cs.CRYPT_HMAC, cs.CRYPT_PREFIX, cs.CRYPT_COUNT); cs.Send(oPacket); } }
/// <summary> /// Returns the uncompressed packet from the input data /// </summary> /// <param name="packetToUncompress">Packet data to be uncompressed</param> /// <returns></returns> public static byte[] UncompressPacket(byte[] packetToUncompress) { return(BytesUtil.ConcatBytes( BytesUtil.ReadBytes(packetToUncompress, 0, 11), ZlibStream.UncompressBuffer(BytesUtil.ReadBytes(packetToUncompress, 11, (packetToUncompress.Length - 11))))); }
public void OnSetSkill(ClientSession cs, InPacket ip) { //Log.Hex("패킷", ip.ToArray()); int unknown1 = ip.ReadInt(); int LoginUID = ip.ReadInt(); int UnknownCharNum = ip.ReadInt(); for (int i = 0; i < UnknownCharNum; i++) { int c = ip.ReadByte(); // 캐릭터 번호 byte u1 = ip.ReadByte(); // ??? int u2 = ip.ReadInt(); // ??? LogFactory.GetLog("Main").LogInfo(" {0} / {1} / {2}", c, u1, u2); } int CharNum = ip.ReadInt(); for (int i = 0; i < CharNum; i++) { int CharType = ip.ReadByte(); // 캐릭터 번호 ip.ReadByte(); // ? ip.ReadInt(); // ? 00 00 00 02 ip.ReadInt(); // ? 00 00 00 00 int SkillCount = ip.ReadInt(); LogFactory.GetLog("Main").LogInfo("Caracteres {0} / {1} habilidades do número", CharType, SkillCount); int CharPos = findCharIndex(CharType); // 캐릭터가 있는 배열 위치 // 캐릭터가 있으면 동작 if (CharPos != -1) { Array.Resize(ref MyChar[CharPos].EquipSkill, SkillCount); // 스킬 개수만큼 배열에 담는다 for (int j = 0; j < SkillCount; j++) { ip.ReadInt(); // ? 00 00 00 00 int SkillGruop = ip.ReadInt(); // 아마도 스킬 그룹일 가능성 높음. int SkillID = ip.ReadInt(); MyChar[CharPos].EquipSkill[j].SkillGroup = SkillGruop; MyChar[CharPos].EquipSkill[j].SkillID = SkillID; } } ip.ReadInt(); // 00 00 00 01 ip.ReadInt(); // 00 00 00 00 } // 패킷은 똑같이 보내면 된다. using (OutPacket oPacket = new OutPacket(GameOpcodes.EVENT_SET_SKILL_BROAD)) { oPacket.WriteInt(0); byte[] data = ip.ToArray(); data = BytesUtil.ReadBytes(data, 4, data.Length - 4); oPacket.WriteBytes(data); /* * oPacket.WriteInt(0); // ?? * oPacket.WriteInt(LoginUID); * * oPacket.WriteInt(MyChar.Length); * for (int i = 0; i < MyChar.Length; i++) * { * oPacket.WriteByte((byte)i); // 캐릭터 번호 * oPacket.WriteByte(0); // ??? * oPacket.WriteInt(); // ??? * } * * oPacket.WriteInt(MyChar.Length); * for (int i = 0; i < MyChar.Length; i++) * { * oPacket.WriteByte((byte)MyChar[i].CharType); * oPacket.WriteByte(0); * oPacket.WriteInt(2); * oPacket.WriteInt(0); * * oPacket.WriteInt(MyChar[i].EquipSkill.Length); * for (int j = 0; j < MyChar[i].EquipSkill.Length; j++) * { * oPacket.WriteInt(0); * oPacket.WriteInt(MyChar[i].EquipSkill[j].SkillGroup); * oPacket.WriteInt(MyChar[i].EquipSkill[j].SkillID); * } * * oPacket.WriteInt(1); * oPacket.WriteInt(0); * } */ oPacket.CompressAndAssemble(cs.CRYPT_KEY, cs.CRYPT_HMAC, cs.CRYPT_PREFIX, cs.CRYPT_COUNT); cs.Send(oPacket); } }