package crypt; import com.jds.jn.Jn; import com.jds.jn.crypt.ProtocolCrypter; import com.jds.jn.network.packets.DecryptedPacket; import com.jds.jn.network.packets.PacketType; import com.jds.jn.parser.datatree.VisualValuePart; import com.jds.jn.session.Session; /** * Author: VISTALL * Company: J Develop Station * Date: 30.10.2009 * Time: 8:09:42 */ public class AionGameCrypter implements ProtocolCrypter { private static byte[] staticKey = "nKO/WctQ0AVLbpzfBkS6NevDYT8ourG5CRlmdjyJ72aswx4EPq1UgZhFMXH?3iI9".getBytes(); private byte[] clientPacketkey; private byte[] serverPacketkey; private boolean _enabled; public byte[] decrypt(byte[] raw, PacketType dir, Session session) { if (dir == PacketType.CLIENT) { if (!_enabled) return raw; decode(raw, clientPacketkey); } else { if (!_enabled) { decodeServerOpcode(raw); searchKey(session, raw, dir); _enabled = true; } else { decode(raw, serverPacketkey); decodeServerOpcode(raw); } } return raw; } @Override public byte[] encrypt(byte[] raw, PacketType dir, Session session) { return null; } private boolean searchKey(Session session, byte[] raw, PacketType dir) { DecryptedPacket packet = new DecryptedPacket(null, dir, raw, System.currentTimeMillis(), session.getProtocol() , false); if (dir == PacketType.SERVER && packet.getPacketInfo() != null && packet.getPacketInfo().isKey()) { int key; VisualValuePart part = (VisualValuePart) packet.getRootNode().getPartByName("key"); if (part == null) { Jn.getForm().warn("Check your protocol there is no part called 'key' which is required in key packet of the GS protocol."); return false; } key = part.getValueAsInt(); key = (key - 0x3FF2CC87) ^ 0xCD92E451; clientPacketkey = new byte[8]; clientPacketkey[0] = (byte) (key & 0xff); clientPacketkey[1] = (byte) ((key >> 8) & 0xff); clientPacketkey[2] = (byte) ((key >> 16) & 0xff); clientPacketkey[3] = (byte) ((key >> 24) & 0xff); clientPacketkey[4] = (byte) 0xa1; clientPacketkey[5] = (byte) 0x6c; clientPacketkey[6] = (byte) 0x54; clientPacketkey[7] = (byte) 0x87; serverPacketkey = new byte[8]; System.arraycopy(clientPacketkey, 0, serverPacketkey, 0, 8); return true; } Jn.getForm().warn("No key found..."); return false; } public void decode(byte[] raw, byte[] key) { int prev = raw[0]; /** Decode first byte */ raw[0] ^= (key[0] & 0xff); for (int i = 1; i < raw.length; i++) { int curr = raw[i] & 0xff; raw[i] = (byte) (curr ^ (staticKey[i & 63] & 0xff) ^ (key[i & 7] & 0xff) ^ prev); prev = curr; } long old = (((long) key[0] & 0xff) << 0) | (((long) key[1] & 0xff) << 8) | (((long) key[2] & 0xff) << 16) | (((long) key[3] & 0xff) << 24) | (((long) key[4] & 0xff) << 32) | (((long) key[5] & 0xff) << 40) | (((long) key[6] & 0xff) << 48) | (((long) key[7] & 0xff) << 56); old += raw.length; key[0] = (byte) (old >> 0 & 0xff); key[1] = (byte) (old >> 8 & 0xff); key[2] = (byte) (old >> 16 & 0xff); key[3] = (byte) (old >> 24 & 0xff); key[4] = (byte) (old >> 32 & 0xff); key[5] = (byte) (old >> 40 & 0xff); key[6] = (byte) (old >> 48 & 0xff); key[7] = (byte) (old >> 56 & 0xff); } private boolean validatePacket(byte[] raw, byte code) { return raw[0] == ~raw[2] && raw[1] == code; } public void decodeServerOpcode(byte[] raw) { raw[0] = (byte) ((raw[0] ^ 0xFFFFFFFF) + 68); } }