nitrogrlie
Members-
Posts
7 -
Joined
-
Last visited
Never -
Donations
0.00 GBP
nitrogrlie's Achievements
Newbie (1/3)
0
Reputation
-
<div class='quotetop'>QUOTE (Exoskeleton @ Aug 21 2008, 06:51 PM) <{POST_SNAPBACK}></div> Sorry, don't have an account there and I'm trying to keep the numbers of forums & accounts I have to a minimum, otherwise I forget. Anyways, here is another update - add this to your MovementInfo structure: // spline float u_unk1; uint32 spline_flag; uint64 s_unkGUID; uint32 s_travel_time, s_inflight_time, s_tick_count, s_points_count; float splineX, splineY, splineZ, splineO; float s_tempX, s_tempY, s_tempZ; Then, you can do this in your _MovementUpdate(): // TODO: Verify this if(mi.flags & MOVEMENTFLAG_SPLINE2) { pkt >> mi.spline_flag; if (mi.spline_flag & 0x10000) pkt >> mi.splineX >> mi.splineY >> mi.splineZ; if (mi.spline_flag & 0x20000) pkt >> mi.s_unkGUID; if (mi.spline_flag & 0x40000) pkt >> mi.splineO; pkt >> mi.s_inflight_time >> mi.s_travel_time >> mi.s_tick_count >> mi.s_points_count; for (uint32 i = 0; i < mi.s_points_count; ++i) { // These are X,Y,Z points in a path pkt >> mi.s_tempX >> mi.s_tempY >> mi.s_tempZ; } // Final path point (points_count - 1) pkt >> mi.s_tempX >> mi.s_tempY >> mi.s_tempZ; logdev("MovementUpdate: MOVEMENTFLAG_SPLINE2 is set with %u points", mi.s_points_count); } Turns out that on the real server the Spline2 will happen a lot for units/players.
-
I encountered something new today while logging in to the server so I figured I would provide the info. The SMSG_AUTH_RESPONSE (just prior to when you ask for the enumeration of all your characters on a given realm) can return an errorcode of 0x1B (you expect 0x0C for success). 0x1B is indicative of a Realm Queue present. I haven't reversed all the information in the packet but it includes the # of people ahead of you in the queue. Here is what you should add to your SMSG_AUTH_RESPONSE handler to not be trouble by it. Note, MaNGOS currently does not ever send 0x1B as an error code as Realm Queues are currently not supported (AFAIK). void WorldSession::_wshandle_SMSG_AUTH_RESPONSE(WorldPacket& pkt) { PrintPacket(stderr, true, pkt, pkt.size()); uint8 errcode; pkt >> errcode; if(errcode == 0xC) { logdetail("World Authentication successful, preparing for char list request..."); WorldPacket new_pkt(CMSG_CHAR_ENUM, 0); SendWorldPacket(new_pkt); } else if (errcode == 0x1B) { uint32 unk_count = pkt.size() - 5; uint8 *unknown = new uint8[unk_count]; uint32 number; for (size_t i = 0; i < unk_count; i++) { pkt >> unknown[i]; } pkt >> number; delete unknown; logerror("World Authentication encountered: Login Queue of %d", number); Sleep( 100 ); } else { logerror("World Authentication failed, errcode=0x%02X", (uint8)errcode); SetMustDie(); } } HERE is a LOG DUMP of the PACKETS I encountered while logging in... notice that they vary between two sizes: {SERVER} Packet: (0x01ee) SMSG_AUTH_RESPONSE - Packet Size = 15 |------------------------------------------------|----------------| |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF| |------------------------------------------------|----------------| |1b 08 ad 1e ff 42 00 00 00 00 00 1b 00 00 00 |.....B......... | ------------------------------------------------------------------- {SERVER} Packet: (0x01ee) SMSG_AUTH_RESPONSE - Packet Size = 15 |------------------------------------------------|----------------| |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF| |------------------------------------------------|----------------| |1b 78 1e 1f ff 42 00 00 00 00 00 19 00 00 00 |.x...B......... | ------------------------------------------------------------------- {SERVER} Packet: (0x01ee) SMSG_AUTH_RESPONSE - Packet Size = 5 |------------------------------------------------|----------------| |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF| |------------------------------------------------|----------------| |1b 1b 00 00 00 |..... | ------------------------------------------------------------------- {SERVER} Packet: (0x01ee) SMSG_AUTH_RESPONSE - Packet Size = 15 |------------------------------------------------|----------------| |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF| |------------------------------------------------|----------------| |1b 6c 66 1f ff 42 00 00 00 00 00 19 00 00 00 |.lf..B......... | ------------------------------------------------------------------- {SERVER} Packet: (0x01ee) SMSG_AUTH_RESPONSE - Packet Size = 5 |------------------------------------------------|----------------| |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF| |------------------------------------------------|----------------| |1b 19 00 00 00 |..... | ------------------------------------------------------------------- {SERVER} Packet: (0x01ee) SMSG_AUTH_RESPONSE - Packet Size = 5 |------------------------------------------------|----------------| |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF| |------------------------------------------------|----------------| |1b 16 00 00 00 |..... | ------------------------------------------------------------------- {SERVER} Packet: (0x01ee) SMSG_AUTH_RESPONSE - Packet Size = 5 |------------------------------------------------|----------------| |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF| |------------------------------------------------|----------------| |1b 11 00 00 00 |..... | ------------------------------------------------------------------- {SERVER} Packet: (0x01ee) SMSG_AUTH_RESPONSE - Packet Size = 5 |------------------------------------------------|----------------| |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF| |------------------------------------------------|----------------| |1b 04 00 00 00 |..... | ------------------------------------------------------------------- {SERVER} Packet: (0x01ee) SMSG_AUTH_RESPONSE - Packet Size = 1 |------------------------------------------------|----------------| |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF| |------------------------------------------------|----------------| |0c |. | -------------------------------------------------------------------
-
Another thing, when interacting with proper server the CMSG_AUTH_SESSION will not work if you pass a "(uin32) 0x00" for the AddOn information list at the end of that packet, b/c it requires that the Blizzard provided Addons be listed, at the minimum. I don't think MaNGOS currently cares about this field so it works with MaNGOS just fine. For proper server you would need the following bytes at the end of the packet: uint8 addon_info[160] = { 0xd0,0x01,0x00,0x00,0x78,0x9c,0x75,0xcf, 0x3b,0x0e,0xc2,0x30,0x0c,0x80,0xe1,0x72, 0x0f,0x2e,0x43,0x18,0x50,0xa5,0x66,0xa1, 0x65,0x46,0x26,0x71,0x2b,0xab,0x89,0x53, 0x19,0x87,0x47,0x4f,0x0f,0x0b,0x62,0x71, 0xbd,0x7e,0xd6,0x6f,0xd9,0x25,0x5a,0x57, 0x90,0x78,0x3d,0xd4,0xa0,0x54,0xf8,0xd2, 0x36,0xbb,0xfc,0xdc,0x77,0xcd,0x77,0xdc, 0xcf,0x1c,0xa8,0x26,0x1c,0x09,0x53,0xf4, 0xc4,0x94,0x61,0xb1,0x96,0x88,0x23,0xf1, 0x64,0x06,0x8e,0x25,0xdf,0x40,0xbb,0x32, 0x6d,0xda,0x80,0x2f,0xb5,0x50,0x60,0x54, 0x33,0x79,0xf2,0x7d,0x95,0x07,0xbe,0x6d, 0xac,0x94,0xa2,0x03,0x9e,0x4d,0x6d,0xf9, 0xbe,0x60,0xb0,0xb3,0xad,0x62,0xee,0x4b, 0x98,0x51,0xb7,0x7e,0xf1,0x10,0xa4,0x98, 0x72,0x06,0x8a,0x26,0x0c,0x90,0x90,0xed, 0x7b,0x83,0x40,0xc4,0x7e,0xa6,0x94,0xb6, 0x98,0x18,0xc5,0x36,0xca,0xe8,0x81,0x61, 0x42,0xf9,0xeb,0x07,0x63,0xab,0x8b,0xec}; for (uint8 i = 0; i < 160; i++) { auth << addon_info[i]; }
-
<div class='quotetop'>QUOTE (ProjectEden @ Aug 1 2008, 04:32 PM) <{POST_SNAPBACK}></div> Debating this as it's not my code and I would have to see how the original author feels about this. <div class='quotetop'>QUOTE (ProjectEden @ Aug 1 2008, 04:32 PM) <{POST_SNAPBACK}></div> I fixed it the following way: void RealmSession::_HandleRealmList(ByteBuffer& pkt) { logdebug("RealmList Packet"); std::string realmAddr; uint32 unk; uint16 len,count; uint8 cmd; pkt >> cmd >> len >> unk >> count; while( pkt.size() < len ) { Sleep( 100 ); // wait for the rest of the packet _socket->OnRead(); if ( pktQueue.size() ) pkt.append( *pktQueue.next() ); } log( "%i %i", pkt.size(), len ); pkt.print(); // no realm? if(count==0) return; // do we have the wrong size? // subtract 3 bytes since len provided in packet // is from that point on so we miss the opcode (1 byte) // and the size (2 bytes) if (len != (pkt.size()-3)) { return; } ... The rest of the pseuwow code as it is here }
-
<div class='quotetop'>QUOTE (ProjectEden @ Aug 1 2008, 01:29 PM) <{POST_SNAPBACK}></div> Stuff to Add to RealmSession.cpp #include <windows.h> #include <fstream> struct sAuthLogonChallenge_S { uint8 cmd; uint8 unk2; uint8 error; uint8 B[32]; uint8 g_len; uint8 g[1]; uint8 N_len; uint8 N[32]; uint8 salt[32]; uint8 seed[16]; // <-- I modified this from unk3 uint8 unk4; // <-- I added this (version 2.4.3) }; // 2 Static funcs you will need (put them towards the top of the file) static int GenerateMemoryHash(char* fn, Sha1Hash* Sha1) { HANDLE hFile = CreateFileA(fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return 0; int len = 0; uint32 dwRead; uint32 dwLen = -1; while (dwLen != 0) { if (!ReadFile(hFile, &dwLen, 4, &dwRead, NULL)) break; if (dwRead == 0) break; if (dwLen > 0) { uint8 *mem = new uint8[dwLen]; if (!ReadFile(hFile, mem, dwLen, &dwRead, NULL)) { CloseHandle(hFile); return 0; } len += (int)dwRead; Sha1->UpdateData(mem, dwLen); delete[] mem; } } CloseHandle(hFile); return len; } static void CalcCRC(uint8* crc_hash, uint8* seed, uint8* A) { char szFileName[128] = {0}; GetModuleFileName(NULL, szFileName, 128); uint32 iPathLen = strlen(szFileName); for(iPathLen; iPathLen > 0; iPathLen--) { if (szFileName[iPathLen] == '\\\\') { szFileName[iPathLen+1] = '\\0'; strcat(szFileName, "crc.bin"); break; } } uint8 szBuf1[64]; uint8 szBuf2[64]; memset(szBuf1, 0x36, 64); memset(szBuf2, 0x5C, 64); for (uint8 i = 0; i < 16; i++) { szBuf1[i] ^= seed[i]; szBuf2[i] ^= seed[i]; } Sha1Hash Sha1; Sha1.UpdateData(szBuf1, 64); GenerateMemoryHash(szFileName, &Sha1); Sha1.Finalize(); uint8 H1[64]; memcpy(H1, Sha1.GetDigest(), Sha1.GetLength()); Sha1.Initialize(); Sha1.UpdateData(szBuf2, 64); Sha1.UpdateData(H1, 20); Sha1.Finalize(); uint8 H2[64]; memcpy(H2, Sha1.GetDigest(), Sha1.GetLength()); Sha1.Initialize(); Sha1.UpdateData(A, 32); Sha1.UpdateData(H2, 20); Sha1.Finalize(); memcpy(crc_hash, Sha1.GetDigest(), Sha1.GetLength()); } // THEN REPLACE CASE 0 WITH THIS: case 0: { pkt.read((uint8*)&lc, sizeof(sAuthLogonChallenge_S)); logdetail("Login successful, now calculating proof packet..."); // now lets start calculating BigNumber N,A,B,a,u,x,v,S,salt,seed,g,k(3); // init BNs, default k to 3 std::string user=stringToUpper( _accname ); std::string _authstr=stringToUpper( user +":"+_accpass ); B.SetBinary(lc.B,32); g.SetBinary(lc.g,lc.g_len); N.SetBinary(lc.N,lc.N_len); salt.SetBinary(lc.salt,32); seed.SetBinary(lc.seed,16); //logdebug("== Server Bignums =="); //logdebug("--> B=%s",B.AsHexStr()); //logdebug("--> g=%s",g.AsHexStr()); //logdebug("--> N=%s",N.AsHexStr()); //logdebug("--> salt=%s",salt.AsHexStr()); //logdebug("--> seed=%s",seed.AsHexStr()); //logdebug("== My Bignums =="); // Probably should use seed here instead of 19*8 a.SetRand(19*8); ASSERT(a.AsDword() > 0); logdebug("--> a=%s",a.AsHexStr()); // GetLogonHash Sha1Hash userhash,xhash,uhash; userhash.UpdateData(_authstr); userhash.Finalize(); // Getx xhash.UpdateData(salt.AsByteArray(),salt.GetNumBytes()); xhash.UpdateData(userhash.GetDigest(),userhash.GetLength()); xhash.Finalize(); x.SetBinary(xhash.GetDigest(),xhash.GetLength()); logdebug("--> x=%s",x.AsHexStr()); // GetA A=g.ModExp(a,N); logdebug("--> A=%s",A.AsHexStr()); // GetU uhash.UpdateBigNumbers(&A, &B, NULL); uhash.Finalize(); u.SetBinary(uhash.GetDigest(), uhash.GetLength()); logdebug("--> u=%s",u.AsHexStr()); // ClientGetS S=(B - k*g.ModExp(x,N) ).ModExp((a + u * x),N); logdebug("--> S=%s",S.AsHexStr()); ASSERT(S.AsDword() > 0); // WHY IS THIS CALCULATED??? IT'S NEVER USED //v=g.ModExp(x,N); //logdebug("--> v=%s",v.AsHexStr()); // Get M1 & M2 unsigned int i=0; char S1[16+1],S2[16+1]; // 32/2=16 +1 for \\0 // split it into 2 seperate strings, interleaved for(i=0;i<16;i++){ S1[i]=S.AsByteArray()[i*2]; S2[i]=S.AsByteArray()[i*2+1]; } // hash each one: Sha1Hash S1hash,S2hash; S1hash.UpdateData((const uint8*)S1,16); S1hash.Finalize(); S2hash.UpdateData((const uint8*)S2,16); S2hash.Finalize(); // Re-combine them char S_hash[40]; for(i=0;i<20;i++){ S_hash[i*2]=S1hash.GetDigest()[i]; S_hash[i*2+1]=S2hash.GetDigest()[i]; } _key.SetBinary((uint8*)S_hash,40); // used later when authing to world logdebug("--> SessionKey=%s",_key.AsHexStr()); char Ng_hash[20]; Sha1Hash userhash2,Nhash,ghash; userhash2.UpdateData((const uint8*)user.c_str(),user.length()); userhash2.Finalize(); //printchex((char*)userhash2.GetDigest(),userhash2.GetLength(),true); Nhash.UpdateBigNumbers(&N,NULL); Nhash.Finalize(); ghash.UpdateBigNumbers(&g,NULL); ghash.Finalize(); for(i=0;i<20;i++)Ng_hash[i] = Nhash.GetDigest()[i]^ghash.GetDigest()[i]; //printchex(Ng_hash,20,true); BigNumber t_acc,t_Ng_hash; t_acc.SetBinary((const uint8*)userhash2.GetDigest(),userhash2.GetLength()); t_Ng_hash.SetBinary((const uint8*)Ng_hash,20); Sha1Hash M1hash,M2hash; M1hash.UpdateBigNumbers(&t_Ng_hash,&t_acc,&salt,&A,&B,NULL); M1hash.UpdateData((const uint8*)S_hash,40); M1hash.Finalize(); M2hash.UpdateBigNumbers(&A,NULL); M2hash.UpdateData((const uint8*)M1hash.GetDigest(),M1hash.GetLength()); M2hash.UpdateData((const uint8*)S_hash,40); M2hash.Finalize(); //logdebug("== Common Hashes =="); //logdebug("--> M1=%s",toHexDump(M1hash.GetDigest(),M1hash.GetLength(),false).c_str()); //logdebug("--> M2=%s",toHexDump(M2hash.GetDigest(),M2hash.GetLength(),false).c_str()); // End of GetM1M2 // Calc CRC & CRC_hash uint8 crc_hash[20] = {0}; CalcCRC(crc_hash, lc.seed, A.AsByteArray()); //logdebug("--> CRC=%s",toHexDump((uint8*)crc_hash,20,false).c_str()); // now lets prepare the packet ByteBuffer packet; packet << (uint8)AUTH_LOGON_PROOF; packet.append(A.AsByteArray(),A.GetNumBytes()); packet.append(M1hash.GetDigest(),M1hash.GetLength()); packet.append(crc_hash,20); packet << (uint8)0; // number of keys = 0 if(GetInstance()->GetConf()->clientbuild > 5302) packet << (uint8)0; // 1.11.x compatibility (needs one more 0) GetInstance()->SetSessionKey(_key); memcpy(this->_m2,M2hash.GetDigest(),M2hash.GetLength()); // save M2 to an extern var to check it later SendRealmPacket(packet); packet.print(); } } Now to get that to compile you will also need to add the print() to ByteBuffer.h which I wrote (and ksniffer people will find familiar) which is way nicer then the hexlike or textlike (and combines both into one) void print() { uint32 line = 1; uint32 countpos = 0; printf("Packet Size: %u\\r\\n", size()); printf("|------------------------------------------------|----------------|\\r\\n"); printf("|00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |0123456789ABCDEF|\\r\\n"); printf("|------------------------------------------------|----------------|\\r\\n"); if (size() > 0) { printf("|"); for (uint32 count = 0; count < size(); count++) { if (countpos == 16) { countpos = 0; printf("|"); for (uint32 a = count-16; a < count; a++) { if ((read<uint8>(a) < 32) || (read<uint8>(a) > 126)) printf("."); else printf("%c", read<uint8>(a)); } printf("|\\r\\n"); line++; printf("|"); } printf("%02x ", read<uint8>(count)); // Fix to parse packets with length < OR = to 16 bytes. if (count+1 == size() && size() <= 16) { for (uint32 b = countpos+1; b < 16; b++) printf(" "); printf("|"); for (uint32 a = 0; a < size(); a++) { if ((read<uint8>(a) < 32) || (read<uint8>(a) > 126)) printf("."); else printf("%c", read<uint8>(a)); } for (uint32 c = count; c < 15; c++) printf(" "); printf("|\\r\\n"); } // Fix to parse the last line of the packets when the length is > 16 and its in the last line if (count+1 == size() && size() > 16) { for (uint32 b = countpos+1; b < 16; b++) printf(" "); printf("|"); uint16 print = 0; for (uint32 a = line*16 - 16; a < size(); a++) { if ((read<uint8>(a) < 32) || (read<uint8>(a) > 126)) printf("."); else printf("%c", read<uint8>(a)); print++; } for (uint32 c = print; c < 16; c++) printf(" "); printf("|\\r\\n"); } countpos++; } } printf("-------------------------------------------------------------------\\r\\n\\r\\n"); } With all that you will calculate the CRC correctly... IF you have the crc.bin file on your system (and this is something I will not provide, mainly cause it's about 11MB in size). Now, with all that and the crc.bin I can connect to a real wow server with your client. However, there is something messed up with your TcpSocket class as when I get the RealmList packet from the server it doesn't combine all the split packets (WoW servers sends them in 1460 byte increments) back. The packet I get claims a length of 8947 bytes (for 229 servers)... but when I get the packet it is only 4140 bytes and thus crashes the subsequent function. Now the re-joining of packets across TCP protocol should be invisible to the user, but clearly something is messed up. Interestingly, on another side note, if I add a sanity check to the RealmSession handling function to just return if pkt.size() != len the subsequent bytes that arrive on the RealmSocket are prepended to the front of the buffer instead of appended to the back (if you follow what I mean).
-
Well, in that case there isn't any point in posting the patch... since PseuWoW doesn't need to calculate a valid CRC hash to connect to a private server. But glad to see people are still working on this project as it is an interesting concept. As I develop my own code I will periodically compare it to PseuWoW and let you guys know if there is any changes that are needed.
-
Are people still actively working on this project? I checked it out recently and fixed some issues with it: like the CRC calculation code needed during AUTH_LOGON_PROOF packet generation, plus updated some of the RealmD packet structs so they match what is received in 2.4.3. Having said that I can actually get to the Character Selection screen on a real WoW server. With that said, that is when you start getting Warden messages & ping messages. Ping is way easier to handle then Warden
Contact Us
To contact us
click here
You can also email us at [email protected]
Privacy Policy | Terms & Conditions
You can also email us at [email protected]
Privacy Policy | Terms & Conditions
Copyright © getMaNGOS. All rights Reserved.
This website is in no way associated with or endorsed by Blizzard Entertainment®
This website is in no way associated with or endorsed by Blizzard Entertainment®