def decrypt(self, crypto): key = '' length = len(self.data) - 3 rand_16 = uint16((self.data[length + 2] << 8 | self.data[length]) ^ 0x6474) rand_8 = uint8(self.data[length + 1] ^ 0x24) if self.encrypt_method == EncryptMethod.Normal: key = crypto.key elif self.encrypt_method == EncryptMethod.MD5Key: key = crypto.generate_key(rand_16, rand_8) else: return for i in range(0, length): salt_index = (i / len(crypto.key)) % 256 self.data[i] ^= uint8(crypto.salt[salt_index] ^ ord(key[i % len(key)])) if salt_index != self.ordinal: self.data[i] ^= crypto.salt[self.ordinal] self.data = self.data[:length]
def log_in(self): print("Logging in as {0}... ".format(self.username)) key_1 = random.randint(0, 0xFF) key_2 = random.randint(0, 0xFF) client_id = random.randint(0, 0xFFFFFFFF) client_id_key = uint8(key_2 + 138) client_id_array = [ client_id & 0x0FF, (client_id >> 8) & 0x0FF, (client_id >> 16) & 0x0FF, (client_id >> 24) & 0x0FF ] hash = NexonCRC16.calculate(client_id_array, 0, 4) client_id_checksum = uint16(hash) client_id_checksum_key = uint8(key_2 + 0x5E) client_id_checksum ^= uint16(client_id_checksum_key | ((client_id_checksum_key + 1) << 8)) client_id ^= uint32(client_id_key | ((client_id_key + 1) << 8) | ((client_id_key + 2) << 16) | ((client_id_key + 3) << 24)) random_val = random.randint(0, 0xFFFF) random_val_key = uint8(key_2 + 115) random_val ^= uint32(random_val_key | ((random_val_key + 1) << 8) | ((random_val_key + 2) << 16) | ((random_val_key + 3) << 24)) x03 = ClientPacket(0x03) x03.write_string8(self.username) x03.write_string8(self.password) x03.write_byte(key_1) x03.write_byte(uint8(key_2 ^ (key_1 + 59))) x03.write_uint32(client_id) x03.write_uint16(client_id_checksum) x03.write_uint32(random_val) crc = NexonCRC16.calculate(x03.data, len(self.username) + len(self.password) + 2, 12) crc_key = uint8(key_2 + 165) crc ^= uint16(crc_key | (crc_key + 1) << 8) x03.write_uint16(crc) x03.write_uint16(0x0100) self.send(x03)
def log_in(self): print("Logging in as {0}... ".format(self.username)) key_1 = random.randint(0, 0xFF) key_2 = random.randint(0, 0xFF) client_id = random.randint(0, 0xFFFFFFFF) client_id_key = uint8(key_2 + 138) client_id_array = [ client_id & 0x0FF, (client_id >> 8) & 0x0FF, (client_id >> 16) & 0x0FF, (client_id >> 24) & 0x0FF] hash = NexonCRC16.calculate(client_id_array, 0, 4) client_id_checksum = uint16(hash) client_id_checksum_key = uint8(key_2 + 0x5E) client_id_checksum ^= uint16(client_id_checksum_key | ((client_id_checksum_key + 1) << 8)) client_id ^= uint32(client_id_key | ((client_id_key + 1) << 8) | ((client_id_key + 2) << 16) | ((client_id_key + 3) << 24)) random_val = random.randint(0, 0xFFFF) random_val_key = uint8(key_2 + 115) random_val ^= uint32(random_val_key | ((random_val_key + 1) << 8) | ((random_val_key + 2) << 16) | ((random_val_key + 3) << 24)) x03 = ClientPacket(0x03) x03.write_string8(self.username) x03.write_string8(self.password) x03.write_byte(key_1) x03.write_byte(uint8(key_2 ^ (key_1 + 59))) x03.write_uint32(client_id) x03.write_uint16(client_id_checksum) x03.write_uint32(random_val) crc = NexonCRC16.calculate(x03.data, len(self.username) + len(self.password) + 2, 12) crc_key = uint8(key_2 + 165) crc ^= uint16(crc_key | (crc_key + 1) << 8) x03.write_uint16(crc) x03.write_uint16(0x0100) self.send(x03)
def encrypt(self, crypto): if self.opcode == 0x39 or self.opcode == 0x3A: self.encrypt_dialog() key = '' self.position = len(self.data) rand_16 = random.randrange(65277) + 256 rand_8 = random.randrange(155) + 100 if self.encrypt_method == EncryptMethod.Normal: self.write_byte(0) key = crypto.key elif self.encrypt_method == EncryptMethod.MD5Key: self.write_byte(0) self.write_byte(self.opcode) key = crypto.generate_key(rand_16, rand_8) else: return for i in range(0, len(self.data)): salt_index = (i / len(crypto.key)) % 256 self.data[i] ^= uint8(crypto.salt[salt_index] ^ ord(key[i % len(key)])) if salt_index != self.ordinal: self.data[i] ^= crypto.salt[self.ordinal] bytes_to_hash = [self.opcode, self.ordinal] bytes_to_hash += self.data data_hash = hashlib.md5(bytearray(bytes_to_hash)).digest() self.write_byte(ord(data_hash[13])) self.write_byte(ord(data_hash[3])) self.write_byte(ord(data_hash[11])) self.write_byte(ord(data_hash[7])) self.write_byte(uint8(rand_16 % 256 ^ 0x70)) self.write_byte(uint8(rand_8 ^ 0x23)) self.write_byte(uint8((rand_16 >> 8) % 256 ^ 0x74))
def send(self, packet): if packet.should_encrypt: packet.ordinal = self.client_ordinal self.client_ordinal = uint8(self.client_ordinal + 1) packet.encrypt(self.crypto) try: self.socket.send(packet.to_bytearray()) if self.show_outgoing: print("Sent: {0}".format(packet.to_string())) except socket.error as error: print(error)
def write_byte(self, value): self.data.append(uint8(value))