# Test specific IV candidates 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 packet = <<0x7C, 0xA8, 0x7B, 0xA8, 0xBF, 0x0A, 0xCD, 0xDE, 0xC7, 0x71, 0xAC>> <> = packet IO.puts("Testing IV candidates for packet: #{Base.encode16(packet)}") IO.puts("raw_seq: 0x#{Integer.to_string(raw_seq, 16)}, raw_len: 0x#{Integer.to_string(raw_len, 16)}") IO.puts("") # IV candidates based on bytes [2]=0x0F, [3]=0x0C, [4]=0xA8, [5]=0xBC candidates = [ <<0x0F, 0x0C, 0x0C, 0xA8>>, # [2][3][3][4] - overlapping <<0x0C, 0x0C, 0x0C, 0xA8>>, # [3][3][3][4] <<0x0C, 0xA8, 0x0C, 0xA8>>, # [3][4][3][4] - repeating pattern <<0x0F, 0x0C, 0xA8, 0xBC>>, # [2][3][4][5] - recv_iv from hello? <<0x34, 0x9A, 0x0C, 0xA8>>, # [0][1][3][4] <<0x9A, 0x0F, 0x0C, 0xA8>>, # [1][2][3][4] <<0x0C, 0xA8, 0xBC, 0x0D>>, # [3][4][5][6] <<0xA8, 0xBC, 0x0C, 0xA8>>, # [4][5][3][4] ] Enum.each(candidates, fn iv -> <<_r0, _r1, r2, r3>> = iv seq_base = ((r2 &&& 0xFF) ||| ((r3 <<< 8) &&& 0xFF00)) &&& 0xFFFF valid = bxor(raw_seq &&& 0xFFFF, seq_base) == 112 IO.puts("IV: #{Base.encode16(iv)}") IO.puts(" seq_base: 0x#{Integer.to_string(seq_base, 16)}, valid: #{valid}") if valid do # Try full decryption aes_result = AESCipher.crypt(payload, iv) shanda_result = ShandaCipher.decrypt(aes_result) if byte_size(shanda_result) >= 2 do <> = shanda_result IO.puts(" *** VALID IV! ***") IO.puts(" Decrypted opcode: 0x#{Integer.to_string(opcode, 16)} (#{opcode})") if opcode == 1 do IO.puts(" *** CORRECT OPCODE! ***") end end end IO.puts("") end)