opcodes not changed since 12539. but I stuck on the world loading screen.
opcodes not changed since 12539. but I stuck on the world loading screen.
Looks like the redirection system from bnet is now also used for game servers. When connected you now do.
Connect to bnet, auth
Connect to grunt, get realmlist,
Connect to realm
Disconnect from grunt
That brings you to char list.
Entering world then makes a new connection to the game server.
Switching servers (for example to instances) now creates a new game server connection and disconnects the old one (theres some challenge and proof that happens with this)
Uh.. Grunt is not even used in 3.3.5a. Why would they use it in 4.x?Connect to grunt, get realmlist,
nothing to do with a new connection I think. it's any other thing but don't know which
Sorry Zor is right, the connection that connects and disconnects is realm connection (auth session, char enum, etc), no idea wtf the other one is, maybe used for redirection.
To clarify: Since around 3.2.x or so (I forgot, to be honest), all authentication goes through Battle.net which uses auth modules to do the actual authentication. I'm not sure either why Andy's getting a connection on the old Grunt port, but I highly doubt that it's actually being used.
See this blog post for a 3.3.5a-compatible description of the redirection going on since 3.3.x: WoW 3.3.3a: New Battle.net Redirection « Zor's Blog - Note that it, apparently, behaves differently in 4.x, though.
but connect works fine only stuck on the end of the world loading screen
12479 world login work
126xx world login work not
Zor: the reason I'm thinking it's grunt is because some of the servers are on 3724 now. They also appear on 4000 and 6112.
And yeh some structures of the redirections have changed. They look the same though.
Maybe I should shout at hiperzone to make a post here on what's changed so far, but he's still busy trying to figure out which sockets handle which packets now.
Who knows, it's Blizzard... ****-ups and laziness are both common. Maybe they were just too lazy to reconfigure ports...Zor: the reason I'm thinking it's grunt is because some of the servers are on 3724 now. They also appear on 4000 and 6112.
Do you have a packet dump from that connection? I can quickly tell if it's Battle.net traffic or not.
Hook WinSock functions and you're golden (socket, connect, recv, send, ...).Maybe I should shout at hiperzone to make a post here on what's changed so far, but he's still busy trying to figure out which sockets handle which packets now.
Last edited by XTZGZoReX; 08-13-2010 at 07:01 PM.
No I mean which sockets handle which packets because of the redirection stuff, not because of bnet.
Example:
{SERVER} Packet: (0x998C) SMSG_LFG_UPDATE_PLAYER PacketSize = 2 Socket ID 9292
{SERVER} Packet: (0x924C) SMSG_AURA_UPDATE PacketSize = 10 Socket ID 10284
Last edited by andy012345; 08-13-2010 at 07:33 PM. Reason: Probly shouldn't post that link it gives away some of hiperzones beta chars.
For Client 12759 you can find the address of the function that handles a certain opcode like that:
Code:public static uint CalcOff(uint opcode) { uint a = (opcode >> 1) & 0x7000; uint b = opcode & 0x800; a |= b; a >>= 1; b = opcode & 0x3C0; a |= b; a >>= 1; b = opcode & 0x10; a |= b; a >>= 1; b = opcode & 0x06; a |= b; a >>= 1; uint off = a * 4 + 0x538; return off; } uint offset = CalcOff(myOpcode); IntPtr funcAddr = Read<IntPtr>(0xCF55B4 + offset);
That code prints whole SMSG opcode handlers table as:
condensedId - handlerOffset - UnkOffset
Some opcodes still missing in this table as they have special handling...
You can convert opcodeId to it's condensedId using this code:
You have to be in world to dump opcode handlers table (client initializes it only after you enter world).Code:uint condensedId = (opcode & 6 | ((opcode & 0x10 | ((opcode & 0x3C0 | ((opcode & 0x800 | (opcode >> 1) & 0x7000) >> 1)) >> 1)) >> 1)) >> 1;
Handlers (build 12759) before world login:Code:[StructLayout(LayoutKind.Sequential)] struct ClientConnection { public int vTable; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] public byte[] unk1; // some crap, may be account name public int unk2; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] public byte[] SessionKey; // session key or pointer to session key... public int unk3; public int State; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2048)] public int[] Handlers; // stores handler pointer [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2048)] public int[] HandlersState; // stores some pointer } using (var pm = new ProcessMemory(GetProcess("Wow"))) { // offset for 4.0.0.12759 var conn = pm.Read<ClientConnection>(pm.Read<uint>(0x00CF55B4)); for (var i = 0; i < conn.Handlers.Length; ++i) { if (conn.Handlers[i] != 0 || conn.HandlersState[i] != 0) Console.WriteLine("{0:X4} - {1:X8} - {2:X8}", i, conn.Handlers[i], conn.HandlersState[i]); } }
http://paste2.org/p/951555
after entering world:
http://paste2.org/p/951556
Last edited by TOM_RUS; 08-15-2010 at 02:06 PM.
alright i will contribute with my research so far.
this is what the server does after connecting the the character list server.
It will create 2 connections, one for the realm server aka for example "Grim Batol" server
and second one will be created once entering world to handle most of world opcodes.
Packets are split between the realm and world servers, i cant tell wich ones atm but a quick IDA search leads to over 20 or so opcodes wich are handled in a special switch.
this is the actual struct of the redirection protocol but im stuck atm after proof.
SMSG_REDIRECT_CLIENT
uint8 connection index //-> connection 1 -> 0x00, connection 2: 0x01
uint32 token // -> 0x0B is used on all the logs i got
uint32 Ip;
HMACSHA1 digest[20];
uint16 port;
theres the digest calculation:
HMACSHA1 sha(40, K.AsByteArray());
sha.UpdateData((uint8 *)&token, 4);
sha.UpdateData((uint8 *)&Ip, 4);
sha.UpdateData((uint8 *)&_acct->redirectionindex, 1);
sha.UpdateData((uint8 *)&port, 2);
sha.Finalize();
after this opcode CHALLENGE is requested and client replies with CMSG_REDIRECTION_AUTH_PROOF
CMSG_REDIRECTION_AUTH_PROOF
uint64 unk;
SHA1 DIGEST[20];
string account;
digest then can be verified with:
Sha1Hash sha;
sha.Initialize();
sha.UpdateData(accountt);
sha.UpdateData(K.AsByteArray(),40);
sha.UpdateData((uint8*)&_seed,4);
sha.Finalize();
if (memcmp(sha.GetDigest(), digest, 20)) { failed }
now the problematic part where im stuck.
on the first connection.
server sends SMSG_UNKOP_1295 with uint32 0x0F from the character list connection;
wich then client replies with another opcode with the same value. opcode 0x8A20
if i send it like that, client stops accepting any packets i send and will disconnect the main connection once my sandbox sends a pong after a few seconds of wait.
NOTE: the new connection is still kept alive but its useless since the client dced and didnt do the switch propely.
once 0x8A20 is sent. SERVER will send SMSG_FORCE_SEND_QUEUED_PACKETS on the new connection made.
END
once you enter world a second connection is made
wich will CHALLENGE AND PROOF like the first one but except now server will only send
SMSG_FORCE_SEND_QUEUED_PACKETS.
everything from here should now work as intended.
NOTE: CHALLENGE uint8 var seems to alternate between 1 and 6, 1 on the first connection and 6 on the second one.
prolly tom can research this better and find where the problem is, i cant seem to find the reason why it isnt working, i simulate the packet order etc fine.
It might be a crypt issue, i tried many things but no luck, and i dont have any means atm to check if the packet is really received from the client since the logger doesnt log anything.
thats all i can help.
ports used for both connections are 6112.
atm i cant provide a log with the nwest version since i need to fix some stuff but i got a semi decent log from the previous build if you want, its only missing cmsg opcodes after login.
GL
---------- Post added at 01:49 PM ---------- Previous post was at 01:35 PM ----------
heres a decent log Paste2: Next Generation Pastebin - Viewing Paste 951540
Its very interesting, now I have a question did you pull this code out of IDA pro? Or did you do a decompile of it? I am just curious because I have been wondering how exactly you managed to get the exact parameters the function took.
i used packet logs and old research data with the help of IDA also to fill up the missing stuff.
thx goes to zor and tom for adding/commenting the 3.3.5 stuff.