# Debug script to trace crypto operations with CORRECT IV # Run with: cd /home/ra/odinsea-elixir && elixir test/debug_crypto2.exs Code.require_file("lib/odinsea/util/bit_tools.ex", ".") Code.require_file("lib/odinsea/net/cipher/ig_cipher.ex", ".") Code.require_file("lib/odinsea/net/cipher/aes_cipher.ex", ".") Code.require_file("lib/odinsea/net/cipher/shanda_cipher.ex", ".") alias Odinsea.Net.Cipher.{IGCipher, AESCipher, ShandaCipher} import Bitwise IO.puts("=== Debugging Crypto (Corrected IV) ===\n") # From the hello packet sent by server: # [Data] 0E 00 70 00 01 00 34 9A 0F 0C A8 BC 0D B3 E6 07 # Server sends: recv_iv=34 9A 0F 0C, send_iv=A8 BC 0D B3 # # Client SWAPS these: # Client's send_iv = server's recv_iv = 34 9A 0F 0C # Client's recv_iv = server's send_iv = A8 BC 0D B3 # # Client encrypts with its send_iv (34 9A 0F 0C) # Server must decrypt with its recv_iv = 34 9A 0F 0C server_send_iv = <<0xA8, 0xBC, 0x0D, 0xB3>> # Server sends this, client uses as recv server_recv_iv = <<0x34, 0x9A, 0x0F, 0x0C>> # Server sends this, client uses as send IO.puts("Server perspective:") IO.puts(" server_send_iv: #{Base.encode16(server_send_iv)}") IO.puts(" server_recv_iv: #{Base.encode16(server_recv_iv)}") IO.puts("\nClient perspective (after swapping):") IO.puts(" client_send_iv = server_recv_iv: #{Base.encode16(server_recv_iv)}") IO.puts(" client_recv_iv = server_send_iv: #{Base.encode16(server_send_iv)}") # First encrypted packet from client: # [Data] 7C A8 7B A8 BF 0A CD DE C7 71 AC packet = <<0x7C, 0xA8, 0x7B, 0xA8, 0xBF, 0x0A, 0xCD, 0xDE, 0xC7, 0x71, 0xAC>> IO.puts("\nRaw packet: #{Base.encode16(packet)}") # Server decrypts with server_recv_iv recv_iv = server_recv_iv IO.puts("Server decrypts with recv_iv: #{Base.encode16(recv_iv)}") # Extract header <> = packet IO.puts("\nHeader:") IO.puts(" raw_seq: 0x#{Integer.to_string(raw_seq, 16)} (#{raw_seq})") IO.puts(" raw_len: 0x#{Integer.to_string(raw_len, 16)} (#{raw_len})") IO.puts(" payload: #{Base.encode16(payload)} (#{byte_size(payload)} bytes)") # Validate header <<_r0, _r1, r2, r3>> = recv_iv enc_version = 112 seq_base = ((r2 &&& 0xFF) ||| ((r3 <<< 8) &&& 0xFF00)) &&& 0xffff calculated_version = bxor(raw_seq &&& 0xFFFF, seq_base) IO.puts("\nHeader validation:") IO.puts(" r2: 0x#{Integer.to_string(r2, 16)} (#{r2})") IO.puts(" r3: 0x#{Integer.to_string(r3, 16)} (#{r3})") IO.puts(" seq_base: 0x#{Integer.to_string(seq_base, 16)} (#{seq_base})") IO.puts(" raw_seq ^ seq_base: #{calculated_version}") IO.puts(" expected_version: #{enc_version}") IO.puts(" valid: #{calculated_version == enc_version}") # Get packet length packet_len = bxor(raw_seq, raw_len) &&& 0xFFFF IO.puts("\nPacket length: #{packet_len}") # Decrypt with AES IO.puts("\n=== AES Decryption ===") IO.puts("Input: #{Base.encode16(payload)}") aes_decrypted = AESCipher.crypt(payload, recv_iv) IO.puts("After AES: #{Base.encode16(aes_decrypted)}") # Decrypt with Shanda IO.puts("\n=== Shanda Decryption ===") shanda_decrypted = ShandaCipher.decrypt(aes_decrypted) IO.puts("After Shanda: #{Base.encode16(shanda_decrypted)}") # Expected opcode 0x01 = 1 if byte_size(shanda_decrypted) >= 2 do <> = shanda_decrypted IO.puts("\n=== Result ===") IO.puts("Opcode: 0x#{Integer.to_string(opcode, 16)} (#{opcode})") IO.puts("Rest: #{Base.encode16(rest)}") if opcode == 1 do IO.puts("\n✓ SUCCESS! This is CP_PermissionRequest (0x01)") else IO.puts("\n✗ FAILED! Expected opcode 0x01, got 0x#{Integer.to_string(opcode, 16)}") end end # Update IV new_recv_iv = IGCipher.inno_hash(recv_iv) IO.puts("\nUpdated recv_iv: #{Base.encode16(new_recv_iv)}") IO.puts("\n=== Done ===")