/// <summary> /// Advances the HashTable to new values without creating a complete packetCRC /// DO NOT call this for an outgoing packet if you have already called "CreatePacketCRC" /// You would advance hashtable twice. /// This simply is a low cost variant for sniffed packets and advancing a mirrored/selfcreated hashtable in background. /// </summary> public void AdvanceHashTable() { // Construct/iterate to new HashMap (see disassembly for formula) LastHashTable = CurrentHashTable; CurrentHashTable.HASH1 = ((CurrentHashTable.HASH1 * CONST1) + CONST2) % CONST3; CurrentHashTable.HASH2 = ((CurrentHashTable.HASH2 * CONST1) + CONST2) % CONST3; CurrentHashTable.HASH3 = ((CurrentHashTable.HASH3 * CONST1) + CONST2) % CONST3; CurrentHashTable.HASH4 = ((CurrentHashTable.HASH4 * CONST1) + CONST2) % CONST3; CurrentHashTable.HASH5 = ((CurrentHashTable.HASH5 * CONST1) + CONST2) % CONST3; }
/// <summary> /// Sets (and returns) a valid CRC on a GameMessage (and advances the hash if not in testmode). /// </summary> /// <param name="Message">Message to set CRC in header</param> /// <param name="BodyCRC">The plain CRC32</param> /// <param name="TestMode">If set to false, hash is not iterated</param> /// <returns>Shortened and encoded CRC also set on Message</returns> public ushort CreatePacketCRC(GameMessage Message, out ushort BodyCRC, bool TestMode = false) { // create a generic CRC32 of message body uint crc32 = Crc32.Compute(Message.BodyBytes); // use first 2 bytes only BodyCRC = (ushort)crc32; // iterate hash HashTable newHashTable = new HashTable(); newHashTable.HASH1 = ((CurrentHashTable.HASH1 * CONST1) + CONST2) % CONST3; newHashTable.HASH2 = ((CurrentHashTable.HASH2 * CONST1) + CONST2) % CONST3; newHashTable.HASH3 = ((CurrentHashTable.HASH3 * CONST1) + CONST2) % CONST3; newHashTable.HASH4 = ((CurrentHashTable.HASH4 * CONST1) + CONST2) % CONST3; newHashTable.HASH5 = ((CurrentHashTable.HASH5 * CONST1) + CONST2) % CONST3; uint ptr = newHashTable.HASH5 & 3; // select the right part to use uint HashToUse = 0; if (ptr == 0) HashToUse = newHashTable.HASH1; else if (ptr == 1) HashToUse = newHashTable.HASH2; else if (ptr == 2) HashToUse = newHashTable.HASH3; else if (ptr == 3) HashToUse = newHashTable.HASH4; else if (ptr == 4) HashToUse = newHashTable.HASH5; // do encryption of plain CRC32 ushort shiftedPI = (ushort)((sbyte)Message.PI << 4); uint packetCRC = HashToUse ^ shiftedPI ^ Message.BodyLength ^ BodyCRC; // set encoded and shortened CRC on message Message.HeaderCRC = (ushort)packetCRC; // write back new Hashtable if not testMode if (!TestMode) { LastHashTable = CurrentHashTable; CurrentHashTable = newHashTable; } return Message.HeaderCRC; }
public GetChoiceMessage(HashTable HashTable) : base(MessageTypeLoginMode.GetChoice) { this.HashTable = HashTable; }