Jump to content

nitrogrlie

Members
  • Posts

    7
  • Joined

  • Last visited

    Never
  • Donations

    0.00 GBP 

Everything posted by nitrogrlie

  1. <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.
  2. 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 |. | -------------------------------------------------------------------
  3. 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]; }
  4. <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 }
  5. <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).
  6. 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.
  7. 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
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use