Author | Message | Time |
---|---|---|
z-stars | I'm trying to make a bot in C++. Using bnetdocs I've built&sent / received the first packets, but now I gotta send SID_AUTH_CHECK (0x51) and I dont know what to do. I've read that you have to encode the CDKEy and some more values, but I dont know how to do that. Can anyone post some source, or a link, or point me in the right direction plz? Thx in advance. | July 22, 2004, 6:47 PM |
Myndfyr | http://www.valhallalegends.com/yoni/BNLSProtocolSpec.txt | July 22, 2004, 7:53 PM |
z-stars | Isn't there any C++ function to make the packet 0x51 yourself or something? | July 22, 2004, 8:05 PM |
OnlyMeat | [quote author=Myndfyre link=board=17;threadid=7821;start=0#msg71910 date=1090526031] http://www.valhallalegends.com/yoni/BNLSProtocolSpec.txt [/quote] Thats assuming that he wants to use another connection layer as apposed to connecting directly, it sounds like he wants to do the hashing etc himself which would make bnls inappropriate. I suggest looking at the prolix source code it's public and the latest versions are pretty accurate, although you may need to modify the rotate functions slightly for big endian. I think you can access the cvs here :- http://prolix.sourceforge.net/ | July 22, 2004, 8:06 PM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=0#msg71916 date=1090526742] Isn't there any C++ function to make the packet 0x51 yourself or something? [/quote] You should use Battle.snp to do all your hashing, and CDKey decoding. If you're interested, let me know. Less code to write, and probably faster :) | July 22, 2004, 9:10 PM |
z-stars | Yeah I'd preffer to do the hashing myself, and what is that Battle.snp thing? | July 22, 2004, 9:35 PM |
OnlyMeat | [quote author=UserLoser. link=board=17;threadid=7821;start=0#msg71926 date=1090530620] [quote author=z-stars link=board=17;threadid=7821;start=0#msg71916 date=1090526742] Isn't there any C++ function to make the packet 0x51 yourself or something? [/quote] You should use Battle.snp to do all your hashing, and CDKey decoding. If you're interested, let me know. Less code to write, and probably faster :) [/quote] What happends if the oridinal position//function name changes in the snp? i think that would leed to linkage problems if the file is changed. I personally think thats just the same as using bnls it relies on others peoples code which can go wrong and if it does for any reason then you cant fix it yourself, my personal preference is to do the hashing myself because it keeps things clean and simple :) | July 22, 2004, 9:56 PM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=0#msg71930 date=1090532144] Yeah I'd preffer to do the hashing myself, and what is that Battle.snp thing? [/quote] Basically, you call functions in Battle.snp to do the hashing and CDKey decoding for you. Note, this is from Starcraft's 1.09 Battle.snp, since the newer one appears to have the CDKey decoding not in it's own function. Here's an example: [code] const DWORD HashFunction = 0x19012400; void HashData(DWORD length, LPVOID outbuf, LPVOID tohash) { DWORD len = length; __asm { push ecx push edx mov ecx, outbuf mov edx, tohash push len call HashFunction pop edx pop ecx } } [/code] If you wanted to create an account, it requires a 5 DWORD password hash. What you could do is: [code] char* outbuf = new char[20]; HashData(strlen(AccountName), outbuf, AccountName); <insert outbuf into packet buffer along with account name, send packet> delete [] outbuf; [/code] If you wanted to log onto your account, you would do a double hash; which includes a client key and server key (server key from 0x50): [code] DWORD dwPasswordHash[7]; dwPasswordHash[0] = GetTickCount(); dwPasswordHash[1] = ServerSessionKey; HashData(strlen(Password), dwPasswordHash+0x2, Password); HashData(28, dwPasswordHash, dwPasswordHash+0x2); [/code] Now, for CDKey decoding and hashing: [code] const DWORD DecodeCDKeyFunction = 0x19019AB0; void RunCDkeyDecode(DWORD *Product, DWORD *CDKeyVal1, DWORD *CDKeyVal2, const char *CDKey) { __asm { push ecx push edx mov ecx, CDKey mov edx, Product push CDKeyVal2 push CDKeyVal1 call DecodeCDKeyFunction pop edx pop ecx } } [/code] Use it like so: [code] DWORD *dwProduct = (DWORD*)malloc(4); DWORD *dwPrivate = (DWORD*)malloc(4); DWORD *dwPublic = (DWORD*)malloc(4); RunCDkeyDecode(&dwProduct, &dwPublic, &dwPrivate, "my sc/d2/w2 cdkey"); [/code] Hash the CDKey values like so: [code] DWORD dwHashBuffer[6]; DWORD dwOutBuffer[5]; dwHashBuffer[0] = GetTickCount(); dwHashBuffer[1] = ServerSessionKey; dwHashBuffer[2] = dwProduct; dwHashBuffer[3] = dwPublic; dwHashBuffer[4] = 0; dwHashBuffer[5] = dwPrivate; HashData(24, dwOutBuffer, dwHashBuffer); [/code] And once again, just insert dwOutBuffer into your buffer for 0x51, along with the cdkey values listed on bnetdocs, then just send it to battle.net. Hope there isn't any mistakes, I haven't done any of this in a while :) Enjoy :) | July 22, 2004, 10:09 PM |
z-stars | Erm yeah I want to do the hashing myself too, but I dont know how ^^ BTW, I have found this source, does anyone know if it works or how to use it? [code] /* Battle.net Version Check Source Code © YobGuls (yobguls@yobguls.2ndmail.com) 2001 * This is the equivalent of the CheckVersion() function that appears * in the IX86VER?.DLL files that are used as part of the Battle.net * connection procedure * Thanks a lot to Onlyer (onlyer@263.net) for explaining the basic * parts of this function to me, it made it a lot easier * Also, Skywing provided the additional checksum keys for certain DLLs */ #include <windows.h> #include <stdlib.h>#include <stdio.h> /* These are special keys that vary depending upon which DLL it is that you're using * They're used to initialize the first variable (A) as part of the checksum algorithm */ /* Thanks to Skywing for the additional checksum keys */ DWORD dwMpqChecksumKeys[] = { 0xE7F4CB62lu, 0xF6A14FFClu, 0xAA5504AFlu, 0x871FCDC2lu, 0x11BF6A18lu, 0xC57292E6lu, 0x7927D27Elu, 0x2FEC8733lu }; /* CheckRevision function * This function takes in three file names and a versioning string. The file names refer * to the main EXE and DLL files that are used by the game. Usually this includes the game's * main EXE file (like Starcraft.exe) and the Battle.net client DLL (Battle.snp for Starcraft * or Bnclient.dll for Diablo 2). In the actual DLLs, the first argument is ignored and * GetModuleFileName(NULL) is used instead. The versioning string is a list of random * variables and operations that tell how the checksum is performed. * The function will write two 32-bit DWORDs as output. The first is the version information * taken from the actual resource in the main EXE file. The second is the result of the * checksum function. */ /* NOTE: I added the MPQ file name argument, it's not in the real function of course. Set * that to the file that Battle.net specifies in the connection, like "IX86VER0.MPQ". You * don't actually have to download this file, the algorithm is all in here. */ BOOL CheckRevision(LPCTSTR lpszFileName1, LPCTSTR lpszFileName2, LPCTSTR lpszFileName3, LPCTSTR lpszValueString, DWORD * lpdwVersion, DWORD * lpdwChecksum, LPSTR lpExeInfoString, LPCTSTR lpszMpqFileName) { HANDLE hFile, hFileMapping; char * s, lpszFileName[256], cOperations[16]; int nHashFile, nVariable1[16], nVariable2[16], nVariable3[16], nVariable, i, k, nHashOperations; DWORD dwTotalSize, dwSize, j, dwBytesRead, dwVariables[4], dwMpqKey, * lpdwBuffer; LPSTR lpszFileNames[3]; FILETIME ft; SYSTEMTIME st; LPBYTE lpbBuffer; VS_FIXEDFILEINFO * ffi; s = strchr((char *) lpszMpqFileName, '.'); if (s == NULL) return FALSE; nHashFile = (int) (*(s - 1) - '0'); if (nHashFile > 7 || nHashFile < 0) return FALSE; dwMpqKey = dwMpqChecksumKeys[nHashFile]; lpszFileNames[0] = (LPSTR) lpszFileName1; lpszFileNames[1] = (LPSTR) lpszFileName2; lpszFileNames[2] = (LPSTR) lpszFileName3; s = (char *) lpszValueString; while (*s != '\0') { if (isalpha(*s)) nVariable = (int) (toupper(*s) - 'A'); else { nHashOperations = (int) (*s - '0'); s = strchr(s, ' '); if (s == NULL) return FALSE; s++; break; } if (*(++s) == '=') s++; dwVariables[nVariable] = atol(s); s = strchr(s, ' '); if (s == NULL) return FALSE; s++; } for (i = 0; i < nHashOperations; i++) { if (!isalpha(*s)) return FALSE; nVariable1[i] = (int) (toupper(*s) - 'A'); if (*(++s) == '=') s++; if (toupper(*s) == 'S') nVariable2[i] = 3; else nVariable2[i] = (int) (toupper(*s) - 'A'); cOperations[i] = *(++s); s++; if (toupper(*s) == 'S') nVariable3[i] = 3; else nVariable3[i] = (int) (toupper(*s) - 'A'); s = strchr(s, ' '); if (s == NULL) break; s++; } dwVariables[0] ^= dwMpqKey; for (i = 0; i < 3; i++) { if (lpszFileNames[i][0] == '\0') continue; hFile = CreateFile(lpszFileNames[i], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == (HANDLE) INVALID_HANDLE_VALUE) return FALSE; hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hFileMapping == NULL) { CloseHandle(hFile); return FALSE; } lpdwBuffer = (LPDWORD) MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); if (lpdwBuffer == NULL) { CloseHandle(hFileMapping); CloseHandle(hFile); return FALSE; } if (i == 0) { GetFileTime(hFile, &ft, NULL, NULL); FileTimeToSystemTime(&ft, &st); dwTotalSize = GetFileSize(hFile, NULL); } dwSize = (GetFileSize(hFile, NULL) / 1024lu) * 1024lu; for (j = 0; j < (dwSize / 4lu); j++) { dwVariables[3] = lpdwBuffer[j]; for (k = 0; k < nHashOperations; k++) { switch (cOperations[k]) { case '+': dwVariables[nVariable1[k]] = dwVariables[nVariable2[k]] + dwVariables[nVariable3[k]]; break; case '-': dwVariables[nVariable1[k]] = dwVariables[nVariable2[k]] - dwVariables[nVariable3[k]]; break; case '^': dwVariables[nVariable1[k]] = dwVariables[nVariable2[k]] ^ dwVariables[nVariable3[k]]; break; default: return FALSE; } } } UnmapViewOfFile(lpdwBuffer); CloseHandle(hFileMapping); CloseHandle(hFile); } strcpy(lpszFileName, lpszFileName1); dwSize = GetFileVersionInfoSize(lpszFileName, &dwBytesRead); lpbBuffer = (LPBYTE) VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); if (lpbBuffer == NULL) return FALSE; if (GetFileVersionInfo(lpszFileName, NULL, dwSize, lpbBuffer) == FALSE) return FALSE; if (VerQueryValue(lpbBuffer, "\\", (LPVOID *) &ffi, (PUINT) &dwSize) == FALSE) return FALSE; *lpdwVersion = ((HIWORD(ffi->dwProductVersionMS) & 0xFF) << 24) | ((LOWORD(ffi->dwProductVersionMS) & 0xFF) << 16) | ((HIWORD(ffi->dwProductVersionLS) & 0xFF) << 8) | (LOWORD(ffi->dwProductVersionLS) & 0xFF); VirtualFree(lpbBuffer, 0lu, MEM_RELEASE); s = (char *) &lpszFileName[strlen(lpszFileName)-1]; while (*s != '\\' && s > (char *) lpszFileName) s--; s++; sprintf(lpExeInfoString, "%s %02u/%02u/%02u %02u:%02u:%02u %lu", s, st.wMonth, st.wDay, st.wYear % 100, st.wHour, st.wMinute, st.wSecond, dwTotalSize); *lpdwChecksum = dwVariables[2]; return TRUE; } [/code] | July 22, 2004, 10:11 PM |
z-stars | Ops I submit my post at the same time than UserLoser. It looks well but how would I do that using d2 lod? | July 22, 2004, 10:16 PM |
OnlyMeat | ye pretty much everyone derived their code from that i think it works pretty well. if you want some working classes for hashing and version extraction in c++ pm me and we can talk. | July 22, 2004, 10:18 PM |
z-stars | How do I actually use the code posted above? I mean, in packet 0x51 each time I log to bnet with d2, it sends different Client Token, Exe Hash, and different CdKey Data Hashes. How do I get these values? | July 22, 2004, 10:29 PM |
OnlyMeat | [quote author=z-stars link=board=17;threadid=7821;start=0#msg71946 date=1090535393] How do I actually use the code posted above? I mean, in packet 0x51 each time I log to bnet with d2, it sends different Client Token, Exe Hash, and different CdKey Data Hashes. How do I get these values? [/quote] when the server sends the 0x50 packet to you it contains the session key which is basically the encryption key, this vaue is then hashed with a salt ( random value ) and your cdkeys. Note for d2 Exp you need to construct 2 hash sets one for each cdkey. This is the function i wrote in my abstract base class for all my bot clients to handle 0x50:- [code] BOOL CBot::CreateAuthPacket(AUTHCHECK_INFO *pAuthInfo, CPacket& Packet) { CNetEvent ne; ne.eEvent = EID_AUTHKEY; PumpMessage(&ne); ////////////////////////////////////////////////////////////////////////////////// // Extract session variables m_SessionKey = *(UINT *)(pAuthInfo->pszAuthData + 0x04); m_SessionNum = *(UINT *)(pAuthInfo->pszAuthData + 0x08); ////////////////////////////////////////////////////////////////////////////////// // Extract equation variables char *pszHashMpq = (pAuthInfo->pszAuthData + 0x14); char *pszHashEqu = (pAuthInfo->pszAuthData + (strlen(pszHashMpq) + 0x15)); int nMpq = *(strstr(pszHashMpq, ".") - 1) - '0'; /////////////////////////////////////////////////////////////////////////////////// // Validate hash files CVerCheck VerCheck; UINT nVersion, nChecksum; char szExeInfo[_MAX_FNAME]; if (!ValidateBinaries(pAuthInfo->lpHashFiles[0], pAuthInfo->lpHashFiles[1], pAuthInfo->lpHashFiles[2])) CGenericException::ThrowException(IDS_ERROR_BINARIES); /////////////////////////////////////////////////////////////////////////////////// // Do version check VerCheck.CheckRevision(pAuthInfo->lpHashFiles[0], pAuthInfo->lpHashFiles[1], pAuthInfo->lpHashFiles[2], pszHashEqu, (LPDWORD)&nVersion, (LPDWORD)&nChecksum, szExeInfo, pszHashMpq); CCDKey CDKey; CEncryption Encryption; char szKeyBuf[MAX_CDKEY]; UINT a, b, c; UINT hashbuf[6], hash[5]; UINT nSeed = GetRand(); // Cookie /////////////////////////////////////////////////////////////////////////////////// // Fill-in default version info Packet << nSeed // Seed << nVersion // Client Version << nChecksum // Checksum from files << pAuthInfo->nCDKeys // No. cd-keys << (UINT)0x00; // Spawn (BOOL) /////////////////////////////////////////////////////////////////////////////////// // Hash cd-key data for ( UINT i=0; i < pAuthInfo->nCDKeys; i++ ) { memset(szKeyBuf,0,MAX_CDKEY); // Reset buffer // Extract cd-key variables strcpy(szKeyBuf, pAuthInfo->lpCDKeys[i]); CDKey.GetCDVars(szKeyBuf, &a, &b, &c); UINT nKeylength = strlen(szKeyBuf); Packet << nKeylength // CD-Key length << a // Product id << b // CD-Key val 1 << (UINT)0x00; // ? // Hash cd-key data hashbuf[0] = nSeed; // Seed hashbuf[1] = m_SessionKey; // Session key hashbuf[2] = a; hashbuf[3] = b; hashbuf[4] = 0; hashbuf[5] = c; // Use correct hash rotation Encryption.Sha1_HashB( (char *)hashbuf, 6*4, (char *)hash); Packet << hash[0] << hash[1] << hash[2] << hash[3] << hash[4]; } ///////////////////////////////////////////////////////////// // Insert exe/reg info Packet << szExeInfo << (BYTE)0x00 << m_sReg << (BYTE)0x00; return TRUE; } [/code] | July 22, 2004, 10:41 PM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=0#msg71946 date=1090535393] How do I actually use the code posted above? I mean, in packet 0x51 each time I log to bnet with d2, it sends different Client Token, Exe Hash, and different CdKey Data Hashes. How do I get these values? [/quote] The Client token is different because it uses GetTickCount() like I posted above for that value. The hash is different because it uses the server key value and a client key (client uses GetTickCount(), but you can use whatever you want) like posted above. The only hashes that will ever be the same is the create account hash. You can use starcraft's battle.snp if you want for all your hashing/cdkey decoding for d2. Or, you can do it your own way. | July 22, 2004, 10:48 PM |
z-stars | I'll try all that tomorrow, I go to sleep. Thanks for your help ppl. | July 22, 2004, 10:53 PM |
z-stars | I'm trying to implement that code u have posted but I'm having some problems... I have written this function... I need to get the "x" values. Could anyone help me to do that plz? I don't know how to apply OnlyMeat's code cuz I dont have most of the functions / classes / overloaded operators called, and I dont have battle.snp cuz it is a d2 bot :( Thx in advance. [code] // This function is supossed to build and send the fifth packet (0x51) int LTBNFifthPacket() { // S SID_AUTH_CHECK int x = 0; // If it's X I dont know what to place in em. BYTE FirstByte = 0xFF; BYTE PacketID = 0x51; WORD PacketLen = 136; DWORD ClientToken = x; DWORD ExeVersion = 0x000A0001; // Alredy in Little Endian. DWORD ExeHash = x; DWORD CDKeyNumber = 2; DWORD UsingOfKeys = 0; DWORD Key1Len = 10; DWORD Key1Product = 0x06000000; DWORD Key1Num1 = 0x00000000; // I set this to zeros. DWORD Key1Unknown = 0; DWORD Key1HashedData[5] = {x, x, x, x, x}; DWORD Key2Len = 10; DWORD Key2Product = 0x0A000000; DWORD Key2Num1 = 0x00000000; // I set this to zeros. DWORD Key2Unknown = 0; DWORD Key2HashedData[5] = {x, x, x, x, x}; char * ExeInfo = "Game.exe 10/13/03 08:35:30 1198857"; char * CDKeyOwner = "Me"; int n = 0; // The packet itself is stored at csFifthPacket.packet and is a // dynamically allocated BYTE array. // WriteByte writes a byte to the packet. (This is the first call // so it will write it at packet[0]. csFifthPacket.WriteByte(0xFF); csFifthPacket.WriteByte(0x51); // This function writes a word to the packet. If first argument is 0, // it will convert it to LittleEndian before writting it. // If it's 1, it wont. csFifthPacket.WriteWord(0, 136); // WriteDWord is like WriteWord but it writes a DWORD. csFifthPacket.WriteDWord(0, ClientToken); csFifthPacket.WriteDWord(1, ExeVersion); csFifthPacket.WriteDWord(0, ExeHash); csFifthPacket.WriteDWord(0, CDKeyNumber); csFifthPacket.WriteDWord(0, UsingOfKeys); csFifthPacket.WriteDWord(0, Key1Len); csFifthPacket.WriteDWord(1, Key1Product); csFifthPacket.WriteDWord(1, Key1Num1); csFifthPacket.WriteDWord(0, Key1Unknown); csFifthPacket.WriteDWord(0, Key1HashedData[4]); csFifthPacket.WriteDWord(0, Key1HashedData[3]); csFifthPacket.WriteDWord(0, Key1HashedData[2]); csFifthPacket.WriteDWord(0, Key1HashedData[1]); csFifthPacket.WriteDWord(0, Key1HashedData[0]); csFifthPacket.WriteDWord(0, Key2Len); csFifthPacket.WriteDWord(1, Key2Product); csFifthPacket.WriteDWord(1, Key2Num1); csFifthPacket.WriteDWord(0, Key2Unknown); csFifthPacket.WriteDWord(0, Key2HashedData[4]); csFifthPacket.WriteDWord(0, Key2HashedData[3]); csFifthPacket.WriteDWord(0, Key2HashedData[2]); csFifthPacket.WriteDWord(0, Key2HashedData[1]); csFifthPacket.WriteDWord(0, Key2HashedData[0]); // Writes an string and a null terminator. csFifthPacket.WriteString(ExeInfo); csFifthPacket.WriteString(CDKeyOwner); // SendPacket sends a packet to battle.net. // GetPacketLen() just returns the packet length. n = SendPacket(csFifthPacket.packet, csFifthPacket.GetPacketLen()); return n; } [/code] BTW, I have stored the values of SID_AUTH_INFO in this struct... The copy with em is called "r_SID_AUTH_INFO". [code] struct sr_SID_AUTH_INFO { BYTE IntegrityCheck; BYTE PacketID; BYTE PacketLen; DWORD Logon_Type; DWORD Server_Token; DWORD UDPValue; FILETIME MPQ_filetime; char IX86ver_filename[50]; char ValueString[100]; }; [/code] | July 23, 2004, 4:30 PM |
St0rm.iD | UL, how are you calling Battle.SNP? Injected or loaded? | July 23, 2004, 4:37 PM |
z-stars | [quote author=$t0rm link=board=17;threadid=7821;start=15#msg72043 date=1090600648] UL, how are you calling Battle.SNP? Injected or loaded? [/quote] I think I don't have Battle.SNP, the code UserLoser posted is for starcraft for what I understood. | July 23, 2004, 4:50 PM |
UserLoser. | [quote author=$t0rm link=board=17;threadid=7821;start=15#msg72043 date=1090600648] UL, how are you calling Battle.SNP? Injected or loaded? [/quote] LoadLibrary("battle.snp"); __asm call <address> | July 23, 2004, 5:27 PM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=15#msg72050 date=1090601434] [quote author=$t0rm link=board=17;threadid=7821;start=15#msg72043 date=1090600648] UL, how are you calling Battle.SNP? Injected or loaded? [/quote] I think I don't have Battle.SNP, the code UserLoser posted is for starcraft for what I understood. [/quote] http://www.userloser.net/files/battle.snp | July 23, 2004, 5:28 PM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=15#msg72055 date=1090603673] [quote author=$t0rm link=board=17;threadid=7821;start=15#msg72043 date=1090600648] UL, how are you calling Battle.SNP? Injected or loaded? [/quote] LoadLibrary("battle.snp"); __asm call <address> [/quote] LoadLibrary("battle.snp"); gives an error at runtime saying that couldn't init the app cuz it didn't find storm.dll :( | July 23, 2004, 5:50 PM |
OnlyMeat | [quote author=z-stars link=board=17;threadid=7821;start=15#msg72059 date=1090605038] [quote author=UserLoser. link=board=17;threadid=7821;start=15#msg72055 date=1090603673] [quote author=$t0rm link=board=17;threadid=7821;start=15#msg72043 date=1090600648] UL, how are you calling Battle.SNP? Injected or loaded? [/quote] LoadLibrary("battle.snp"); __asm call <address> [/quote] LoadLibrary("battle.snp"); gives an error at runtime saying that couldn't init the app cuz it didn't find storm.dll :( [/quote] If you are loading like that LoadLibrary("battle.snp"); you are assuming the battle.snp is in the exe directory of your program. Second point is their is'nt a battle.snp for diablo there is d2client.dll and bnclient.dll, i think d2client.dll is the equivilent but i cant be sure. If you dont specify a path to that file then you will need to copy the .dll into your application directory for loadlibrary to find it. Forgot to note that you will have to put the other hash files in your application directory:- (1) game.exe (2) d2client.dll (3) bnclient.dll | July 23, 2004, 6:03 PM |
z-stars | [quote author=OnlyMeat link=board=17;threadid=7821;start=15#msg72061 date=1090605813] [quote author=z-stars link=board=17;threadid=7821;start=15#msg72059 date=1090605038] [quote author=UserLoser. link=board=17;threadid=7821;start=15#msg72055 date=1090603673] [quote author=$t0rm link=board=17;threadid=7821;start=15#msg72043 date=1090600648] UL, how are you calling Battle.SNP? Injected or loaded? [/quote] LoadLibrary("battle.snp"); __asm call <address> [/quote] LoadLibrary("battle.snp"); gives an error at runtime saying that couldn't init the app cuz it didn't find storm.dll :( [/quote] If you are loading like that LoadLibrary("battle.snp"); you are assuming the battle.snp is in the exe directory of your program. Second point is their is'nt a battle.snp for diablo there is d2client.dll and bnclient.dll, i think d2client.dll is the equivilent but i cant be sure. If you dont specify a path to that file then you will need to copy the .dll into your application directory for loadlibrary to find it. [/quote] I have downloaded battle.snp from UserLoser's link and placed it at my program directory, but it gives the couldn't find storm.dll error | July 23, 2004, 6:06 PM |
OnlyMeat | well the thing is if you are trying to use d2 im not sure if that will work cuz the real d2 client does'nt use battle.snp it uses d2client.dll. If assuming that userloser has tried this and it works then you should copy the storm to dll into that directory as well. | July 23, 2004, 6:14 PM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=15#msg72059 date=1090605038] [quote author=UserLoser. link=board=17;threadid=7821;start=15#msg72055 date=1090603673] [quote author=$t0rm link=board=17;threadid=7821;start=15#msg72043 date=1090600648] UL, how are you calling Battle.SNP? Injected or loaded? [/quote] LoadLibrary("battle.snp"); __asm call <address> [/quote] LoadLibrary("battle.snp"); gives an error at runtime saying that couldn't init the app cuz it didn't find storm.dll :( [/quote] http://www.userloser.net/files/storm.dll D2 does have storm.dll also. | July 23, 2004, 6:33 PM |
z-stars | It does load it :) Now how do I use it to get ClientToken, ExeHash, etc? | July 23, 2004, 6:47 PM |
St0rm.iD | WHOA thats cool. Didn't know you could do that... Could't the place it loads in memory change, though? | July 23, 2004, 6:53 PM |
Kp | [quote author=$t0rm link=board=17;threadid=7821;start=15#msg72070 date=1090608794]Could't the place it loads in memory change, though?[/quote] Yes. That's why using a Logitech mouse can sometimes get you banned for cheating. However, the function can't move around inside the DLL without a version change (which might require a client update anyway), so you could opt to instead jump to <DLL-base-address>+function offset. When the DLL loads at its preferred address, DLL-base-address will be 19000000. You can do the math to compute the function offset. :) | July 23, 2004, 6:56 PM |
z-stars | Anyone knows how to get the value to place in the x's of the code I posted above? Using battle.snp or another thing, I dont care :( | July 23, 2004, 8:37 PM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=15#msg72084 date=1090615037] Anyone knows how to get the value to place in the x's of the code I posted above? Using battle.snp or another thing, I dont care :( [/quote] Read my post about CDKey hashing. It returns a 5 DWORD output. dwOutBuffer is what you're wanting to send. | July 23, 2004, 9:01 PM |
K | UserLoser: Why all the inline asm? [code] typedef void(__fastcall *pHashingFunction)(void* outbuf, void* inbuf, DWORD len); DWORD dwHashAddr = 0x12400; HMODULE hBattleSnp = LoadLibrary(_T("battle.snp")); dwHashAddr += reinterpret_cast<DWORD>(hBattleSnp); pHashFunction HashData = reinterpret_cast<pHashFunction>(dwHashAddr); // ... HashData(a, b, c); // whatever :-P [/code] but otherwise, good code. Nice to see other people are as lazy as I am. | July 23, 2004, 9:26 PM |
z-stars | Ok I think I understand but there are some things I dont know what they are. I supose dwProduct is my Key1Product and my Key2Product, but what are ServerSessionKey, dwPublic and dwPrivate? [code] DWORD dwHashBuffer[6]; DWORD dwOutBuffer[5]; dwHashBuffer[0] = GetTickCount(); //dwHashBuffer[1] = ServerSessionKey; dwHashBuffer[2] = Key1Product; //dwHashBuffer[3] = dwPublic; dwHashBuffer[4] = 0; //dwHashBuffer[5] = dwPrivate; HashData(24, dwOutBuffer, dwHashBuffer); /* ~~ */ DWORD dwHashBuffer2[6]; DWORD dwOutBuffer2[5]; dwHashBuffer[0] = GetTickCount(); //dwHashBuffer[1] = ServerSessionKey; dwHashBuffer[2] = Key2Product; //dwHashBuffer[3] = dwPublic; dwHashBuffer[4] = 0; //dwHashBuffer[5] = dwPrivate; HashData(24, dwOutBuffer2, dwHashBuffer2); /* ~~ */ [/code] | July 23, 2004, 9:57 PM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=30#msg72095 date=1090619820] Ok I think I understand but there are some things I dont know what they are. I supose dwProduct is my Key1Product and my Key2Product, but what are ServerSessionKey, dwPublic and dwPrivate? [code] DWORD dwHashBuffer[6]; DWORD dwOutBuffer[5]; dwHashBuffer[0] = GetTickCount(); //dwHashBuffer[1] = ServerSessionKey; dwHashBuffer[2] = Key1Product; //dwHashBuffer[3] = dwPublic; dwHashBuffer[4] = 0; //dwHashBuffer[5] = dwPrivate; HashData(24, dwOutBuffer, dwHashBuffer); /* ~~ */ DWORD dwHashBuffer2[6]; DWORD dwOutBuffer2[5]; dwHashBuffer[0] = GetTickCount(); //dwHashBuffer[1] = ServerSessionKey; dwHashBuffer[2] = Key2Product; //dwHashBuffer[3] = dwPublic; dwHashBuffer[4] = 0; //dwHashBuffer[5] = dwPrivate; HashData(24, dwOutBuffer2, dwHashBuffer2); /* ~~ */ [/code] [/quote] ! I said ServerSessionKey is from 0x50 (i believe the 3rd DWORD, received ofcourse). dwPublic and dwPrivate are the CDKey values returned from RunCDKeyDecode which I also posted. | July 23, 2004, 11:21 PM |
z-stars | Erm I got some more questions, in BnetDocs says that for each cdkey you have to put the first number of the cdkey... what does it mean with that? If it means the first group of digits and letters, there are letters, and if it means the first digit, in a packet log it isnt the first digit :( Another thing, the third DWORD to sent is called "Exe Hash", how do I get that? And a little thing, in RunCDKeyDecode(), the last argument, do I include the dashes or I dont include them? | July 24, 2004, 12:06 AM |
UserLoser. | No dashes, no spaces. For a Starcraft CDKey, it should be 13 numbers, for a D2/W2 CDKey, it should be 16 numbers/letters. It doesn't support W3 CDKeys. | July 24, 2004, 12:36 AM |
z-stars | I see, but how do I get Exe hash and CD Key 1 Number 1 and CD Key 2 Number 2? I tried setting Exe Hash to zero and CD Key Num 1's to some values I logged, but I send the packet and BNet IP bans me and doesn't send me the next packet... | July 24, 2004, 12:47 AM |
UserLoser. | exe hash is from checkrevision, which someone posted. cdkey value 1 = dwpublic, cdkey value 2 = dwprivate. | July 24, 2004, 1:02 AM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=30#msg72120 date=1090630930] exe hash is from checkrevision, which someone posted. cdkey value 1 = dwpublic, cdkey value 2 = dwprivate. [/quote] Oh yeah I posted a checkrevision function, I'll try to make it work tomorrow :) | July 24, 2004, 1:31 AM |
St0rm.iD | semi-OT, but how did you find the offset in battle.snp? | July 24, 2004, 2:49 PM |
UserLoser. | [quote author=$t0rm link=board=17;threadid=7821;start=30#msg72179 date=1090680576] semi-OT, but how did you find the offset in battle.snp? [/quote] disassembly. | July 24, 2004, 4:41 PM |
z-stars | I have "finished" the function to build 0x51 packet but it doesn't work, I run it, it sends the packet, but then it doesn't receive the next packet and BNet IP bans me :( Anyway I didn't expect it to work at the first try... I think I need some help to make it work... Some things that may be useful to know... -CheckRevision() returns TRUE (I think that means it didnt fail) -These are all the components of packet 0x51. BNetDocs is offline now so I dont know if there they are called exactly the same way. [code] (byte) 0xFF (byte) PacketID (word) PacketLength (dword) Client Token (dword) Exe Version (dword) Exe Hash (dword) Number of CD Keys (dword) Always 0 for non warcraft 3 connections. ;First cd key (dword) Key Length (dword) Product ID (dword) First number of the cdkey (dword) Unknown (0) (dword[5]) CdKey Hashed Data ;Second cd key (dword) Key Length (dword) Product ID (dword) First number of the cdkey (dword) Unknown (0) (dword[5]) CdKey Hashed Data (string) Exe Info (string) CD Key Owner [/code] -The things that I think that may go wrong are for example the conversions to LittleEndian. For example, I have assumed that dwOutputBuffer is "Rdy to send", I mean, I just copy all its bytes in order into the packet. dwOutputBuffer[0]'s first byte will be the first byte at the packet's CDKeyDataHash bytes, etc. -Another thing that may be wrong is (dword) First CD Key first number and (dword) Second CD Key first number. In my function, the first one is dwPublic and the second dwPrivate, because their values aren't the same than the values I log with a packet sniffer when I log to battle.net. -szD2CdKey, the var that contains the D2 cd key for RunCDKeyDecode to decode, is declared like this: char * szD2CdKey = "xxxxxxxxxxxxxxxx"; (of course, each x represents a number / letter of the real cd key). There are 16 numbers/letters in total. -I dont know what more to say, just ask if I forgot something. This is the code, I have tidied it to make it more readable and commented it better... The CheckRevision() function is the same that I posted at the first page of this topic. [code] // S SID_AUTH_CHECK // This function is supossed to build and send the fifth packet (0x51) // At the start of this function, csFifthPacket.packet (the packet 0x51 that // this function sends to battle.net at the end) is EMPTY. int LTBNFifthPacket() { /* Var declarations... */ int n = 0; char * CDKeyOwner = "Me"; /* End of Var declarations */ /* First, load Battle.snp to do the hasing for us */ HMODULE battlesnp; battlesnp = LoadLibrary("Battle.snp"); if(!battlesnp) cout << "Couldn't load battle.snp" << endl; /* Battlesnp Loaded */ /* CHECK REVISION */ /* Call CheckRevision() to get the some of the values to send */ /* The values we get are: ExeHash and Version (dwExeHash, and dwVersion) */ /* Also, we get an ExeInfo string. (To CRExeInfo). */ DWORD dwVersion = 0; DWORD dwChecksum = 0; char CRExeInfo[5000]; memset(CRExeInfo, 0, 5000); //strcpy(CRExeInfo, ExeInfo); BOOL bCheckRevision = 0; bCheckRevision = CheckRevision("C:\\Archivos de programa\\Diablo II\\Game.exe", "C:\\Archivos de programa\\Diablo II\\Bnclient.dll", "C:\\Archivos de programa\\Diablo II\\storm.dll", r_SID_AUTH_INFO.ValueString, &dwVersion, &dwChecksum, CRExeInfo, r_SID_AUTH_INFO.IX86ver_filename); if(bCheckRevision == FALSE) cout << "ERROR: CheckRevision() Failed" << endl; else cout << "CheckRevision() Success" << endl; /*printf("dwVersion: %x || dwChecksum: %x || ExeInfo: %s", dwVersion, dwChecksum, CRExeInfo);*/ /* END OF CHECK REVISION */ /* VARIABLES TO PUT IN THE PACKET DECLARATIONS */ int x = 0; BYTE FirstByte = 0xFF; // It's always 0xFF BYTE PacketID = 0x51; // PacketId's 0x51 WORD PacketLen = 136; // Packet Length is 136 DWORD ClientToken = GetTickCount(); // I use GetTickCount() to get that DWORD ExeVersion = dwVersion; // From CheckRevision() DWORD ExeHash = dwChecksum; // From CheckRevision() DWORD CDKeyNumber = 2; // 1 D2 cd key, 1 Lod cd key. DWORD UsingOfKeys = 0; // 0 DWORD Key1Len = 0x10; // Length of D2 CdKey: 16 (0x10) DWORD Key1Product = 0x06000000; // Key1 Product: 0x06000000 DWORD Key1Num1 = x; // This is supossed to be the First Number of the first cd key. // I'm not sure how to get it. DWORD Key1Unknown = 0; // Unknown(0) DWORD Key2Len = 0x10; // Same... DWORD Key2Product = 0x0A000000; // Key2 (LOD) Product: 0x0A000000 DWORD Key2Num1 = x; // Same... DWORD Key2Unknown = 0; // Unknown (0) /* END OF VARIABLES TO PUT IN THE PACKET DECLARATIONS */ /* CALL RUNCDKEYDECODE */ DWORD dwProduct = Key1Product; DWORD dwPrivate = 0; DWORD dwPublic = 0; RunCDkeyDecode(&dwProduct, &dwPublic, &dwPrivate, szD2CdKey); //// //cout << endl << "RUNCDKEYDECODE" << endl; //cout << "dwProduct: " << hex << dwProduct << endl; //cout << "dwPublic: " << hex << dwPublic << endl; //cout << "dwPrivate: " << hex << dwPrivate << endl; //cout << endl << endl; /* END OF CALL RUNCDKEYDECODE */ /* CALL HASHDATA FOR CDKEY1*/ DWORD dwHashBuffer[6]; DWORD dwOutBuffer[5]; // This is supossed to be the CDKey1 Data. dwHashBuffer[0] = ClientToken; // We got this with GetTickCount() dwHashBuffer[1] = r_SID_AUTH_INFO.Server_Token; // Bnet sent this in the last packet dwHashBuffer[2] = dwProduct; // We got this with RunCDKeyDecode dwHashBuffer[3] = dwPublic; // We got this with RunCDKeyDecode too dwHashBuffer[4] = 0; // 0... dwHashBuffer[5] = dwPrivate; // Also, we got this with RunCDKeyDecode HashData(24, dwOutBuffer, dwHashBuffer); /* END OF CALL HASHDATA */ /* DO THE SAME FOR CDKEY2 */ DWORD dwProduct2 = Key2Product; DWORD dwPrivate2 = 0; DWORD dwPublic2 = 0; RunCDkeyDecode(&dwProduct, &dwPublic, &dwPrivate, szCdKey2); DWORD dwHashBuffer2[6]; DWORD dwOutBuffer2[5]; dwHashBuffer[0] = GetTickCount(); dwHashBuffer[1] = r_SID_AUTH_INFO.Server_Token; dwHashBuffer[2] = dwProduct2; dwHashBuffer[3] = dwPublic2; dwHashBuffer[4] = 0; dwHashBuffer[5] = dwPrivate2; HashData(24, dwOutBuffer2, dwHashBuffer2); /* ~~ */ /* WRITE EVERYTHING IN THE PACKET */ // Info about csFifthPacket class: // The packet itself is csFifthPacket.packet and it is a // dynamically allocated BYTE array. // The position the next function will write to is stored at // nByte2Write and is increased automatically with each WriteX function // call. // WriteByte writes a byte to packet. (csFifthPacket.packet). // WriteWord and WriteDWord take 2 arguments. The first one tells // if it has to convert the Word or DWord given to Little Endian before // putting it in packet or not. If the first argument is 0, it will // convert the DWORD given to Little Endian, and then put it in the // packet. If it is 1, it will put it in the packet directly without // converting it. // WriteString() just writes a string and a null terminator to packet. csFifthPacket.WriteByte(0xFF); csFifthPacket.WriteByte(0x51); csFifthPacket.WriteWord(0, 136); csFifthPacket.WriteDWord(0, ClientToken); csFifthPacket.WriteDWord(0, ExeVersion); // From CheckRevision() csFifthPacket.WriteDWord(0, ExeHash); // From CheckRevision() csFifthPacket.WriteDWord(0, CDKeyNumber); csFifthPacket.WriteDWord(0, UsingOfKeys); csFifthPacket.WriteDWord(0, Key1Len); csFifthPacket.WriteDWord(1, Key1Product); csFifthPacket.WriteDWord(1, dwPublic); csFifthPacket.WriteDWord(0, Key1Unknown); csFifthPacket.WriteDWord(1,dwOutBuffer[0]); csFifthPacket.WriteDWord(1,dwOutBuffer[1]); csFifthPacket.WriteDWord(1,dwOutBuffer[2]); csFifthPacket.WriteDWord(1,dwOutBuffer[3]); csFifthPacket.WriteDWord(1,dwOutBuffer[4]); csFifthPacket.WriteDWord(0, Key2Len); csFifthPacket.WriteDWord(1, Key2Product); csFifthPacket.WriteDWord(1, dwPrivate); csFifthPacket.WriteDWord(0, Key2Unknown); csFifthPacket.WriteDWord(1,dwOutBuffer2[0]); csFifthPacket.WriteDWord(1,dwOutBuffer2[1]); csFifthPacket.WriteDWord(1,dwOutBuffer2[2]); csFifthPacket.WriteDWord(1,dwOutBuffer2[3]); csFifthPacket.WriteDWord(1,dwOutBuffer2[4]); csFifthPacket.WriteString(CRExeInfo); // From CheckRevision() csFifthPacket.WriteString(CDKeyOwner); // These two sentences set the packet size word of packet to the packet // len. (Previously it was 136 instead 134). csFifthPacket.SetByte2Write(2); csFifthPacket.WriteWord(0, csFifthPacket.GetPacketLen()); /* END OF WRITE EVERYTHING AT THE PACKET */ /* SEND csFifthPacket.packet TO BATTLE.NET */ n = SendPacket(csFifthPacket.packet, csFifthPacket.GetPacketLen()); if(n == -1) error(10, "SendPacket"); else cout << "Packet 0x51 Sent " << "Bytes: " << n << endl; /* END OF SEND PACKET TO BATTLE.NET */ return n; } void HashData(DWORD length, LPVOID outbuf, LPVOID tohash) { DWORD len = length; __asm { push ecx push edx mov ecx, outbuf mov edx, tohash push len call HashFunction pop edx pop ecx } } void RunCDkeyDecode(DWORD *Product, DWORD *CDKeyVal1, DWORD *CDKeyVal2, const char *CDKey) { __asm { push ecx push edx mov ecx, CDKey mov edx, Product push CDKeyVal2 push CDKeyVal1 call DecodeCDKeyFunction pop edx pop ecx } } [/code] Sorry for asking so many questions and thanks for your help in advance :) | July 24, 2004, 6:05 PM |
UserLoser. | Could you show us a packet log of the connection? | July 24, 2004, 6:14 PM |
z-stars | Packet log between my program and USWEST battle.net (Normally I use europe but I was IP banned...) The X's are either the CDKey Hashed Data or the CD Key first numbers... [code] 1 Hide Hide 1 Send 0000 01 . 2 Hide Hide 50 Send 0000 FF 50 32 00 00 00 00 00 36 38 58 49 50 58 32 44 .P2.....68XIPX2D 0010 0A 00 00 00 53 45 73 65 50 23 6B 1D 88 FF FF FF ....SEseP#k..... 0020 0A 0C 00 00 0A 0C 00 00 45 53 50 00 53 70 61 69 ........ESP.Spai 0030 6E 00 n. 3 Hide Hide 8 Recv 0000 FF 25 08 00 3E 6B CB 97 .%..>k.. 4 Hide Hide 98 Recv 0000 FF 50 62 00 00 00 00 00 23 E1 64 6C 22 6F 15 00 .Pb.....#.dl"o.. 0010 00 81 8F 83 91 E7 C3 01 49 58 38 36 76 65 72 37 ........IX86ver7 0020 2E 6D 70 71 00 41 3D 35 37 38 33 31 35 30 34 32 .mpq.A=578315042 0030 20 42 3D 37 39 35 34 31 35 34 34 33 20 43 3D 36 B=795415443 C=6 0040 32 34 39 37 32 31 37 20 34 20 41 3D 41 2D 53 20 2497217 4 A=A-S 0050 42 3D 42 2B 43 20 43 3D 43 5E 41 20 41 3D 41 2D B=B+C C=C^A A=A- 0060 42 00 B. 5 Hide Hide 9 Send 0000 FF 25 08 00 F3 2A 9F 4D CC .%...*.M. 6 Hide Hide 134 Send 0000 FF 51 88 00 67 A3 B1 00 00 0A 00 00 1E 9B F9 00 .Q..g........... 0010 02 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ................ 0020 XX XX XX XX 00 00 00 00 XX XX XX XX XX XX XX XX ................ 0030 XX XX XX XX XX XX XX XX XX XX XX XX 10 00 00 00 ................ 0040 00 00 00 00 XX XX XX XX 00 00 00 00 XX XX XX XX .....1.`.......5 0050 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX .....t....R5...r 0060 47 61 6D 65 2E 65 78 65 20 30 35 2F 31 36 2F 30 Game.exe 05/16/0 0070 34 20 32 31 3A 33 31 3A 33 36 20 31 31 39 38 38 4 21:31:36 11988 0080 35 37 00 4D 65 00 57.Me. [/code] | July 24, 2004, 6:33 PM |
UserLoser. | [quote] 6 Hide Hide 134 Send [/quote] You're giving 0x88 (136) as your length. Edit: Also, you're only supposed to reply with one DWORD in 0x25, and echo what the server sent you first. That's mostly be causing the disconnect. The bad length on 0x51 packet would most likely just make the server wait for 2 more bytes (or however many) until the amount of data you sent matched the length you have given. | July 24, 2004, 6:47 PM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=30#msg72250 date=1090694845] [quote] 6 Hide Hide 134 Send [/quote] You're giving 0x88 (136) as your length. [/quote] Yeah, modified the code in my program (and the code in the post) but it still doesn't work. :( | July 24, 2004, 6:49 PM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=30#msg72245 date=1090694035] [code] 3 Hide Hide 8 Recv 0000 FF 25 08 00 3E 6B CB 97 .%..>k.. 5 Hide Hide 9 Send 0000 FF 25 08 00 F3 2A 9F 4D CC .%...*.M. [/code] [/quote] That's your problem. | July 24, 2004, 6:51 PM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=45#msg72254 date=1090695100] [quote author=z-stars link=board=17;threadid=7821;start=30#msg72245 date=1090694035] [code] 3 Hide Hide 8 Recv 0000 FF 25 08 00 3E 6B CB 97 .%..>k.. 5 Hide Hide 9 Send 0000 FF 25 08 00 F3 2A 9F 4D CC .%...*.M. [/code] [/quote] That's your problem. [/quote] I removed the PingPacket and I received the sixth packet :) I'll try to parse it as soon as I get my IP ban removed. | July 24, 2004, 7:08 PM |
z-stars | I've tried to parse the 0x51 packet I receive but it doesn't seem to be any of the BNetDoc values... Maybe I am parsing it wrong... I am just parsing the first CD Key1 values because I'm not sure how to parse the ones of the second cd key. This is the new packet log... [code] 1 Hide Hide 1 Send 0000 01 . 2 Hide Hide 50 Send 0000 FF 50 32 00 00 00 00 00 36 38 58 49 50 58 32 44 .P2.....68XIPX2D 0010 0A 00 00 00 53 45 73 65 50 23 6B 1D 88 FF FF FF ....SEseP#k..... 0020 0A 0C 00 00 0A 0C 00 00 45 53 50 00 53 70 61 69 ........ESP.Spai 0030 6E 00 n. 3 Hide Hide 8 Recv 0000 FF 25 08 00 C2 DD 48 48 .%....HH 4 Hide Hide 99 Recv 0000 FF 50 63 00 00 00 00 00 26 E6 3A 18 79 67 26 00 .Pc.....&.:.yg&. 0010 00 92 72 76 91 E7 C3 01 49 58 38 36 76 65 72 31 ..rv....IX86ver1 0020 2E 6D 70 71 00 41 3D 33 33 31 38 36 34 32 38 34 .mpq.A=331864284 0030 20 42 3D 37 36 30 38 31 39 34 30 37 20 43 3D 31 B=760819407 C=1 0040 36 39 32 32 32 38 33 35 20 34 20 41 3D 41 2B 53 69222835 4 A=A+S 0050 20 42 3D 42 2D 43 20 43 3D 43 5E 41 20 41 3D 41 B=B-C C=C^A A=A 0060 5E 42 00 ^B. 5 Hide Hide 136 Send 0000 FF 51 86 00 6E 61 EF 00 00 0A 00 00 90 8D E7 00 .Q..na.......... 0010 02 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ................ 0020 00 13 7D 6C 00 00 00 00 XX XX XX XX XX XX XX XX ..}l.......V.... 0030 XX XX XX XX XX XX XX XX XX XX XX XX 10 00 00 00 ...%.x...+m..... 0040 00 00 00 00 XX XX XX XX 00 00 00 00 XX XX XX XX .....1.`.......5 0050 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX .....t....R5...r 0060 47 61 6D 65 2E 65 78 65 20 30 35 2F 31 36 2F 30 Game.exe 05/16/0 0070 34 20 32 31 3A 33 31 3A 33 36 20 31 31 39 38 38 4 21:31:36 11988 0080 35 37 00 4D 65 00 CD CD 57.Me... 6 Hide Hide 9 Recv 0000 FF 51 09 00 01 01 00 00 00 .Q....... [/code] And here the code I use to parse the packet: [code] LTBNSixthPacket() { int n = 0; BEFORE_RECV; n = RecvPacket(crSixthPacket.packet, 50); if(n == -1) error(9, "RecvPacket"); else cout << "Packet 6 Recv. Bytes: " << n << endl; memset(r_SID_AUTH_CHECK.AdditionalInformation, 0, sizeof(r_SID_AUTH_CHECK.AdditionalInformation)); crSixthPacket.ReadByte(&r_SID_AUTH_CHECK.IntegrityCheck); crSixthPacket.ReadByte(&r_SID_AUTH_CHECK.PacketID); crSixthPacket.ReadWord(0, &r_SID_AUTH_CHECK.PacketLen); // Im converting this dword to big endian before parsing it. crSixthPacket.ReadDWord(0, &r_SID_AUTH_CHECK.Result); crSixthPacket.ReadString(r_SID_AUTH_CHECK.AdditionalInformation); cout << endl; switch(r_SID_AUTH_CHECK.Result) { case 0x000: cout << "Passed Challenge" << endl; break; case 0x100: cout << "Old Game Version" << endl; break; case 0x001: cout << "Invalid Version" << endl; break; case 0x200: cout << "Invalid CDKey" << endl; break; case 0x201: cout << "CDKey in use" << endl; break; case 0x202: cout << "Banned CDKey" << endl; break; case 0x203: cout << "Wrong Product" << endl; break; default: cout << "Undefined" << endl; } [/code] And the cr_SID_AUTH_CHECK struct: [code] struct sr_SID_AUTH_CHECK { BYTE IntegrityCheck; BYTE PacketID; WORD PacketLen; DWORD Result; char AdditionalInformation[200]; }; [/code] BTW, the output from this part of the code is: [code] Packet 6 recv. Bytes: 9 Undefined ADDITIONAL INFORMATION: [/code] Also, battle.net still IP Bans me. BNETDocs description of the packet: [code] Packet ID: 0x51 Direction: Server -> Client (Received) Format: Help (DWORD) Result (STRING) Additional Information Remarks: Reports success/failure on version & CD Key check. Result: 0x000: Passed challenge 0x100: Old game version (Additional info field supplies patch MPQ filename) 0x101: Invalid version 0x200: Invalid CD key 0x201: CD key in use (Additional info field supplies name of user) 0x202: Banned key 0x203: Wrong product The last 4 codes also apply to the second cdkey, as indicated by a bitwise combination with 0x010. [/code] | July 24, 2004, 7:44 PM |
UserLoser. | You're sending two extra bytes which shouldn't be there at the very end of your 0x51 packet which is causing the IPban. As far as the invalid version (0x101) response, do you have the newest hash files? Are you sure you're using the expansion files and not classic? | July 24, 2004, 7:49 PM |
ChR0NiC | [quote author=z-stars link=board=17;threadid=7821;start=45#msg72266 date=1090698249] [code] 5 Hide Hide 136 Send 0000 FF 51 86 00 6E 61 EF 00 00 0A 00 00 90 8D E7 00 .Q..na.......... 0010 02 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ................ 0020 00 13 7D 6C 00 00 00 00 XX XX XX XX XX XX XX XX ..}l.......V.... 0030 XX XX XX XX XX XX XX XX XX XX XX XX 10 00 00 00 ...%.x...+m..... 0040 00 00 00 00 XX XX XX XX 00 00 00 00 XX XX XX XX .....1.`.......5 0050 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX .....t....R5...r 0060 47 61 6D 65 2E 65 78 65 20 30 35 2F 31 36 2F 30 Game.exe 05/16/0 0070 34 20 32 31 3A 33 31 3A 33 36 20 31 31 39 38 38 4 21:31:36 11988 0080 35 37 00 4D 65 00 CD CD 57.Me... [/code] [/quote] After "Me" which is shown being sent here Null Terminated, you have included two bytes here and that will DEFINITELY cause an IP Ban, could also be what's screwing you over with the invalid game version error. | July 24, 2004, 7:54 PM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=45#msg72267 date=1090698560] You're sending two extra bytes which shouldn't be there at the very end of your 0x51 packet which is causing the IPban. As far as the invalid version (0x101) response, do you have the newest hash files? Are you sure you're using the expansion files and not classic? [/quote] Mhh didn't know it was invalid version response, my switch goes to the default for some reason, but about the hash files no I'm not sure, which files are the hash files? | July 24, 2004, 7:55 PM |
ChR0NiC | [quote author=UserLoser. link=board=17;threadid=7821;start=45#msg72267 date=1090698560] You're sending two extra bytes which shouldn't be there at the very end of your 0x51 packet which is causing the IPban. As far as the invalid version (0x101) response, do you have the newest hash files? Are you sure you're using the expansion files and not classic? [/quote] [quote author=z-stars link=board=17;threadid=7821;start=45#msg72269 date=1090698923] Mhh didn't know it was invalid version response, my switch goes to the default for some reason, but about the hash files no I'm not sure, which files are the hash files? [/quote] That would be your Game.exe, D2Client.dll and BNClient.dll I believe | July 24, 2004, 7:56 PM |
z-stars | [quote author=ChR0NiC link=board=17;threadid=7821;start=45#msg72270 date=1090698984] [quote author=UserLoser. link=board=17;threadid=7821;start=45#msg72267 date=1090698560] You're sending two extra bytes which shouldn't be there at the very end of your 0x51 packet which is causing the IPban. As far as the invalid version (0x101) response, do you have the newest hash files? Are you sure you're using the expansion files and not classic? [/quote] [quote author=z-stars link=board=17;threadid=7821;start=45#msg72269 date=1090698923] Mhh didn't know it was invalid version response, my switch goes to the default for some reason, but about the hash files no I'm not sure, which files are the hash files? [/quote] That would be your Game.exe, D2Client.dll and BNClient.dll I believe [/quote] Ahh, I'll try with D2Client.dll | July 24, 2004, 8:00 PM |
z-stars | Well we're advancing, now it doesn't ban me :) but the packet I receive is the same... New log: [code] 1 Hide Hide 1 Send 0000 01 . 2 Hide Hide 50 Send 0000 FF 50 32 00 00 00 00 00 36 38 58 49 50 58 32 44 .P2.....68XIPX2D 0010 0A 00 00 00 53 45 73 65 50 23 6B 1D 88 FF FF FF ....SEseP#k..... 0020 0A 0C 00 00 0A 0C 00 00 45 53 50 00 53 70 61 69 ........ESP.Spai 0030 6E 00 n. 3 Hide Hide 8 Recv 0000 FF 25 08 00 D3 E8 8C 69 .%.....i 4 Hide Hide 100 Recv 0000 FF 50 64 00 00 00 00 00 88 EE 54 4C 41 44 0E 00 .Pd.......TLAD.. 0010 00 FA FB 7F 91 E7 C3 01 49 58 38 36 76 65 72 35 ........IX86ver5 0020 2E 6D 70 71 00 41 3D 31 30 32 36 37 38 35 35 33 .mpq.A=102678553 0030 39 20 42 3D 32 38 34 34 36 37 34 33 32 20 43 3D 9 B=284467432 C= 0040 35 33 31 36 32 30 36 30 37 20 34 20 41 3D 41 5E 531620607 4 A=A^ 0050 53 20 42 3D 42 2B 43 20 43 3D 43 2D 41 20 41 3D S B=B+C C=C-A A= 0060 41 2B 42 00 A+B. 5 Hide Hide 134 Send 0000 FF 51 86 00 ED D9 0C 00 00 0A 00 00 A8 D0 6E 00 .Q............n. 0010 02 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ................ 0020 00 13 7D 6C 00 00 00 00 XX XX XX XX XX XX XX XX ..}l.....Y...... 0030 XX XX XX XX XX XX XX XX XX XX XX XX 10 00 00 00 ..%}.=.}.:...... 0040 00 00 00 00 XX XX XX XX 00 00 00 00 XX XX XX XX .....1.`.......5 0050 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX .....t....R5...r 0060 47 61 6D 65 2E 65 78 65 20 30 35 2F 31 36 2F 30 Game.exe 05/16/0 0070 34 20 32 31 3A 33 31 3A 33 36 20 31 31 39 38 38 4 21:31:36 11988 0080 35 37 00 4D 65 00 57.Me. 6 Hide Hide 9 Recv 0000 FF 51 09 00 01 01 00 00 00 [/code] BTW, the CheckRevision call... [code] bCheckRevision = CheckRevision("C:\\Archivos de programa\\Diablo II\\Game.exe", "C:\\Archivos de programa\\Diablo II\\D2Client.dll", "C:\\Archivos de programa\\Diablo II\\BnClient.dll", r_SID_AUTH_INFO.ValueString, &dwVersion, &dwChecksum, CRExeInfo, r_SID_AUTH_INFO.IX86ver_filename); if(bCheckRevision == FALSE) cout << "ERROR: CheckRevision() Failed" << endl; else cout << "CheckRevision() Success" << endl; [/code] It returns TRUE. I posted the CheckRevision() function at the first page of the topic. | July 24, 2004, 8:12 PM |
z-stars | Does anyone know what can be failing? :( | July 24, 2004, 10:26 PM |
kamakazie | [quote author=UserLoser. link=board=17;threadid=7821;start=45#msg72372 date=1090731457][quote author=$t0rm link=board=17;threadid=7821;start=45#msg72360 date=1090725687][quote author=UserLoser. link=board=17;threadid=7821;start=30#msg72205 date=1090687296][quote author=$t0rm link=board=17;threadid=7821;start=30#msg72179 date=1090680576]semi-OT, but how did you find the offset in battle.snp?[/quote] disassembly.[/quote] never thought of that :P But seriously, what tools did you use? Did you just breakpoint CreateFile on stardat.mpq and trace from there? [/quote] All starts from send. You find the call to send used for BNCS related packets. You then trace it back to 0x51. Then you go back on each call and see what they do and what's being passed into it. So setting some breakpoints would help. Or, just search for mov cl and find mov cl, 51h[/quote] Thats how I started ;) [Kp edit: no changes to original post, just an explanation. Per Adron's hint, I've split the reverse-engineering section out into its own thread. This response and the one after it are remnants of that side discussion, which deserved its own thread.] | July 25, 2004, 5:13 AM |
z-stars | [quote author=Adron link=board=17;threadid=7821;start=45#msg72402 date=1090752921] Wish I could steal this part of the thread to the advanced programming forum, or somewhere that the hints on reverse engineering wouldn't be buried in newbie questions so quickly :) [/quote] And I wish someone would answer my last newbie question so I can finish my bot :) | July 25, 2004, 1:34 PM |
St0rm.iD | What's a good debugger on winxp? | July 25, 2004, 1:58 PM |
z-stars | [quote author=$t0rm link=board=17;threadid=7821;start=60#msg72421 date=1090763901] What's a good debugger on winxp? [/quote] Softice :) | July 25, 2004, 2:07 PM |
St0rm.iD | not on xp it isn't. | July 25, 2004, 2:22 PM |
z-stars | [quote author=$t0rm link=board=17;threadid=7821;start=60#msg72424 date=1090765351] not on xp it isn't. [/quote] Well my softice works in xp pretty well, but its true that I don't really use it for Debugging... | July 25, 2004, 3:01 PM |
z-stars | Going back to the topic, nobody knows how to make my bot log to battle.net? | July 25, 2004, 7:56 PM |
kamakazie | [quote author=z-stars link=board=17;threadid=7821;start=45#msg72269 date=1090698923] [quote author=UserLoser. link=board=17;threadid=7821;start=45#msg72267 date=1090698560] You're sending two extra bytes which shouldn't be there at the very end of your 0x51 packet which is causing the IPban. As far as the invalid version (0x101) response, do you have the newest hash files? Are you sure you're using the expansion files and not classic? [/quote] Mhh didn't know it was invalid version response, my switch goes to the default for some reason, but about the hash files no I'm not sure, which files are the hash files? [/quote] [quote] cout << endl; switch(r_SID_AUTH_CHECK.Result) { case 0x000: cout << "Passed Challenge" << endl; break; case 0x100: cout << "Old Game Version" << endl; break; case 0x001: cout << "Invalid Version" << endl; break; case 0x200: cout << "Invalid CDKey" << endl; break; case 0x201: cout << "CDKey in use" << endl; break; case 0x202: cout << "Banned CDKey" << endl; break; case 0x203: cout << "Wrong Product" << endl; break; default: cout << "Undefined" << endl; } [/quote] I don't know if this was fixed and it shouldn't really matter but you need to fix the bold part to 0x101. | July 25, 2004, 8:03 PM |
kamakazie | [quote author=z-stars link=board=17;threadid=7821;start=45#msg72273 date=1090699943] BTW, the CheckRevision call... [code] bCheckRevision = CheckRevision("C:\\Archivos de programa\\Diablo II\\Game.exe", "C:\\Archivos de programa\\Diablo II\\D2Client.dll", "C:\\Archivos de programa\\Diablo II\\BnClient.dll", r_SID_AUTH_INFO.ValueString, &dwVersion, &dwChecksum, CRExeInfo, r_SID_AUTH_INFO.IX86ver_filename); if(bCheckRevision == FALSE) cout << "ERROR: CheckRevision() Failed" << endl; else cout << "CheckRevision() Success" << endl; [/code] It returns TRUE. I posted the CheckRevision() function at the first page of the topic. [/quote] Try swapping BnClient.dll and D2Client.dll. | July 25, 2004, 8:06 PM |
z-stars | Thx dxoigmn, I changed the 0x001 and the switch works now, but I swapped d2client and bnetclient and it stills sends me the invalid version packet :( | July 25, 2004, 11:53 PM |
kamakazie | [quote author=z-stars link=board=17;threadid=7821;start=60#msg72535 date=1090799609] Thx dxoigmn, I changed the 0x001 and the switch works now, but I swapped d2client and bnetclient and it stills sends me the invalid version packet :( [/quote] Post your code where it creates SID_AUTH_CHECK (0x51) again. | July 26, 2004, 12:00 AM |
z-stars | Function offsets: [code] const DWORD HashFunction = 0x19012400; const DWORD DecodeCDKeyFunction = 0x19019AB0; [/code] The function that builds the packet: [code] // S SID_AUTH_CHECK // This function is supossed to build and send the fifth packet (0x51) // At the start of this function, csFifthPacket.packet (the packet 0x51 that // this function sends to battle.net at the end) is EMPTY. int LTBNFifthPacket() { /* Globals... */ BEFORE_SEND; int n = 0; char * CDKeyOwner = "Me"; /* End of Globals */ /* First, load Battle.snp to do the hasing for us */ HMODULE battlesnp; battlesnp = LoadLibrary("Battle.snp"); if(!battlesnp) cout << "Couldn't load battle.snp" << endl; /* Battlesnp Loaded */ /* CHECK REVISION */ /* Call CheckRevision() to get the some of the values to send */ /* The values we get are: ExeHash and Version (dwExeHash, and dwVersion) */ /* Also, we get an ExeInfo string. (To CRExeInfo). */ DWORD dwVersion = 0; DWORD dwChecksum = 0; char CRExeInfo[5000]; memset(CRExeInfo, 0, 5000); //strcpy(CRExeInfo, ExeInfo); BOOL bCheckRevision = 0; bCheckRevision = CheckRevision("C:\\Archivos de programa\\Diablo II\\Game.exe", "C:\\Archivos de programa\\Diablo II\\BnClient.dll", "C:\\Archivos de programa\\Diablo II\\D2Client.dll", r_SID_AUTH_INFO.ValueString, &dwVersion, &dwChecksum, CRExeInfo, r_SID_AUTH_INFO.IX86ver_filename); if(bCheckRevision == FALSE) cout << "ERROR: Check Revision() Failed" << endl; else cout << "CheckRevision() Success" << endl; /*printf("dwVersion: %x || dwChecksum: %x || ExeInfo: %s", dwVersion, dwChecksum, CRExeInfo);*/ /* END OF CHECK REVISION */ /* VARIABLES TO PUT IN THE PACKET DECLARATIONS */ int x = 0; BYTE FirstByte = 0xFF; // It's always 0xFF BYTE PacketID = 0x51; // PacketId's 0x51 WORD PacketLen = 136; // Packet Length is 136 DWORD ClientToken = GetTickCount(); // I use GetTickCount() to get that DWORD ExeVersion = dwVersion; // From CheckRevision() DWORD ExeHash = dwChecksum; // From CheckRevision() DWORD CDKeyNumber = 2; // 1 D2 cd key, 1 Lod cd key. DWORD UsingOfKeys = 0; // 0 DWORD Key1Len = 0x10; // Length of D2 CdKey: 16 (0x10) DWORD Key1Product = 0x06000000; // Key1 Product: 0x06000000 DWORD Key1Num1 = x; // This is supossed to be the First Number of the first cd key. // I'm not sure how to get it. DWORD Key1Unknown = 0; // Unknown(0) DWORD Key2Len = 0x10; // Same... DWORD Key2Product = 0x0A000000; // Key2 (LOD) Product: 0x0A000000 DWORD Key2Num1 = x; // Same... DWORD Key2Unknown = 0; // Unknown (0) /* END OF VARIABLES TO PUT IN THE PACKET DECLARATIONS */ /* CALL RUNCDKEYDECODE */ DWORD dwProduct = Key1Product; DWORD dwPrivate = 0; DWORD dwPublic = 0; RunCDkeyDecode(&dwProduct, &dwPublic, &dwPrivate, szD2CdKey); //// //cout << endl << "RUNCDKEYDECODE" << endl; //cout << "dwProduct: " << hex << dwProduct << endl; //cout << "dwPublic: " << hex << dwPublic << endl; //cout << "dwPrivate: " << hex << dwPrivate << endl; //cout << endl << endl; /* END OF CALL RUNCDKEYDECODE */ /* CALL HASHDATA FOR CDKEY1*/ DWORD dwHashBuffer[6]; DWORD dwOutBuffer[5]; // This is supossed to be the CDKey1 Data. dwHashBuffer[0] = ClientToken; // We got this with GetTickCount() dwHashBuffer[1] = r_SID_AUTH_INFO.Server_Token; // Bnet sent this in the last packet dwHashBuffer[2] = dwProduct; // We got this with RunCDKeyDecode dwHashBuffer[3] = dwPublic; // We got this with RunCDKeyDecode too dwHashBuffer[4] = 0; // 0... dwHashBuffer[5] = dwPrivate; // Also, we got this with RunCDKeyDecode HashData(24, dwOutBuffer, dwHashBuffer); /* END OF CALL HASHDATA */ /* DO THE SAME FOR CDKEY2 */ DWORD dwProduct2 = Key2Product; DWORD dwPrivate2 = 0; DWORD dwPublic2 = 0; RunCDkeyDecode(&dwProduct, &dwPublic, &dwPrivate, szLODCdKey); DWORD dwHashBuffer2[6]; DWORD dwOutBuffer2[5]; dwHashBuffer[0] = GetTickCount(); dwHashBuffer[1] = r_SID_AUTH_INFO.Server_Token; dwHashBuffer[2] = dwProduct2; dwHashBuffer[3] = dwPublic2; dwHashBuffer[4] = 0; dwHashBuffer[5] = dwPrivate2; HashData(24, dwOutBuffer2, dwHashBuffer2); /* ~~ */ /* WRITE EVERYTHING IN THE PACKET */ // Info about csFifthPacket class: // The packet itself is csFifthPacket.packet and it is a // dynamically allocated BYTE array. // The position the next function will write to is stored at // nByte2Write and is increased automatically with each WriteX function // call. // WriteByte writes a byte to packet. (csFifthPacket.packet). // WriteWord and WriteDWord take 2 arguments. The first one tells // if it has to convert the Word or DWord given to Little Endian before // putting it in packet or not. If the first argument is 0, it will // convert the DWORD given to Little Endian, and then put it in the // packet. If it is 1, it will put it in the packet directly without // converting it. // WriteString() just writes a string and a null terminator to packet. csFifthPacket.WriteByte(0xFF); csFifthPacket.WriteByte(0x51); // Gotta solve this bug some day... csFifthPacket.WriteWord(0, 134); csFifthPacket.WriteDWord(0, ClientToken); csFifthPacket.WriteDWord(0, ExeVersion); // From CheckRevision() csFifthPacket.WriteDWord(0, ExeHash); // From CheckRevision() csFifthPacket.WriteDWord(0, CDKeyNumber); csFifthPacket.WriteDWord(0, UsingOfKeys); csFifthPacket.WriteDWord(0, Key1Len); csFifthPacket.WriteDWord(1, Key1Product); csFifthPacket.WriteDWord(1, dwPublic); csFifthPacket.WriteDWord(0, Key1Unknown); csFifthPacket.WriteDWord(1,dwOutBuffer[0]); csFifthPacket.WriteDWord(1,dwOutBuffer[1]); csFifthPacket.WriteDWord(1,dwOutBuffer[2]); csFifthPacket.WriteDWord(1,dwOutBuffer[3]); csFifthPacket.WriteDWord(1,dwOutBuffer[4]); csFifthPacket.WriteDWord(0, Key2Len); csFifthPacket.WriteDWord(1, Key2Product); csFifthPacket.WriteDWord(1, dwPrivate); csFifthPacket.WriteDWord(0, Key2Unknown); csFifthPacket.WriteDWord(1,dwOutBuffer2[0]); csFifthPacket.WriteDWord(1,dwOutBuffer2[1]); csFifthPacket.WriteDWord(1,dwOutBuffer2[2]); csFifthPacket.WriteDWord(1,dwOutBuffer2[3]); csFifthPacket.WriteDWord(1,dwOutBuffer2[4]); csFifthPacket.WriteString(CRExeInfo); // From CheckRevision() csFifthPacket.WriteString(CDKeyOwner); // These two sentences set the packet size word of packet to the packet // len. (Previously it was 136 instead 134). /* END OF WRITE EVERYTHING AT THE PACKET */ /* SEND csFifthPacket.packet TO BATTLE.NET */ n = SendPacket(csFifthPacket.packet, csFifthPacket.GetPacketLen()); if(n == -1) error(10, "SendPacket"); else cout << "Packet 0x51 Sent " << "Bytes: " << n << endl; /* END OF SEND PACKET TO BATTLE.NET */ return n; } [/code] Another functions used: [code] void HashData(DWORD length, LPVOID outbuf, LPVOID tohash) { DWORD len = length; __asm { push ecx push edx mov ecx, outbuf mov edx, tohash push len call HashFunction pop edx pop ecx } } void RunCDkeyDecode(DWORD *Product, DWORD *CDKeyVal1, DWORD *CDKeyVal2, const char *CDKey) { __asm { push ecx push edx mov ecx, CDKey mov edx, Product push CDKeyVal2 push CDKeyVal1 call DecodeCDKeyFunction pop edx pop ecx } } [/code] | July 26, 2004, 12:12 AM |
kamakazie | Hmm, everything looks right. Seems like the only problem could be with your files. Make sure you're not using modified files (Game.exe, BnClient.dll, D2Client.dll). And dwVersion should be 0x1000A00 but in your packet logs it's not. Check those things. | July 26, 2004, 12:42 AM |
z-stars | [quote author=dxoigmn link=board=17;threadid=7821;start=60#msg72548 date=1090802549] Hmm, everything looks right. Seems like the only problem could be with your files. Make sure you're not using modified files (Game.exe, BnClient.dll, D2Client.dll). And dwVersion should be 0x1000A00 but in your packet logs it's not. Check those things. [/quote] I think they aren't modified, after all, they are the files diablo II uses to log to bnet so if they work for it they should work for my bot. About the version, I dont understand why it is "00 0A 00 01" instead "00 0A 00 00" like the d2 client, I'll try to solve that, if anyone knows why could this be this, post plz. | July 26, 2004, 1:19 AM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=60#msg72554 date=1090804764] I think they aren't modified, after all, they are the files diablo II uses to log to bnet so if they work for it they should work for my bot. About the version, I dont understand why it is "00 0A 00 01" instead "00 0A 00 00" like the d2 client, I'll try to solve that, if anyone knows why could this be this, post plz. [/quote] Are you using the expansion files or classic files? | July 26, 2004, 1:25 AM |
z-stars | Aparently, CheckRevision() puts a wrong value into dwVersion. I have tried changing it to the right value, but it still gives me "Invalid Version". But if CheckRevision() puts wrong values in dwVersion, maybe it puts wrong values in the ExeHash too. Could this be caused by the arguments I pass to CheckRevision(), or by the CheckRevision() function itself? | July 26, 2004, 1:28 AM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=60#msg72555 date=1090805123] [quote author=z-stars link=board=17;threadid=7821;start=60#msg72554 date=1090804764] I think they aren't modified, after all, they are the files diablo II uses to log to bnet so if they work for it they should work for my bot. About the version, I dont understand why it is "00 0A 00 01" instead "00 0A 00 00" like the d2 client, I'll try to solve that, if anyone knows why could this be this, post plz. [/quote] Are you using the expansion files or classic files? [/quote] Uhm what do you mean? I've LOD installed if that's what u mean. I'm passing as arguments to CheckRevision() the path to the files d2Client, BnClient, and game.exe. (They are in D2's folder). | July 26, 2004, 1:29 AM |
z-stars | I found another thing that doesn't work :( This is the bnetdoc description of 0x51 packet: [code] (DWORD) Client Token (DWORD) EXE Version (DWORD) EXE Hash (DWORD) Number of keys in this packet (BOOLEAN) Using Spawn (32-bit) For Each Key: (DWORD) Key Length (DWORD) Product (DWORD) CDKEY Value 1 (DWORD) Unknown (0) (DWORD[5]) Hashed Key Data (STRING) Exe Information (STRING) CD Key owner name [/code] Each key, has a "CDKEY Value 1" dword. In the logs D2Client to Battle.net, these values are always the same. (The value 1 of the first cd key is different from the value 1 of the second cd key, but when I log to battle.net again, they never change). But my program sends a different "CDKEY Value 1" value each time it tries to log to bnet, so I think there is some problem here... | July 26, 2004, 1:44 AM |
z-stars | I go to sleep, if anyone finds out anything post it plz Thx everyone for the help BTW. | July 26, 2004, 2:00 AM |
kamakazie | Here is what I would do. Packet log the real client then in your client emulate that packet log exactly without connecting to battle.net. That means fixing the values of the client salt, server salt, the equation string, the mpq file. Make sure you use the same cdkeys as your real client too. This should save you a load of headaches when you start debugging your cdkey stuff because battle.net will start ip banning you for several minutes. Alternatively, you could create a test server using Arta's TestBNCS and connect locally. | July 26, 2004, 2:02 AM |
UserLoser. | dwPublic shouldn't be changing at all, and it doesn't look like the code you posted is modifying it in any way. I'd blame your WriteDWord/outgoing packet buffer class. Try printf("%08x\n", dwPublic); or something to see if it really is changing. (which it shouldn't) | July 26, 2004, 2:22 AM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=75#msg72571 date=1090808521] dwPublic shouldn't be changing at all, and it doesn't look like the code you posted is modifying it in any way. I'd blame your WriteDWord/outgoing packet buffer class. Try printf("%08x\n", dwPublic); or something to see if it really is changing. (which it shouldn't) [/quote] Sorry you are right dwPublic doesn't change, I was using an old log to compare or something, but the dwPublic the program sends is different than the one d2 client sends. | July 26, 2004, 11:36 AM |
z-stars | [quote author=dxoigmn link=board=17;threadid=7821;start=60#msg72566 date=1090807360] Here is what I would do. Packet log the real client then in your client emulate that packet log exactly without connecting to battle.net. That means fixing the values of the client salt, server salt, the equation string, the mpq file. Make sure you use the same cdkeys as your real client too. This should save you a load of headaches when you start debugging your cdkey stuff because battle.net will start ip banning you for several minutes. Alternatively, you could create a test server using Arta's TestBNCS and connect locally. [/quote] I'm not sure to understand that, I can't copy exactly a packet log because a lot of values change. | July 26, 2004, 11:57 AM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=75#msg72642 date=1090841799] [quote author=UserLoser. link=board=17;threadid=7821;start=75#msg72571 date=1090808521] dwPublic shouldn't be changing at all, and it doesn't look like the code you posted is modifying it in any way. I'd blame your WriteDWord/outgoing packet buffer class. Try printf("%08x\n", dwPublic); or something to see if it really is changing. (which it shouldn't) [/quote] Sorry you are right dwPublic doesn't change, I was using an old log to compare or something, but the dwPublic the program sends is different than the one d2 client sends. [/quote] Did you install the game with the same CDKeys that you're using now? | July 26, 2004, 4:31 PM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=75#msg72672 date=1090859480] [quote author=z-stars link=board=17;threadid=7821;start=75#msg72642 date=1090841799] [quote author=UserLoser. link=board=17;threadid=7821;start=75#msg72571 date=1090808521] dwPublic shouldn't be changing at all, and it doesn't look like the code you posted is modifying it in any way. I'd blame your WriteDWord/outgoing packet buffer class. Try printf("%08x\n", dwPublic); or something to see if it really is changing. (which it shouldn't) [/quote] Sorry you are right dwPublic doesn't change, I was using an old log to compare or something, but the dwPublic the program sends is different than the one d2 client sends. [/quote] Did you install the game with the same CDKeys that you're using now? [/quote] yes | July 26, 2004, 5:41 PM |
z-stars | Mhh dunno what I have done that now it doesn't remove the '1' from dwVersion, but BNet keeps sending me that Invalid Version packet... I dont know what to do, should I post the full source? | July 26, 2004, 7:29 PM |
z-stars | I have put together some logs... The first two logs are from the real d2 lod client, the other 2 logs are from my program. [code] FF 51 86 00 header ED E7 B4 11 client token 00 0A 00 01 exe version D5 AD 18 D6 exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key 1length 06 00 00 00 cdkey1 product D9 15 0D 00 cdkey1 value1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 value1 00 00 00 00 k2 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 35 37 00 4D 65 00 57.Me. __________________________________________________________________________ FF 51 86 00 header 1B 13 43 DF client token 00 0A 00 01 exe version DF F5 4A EE exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key 1 length 06 00 00 00 cdkey1 product D9 15 0D 00 cdkey1 value1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 value1 00 00 00 00 k1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 35 37 00 4D 65 00 57.Me. ____________________________________________________________________________________________________ FF 51 86 00 header... D9 DA 69 00 client token 00 0A 00 01 exe version AF 3C 9C 00 exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key 1 length 00 00 00 00 key 1 product 00 12 F9 FB cdkey1 value1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 00 00 00 00 k2 product 00 C3 9C E9 key2 value1 00 00 00 00 key2 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 30 35 2F 31 36 2F 30 Game.exe 05/16/0 34 20 32 31 3A 33 31 3A 33 36 20 31 31 39 38 38 4 21:31:36 11988 35 37 00 4D 65 00 57.Me. ___________________________________________________________________________________ FF 51 86 00 header 12 82 E0 01 client token 00 0A 00 01 exe version 56 4A 75 70 exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 k1 len 00 00 00 00 k1 product 00 12 F9 FB k1 value1 00 00 00 00 k1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 00 00 00 00 k2 product D8 C3 9C E9 k2 value1 00 00 00 00 k2 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 30 35 2F 31 36 2F 30 Game.exe 05/16/0 34 20 32 31 3A 33 31 3A 33 36 20 31 31 39 38 38 4 21:31:36 11988 35 37 00 4D 65 00 57.Me. [/code] Differences: -The "CDKey Number 1" of each cd key. -The last string. D2 client sends "Game.exe 10/13/04 21:31:36 11988" while for some reason my program sends "Game.exe 05/16/04 21:31:36 11988" -Also, the product of my program is 00 00 00 00. I thought RunCDKeyDecode wrote the product in dwProduct, do I have to write the product id in a variable myself? | July 26, 2004, 8:33 PM |
UserLoser. | 10 00 00 00 key 1length 06 00 00 00 cdkey1 product D9 15 0D 00 cdkey1 value1 00 00 00 00 key1 unknown 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 value1 00 00 00 00 k2 unknown 10 00 00 00 key 1 length 06 00 00 00 cdkey1 product D9 15 0D 00 cdkey1 value1 00 00 00 00 key1 unknown 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 value1 00 00 00 00 k1 unknown [hr] 10 00 00 00 key 1 length 00 00 00 00 key 1 product 00 12 F9 FB cdkey1 value1 00 00 00 00 key1 unknown 10 00 00 00 k2 len 00 00 00 00 k2 product 00 C3 9C E9 key2 value1 00 00 00 00 key2 unknown 10 00 00 00 k1 len 00 00 00 00 k1 product 00 12 F9 FB k1 value1 00 00 00 00 k1 unknown 10 00 00 00 k2 len 00 00 00 00 k2 product D8 C3 9C E9 k2 value1 00 00 00 00 k2 unknown Your classic CDKeys appear to be the same, but the expansion ones are not. The way you're inserting them in your outgoing packetbuffer seems to be a problem. They should be inserted without modification to them. Your not giving a product id, which comes from RunDecodeCDKey. If you're using the same CDkeys, everything on the top should be identical to the bottom two. If i'm understanding your WriteDword function, the first parameter should be a 0 for all this | July 26, 2004, 8:50 PM |
z-stars | I found an error in my code (In RuncdKeyDecode, I used some first cd key vars with the second cd key), I have fixed it I think. (But it still gives the wrong version packet). The new code: [code] // S SID_AUTH_CHECK // This function is supossed to build and send the fifth packet (0x51) // At the start of this function, csFifthPacket.packet (the packet 0x51 that // this function sends to battle.net at the end) is EMPTY. int LTBNFifthPacket() { /* Globals... */ BEFORE_SEND; int n = 0; char * CDKeyOwner = "Me"; //DWORD Key1Product = 0x06; //DWORD Key2Product = 0x0A; /* End of Globals */ /* First, load Battle.snp to do the hashing for us */ HMODULE battlesnp; battlesnp = LoadLibrary("Battle.snp"); if(!battlesnp) cout << "Couldn't load battle.snp" << endl; /* Battlesnp Loaded */ /* CHECK REVISION */ /* Call CheckRevision() to get the some of the values to send */ /* The values we get are: ExeHash and Version (dwExeHash, and dwVersion) */ /* Also, we get an ExeInfo string. (To CRExeInfo). */ DWORD dwVersion = 0; DWORD dwChecksum = 0; char CRExeInfo[5000]; memset(CRExeInfo, 0, 5000); //strcpy(CRExeInfo, ExeInfo); BOOL bCheckRevision = 0; bCheckRevision = CheckRevision("C:\\Archivos de programa\\Diablo II\\Game.exe", "C:\\Archivos de programa\\Diablo II\\storm.dll", "C:\\Archivos de programa\\Diablo II\\BNClient.dll", r_SID_AUTH_INFO.ValueString, &dwVersion, &dwChecksum, CRExeInfo, r_SID_AUTH_INFO.IX86ver_filename); if(bCheckRevision == FALSE) { cout << "ERROR: Check Revision() Failed" << endl; system("pause"); } else cout << "CheckRevision() Success" << endl; /*printf("dwVersion: %x || dwChecksum: %x || ExeInfo: %s", dwVersion, dwChecksum, CRExeInfo);*/ /* END OF CHECK REVISION */ cout << "dwVersion: " << hex << dwVersion << endl; /* VARIABLES TO PUT IN THE PACKET DECLARATIONS */ int x = 0; BYTE FirstByte = 0xFF; // It's always 0xFF BYTE PacketID = 0x51; // PacketId's 0x51 WORD PacketLen = 132 + strlen(CDKeyOwner); // Packet Length is 132 + ownerlen DWORD ClientToken = GetTickCount(); // I use GetTickCount() to get that DWORD ExeVersion = dwVersion; // From CheckRevision() DWORD ExeHash = dwChecksum; // From CheckRevision() DWORD CDKeyNumber = 2; // 1 D2 cd key, 1 Lod cd key. DWORD UsingOfKeys = 0; // 0 DWORD Key1Len = 0x10; // Length of D2 CdKey: 16 (0x10) DWORD Key1Num1 = x; // This is supossed to be the First Number of the first cd key. // I'm not sure how to get it. DWORD Key1Unknown = 0; // Unknown(0) DWORD Key2Len = 0x10; // Same... DWORD Key2Num1 = x; // Same... DWORD Key2Unknown = 0; // Unknown (0) /* END OF VARIABLES TO PUT IN THE PACKET DECLARATIONS */ /* CALL RUNCDKEYDECODE */ DWORD dwKey1Product = 0; DWORD dwKey1Private = 0; DWORD dwKey1Public = 0; RunCDkeyDecode(&dwKey1Product, &dwKey1Public, &dwKey1Private, szD2CdKey); //// //cout << endl << "RUNCDKEYDECODE" << endl; //cout << "dwProduct: " << hex << dwProduct << endl; //cout << "dwPublic: " << hex << dwPublic << endl; //cout << "dwPrivate: " << hex << dwPrivate << endl; //cout << endl << endl; /* END OF CALL RUNCDKEYDECODE */ /* CALL HASHDATA FOR CDKEY1*/ DWORD dwKey1HashBuffer[6]; DWORD dwKey1OutBuffer[5]; // This is supossed to be the CDKey1 Data. dwKey1HashBuffer[0] = ClientToken; // We got this with GetTickCount() dwKey1HashBuffer[1] = r_SID_AUTH_INFO.Server_Token; // Bnet sent this in the last packet dwKey1HashBuffer[2] = dwKey1Product; // We got this with RunCDKeyDecode dwKey1HashBuffer[3] = dwKey1Public; // We got this with RunCDKeyDecode too dwKey1HashBuffer[4] = 0; // 0... dwKey1HashBuffer[5] = dwKey1Private; // Also, we got this with RunCDKeyDecode HashData(24, dwKey1OutBuffer, dwKey1HashBuffer); /* END OF CALL HASHDATA */ /* DO THE SAME FOR CDKEY2 */ DWORD dwKey2Product = 0; DWORD dwKey2Private = 0; DWORD dwKey2Public = 0; RunCDkeyDecode(&dwKey2Product, &dwKey2Public, &dwKey2Private, szLODCdKey); DWORD dwKey2HashBuffer[6]; DWORD dwKey2OutBuffer[5]; dwKey2HashBuffer[0] = GetTickCount(); dwKey2HashBuffer[1] = r_SID_AUTH_INFO.Server_Token; dwKey2HashBuffer[2] = dwKey2Product; dwKey2HashBuffer[3] = dwKey2Public; dwKey2HashBuffer[4] = 0; dwKey2HashBuffer[5] = dwKey2Private; HashData(24, dwKey2OutBuffer, dwKey2HashBuffer); /* ~~ */ /* WRITE EVERYTHING IN THE PACKET */ // Info about csFifthPacket class: // The packet itself is csFifthPacket.packet and it is a // dynamically allocated BYTE array. // The position the next function will write to is stored at // nByte2Write and is increased automatically with each WriteX function // call. // WriteByte writes a byte to packet. (csFifthPacket.packet). // WriteWord and WriteDWord take 2 arguments. The first one tells // if it has to convert the Word or DWord given to Little Endian before // putting it in packet or not. If the first argument is 0, it will // convert the DWORD given to Little Endian, and then put it in the // packet. If it is 1, it will put it in the packet directly without // converting it. // WriteString() just writes a string and a null terminator to packet. csFifthPacket.WriteByte(0xFF); csFifthPacket.WriteByte(0x51); // Gotta solve this bug some day... csFifthPacket.WriteWord(0, 132 + strlen(CDKeyOwner)); csFifthPacket.WriteDWord(0, ClientToken); cout << "dwVersion: " << hex << dwVersion << endl; cout << "ExeVersion: " << hex << ExeVersion << endl; cout << "hdwVersion: " << hex << htonl(dwVersion) << endl; csFifthPacket.WriteDWord(0, ExeVersion); // From CheckRevision() csFifthPacket.WriteDWord(0, ExeHash); // From CheckRevision() csFifthPacket.WriteDWord(0, CDKeyNumber); csFifthPacket.WriteDWord(0, UsingOfKeys); cout << "dwKey1Public: " << hex << dwKey1Public << endl; cout << "dwKey1Private: " << hex << dwKey1Private << endl; cout << "dwKey2Public: " << hex << dwKey2Public << endl; cout << "dwKey2Private: " << hex << dwKey2Private << endl; csFifthPacket.WriteDWord(0, Key1Len); cout << "dwKey1Product: " << hex << dwKey1Product << endl; cout << "dwKey2Product: " << hex << dwKey2Product << endl; // cout << "Key1Product: " << hex << Key1Product << endl; // cout << "Key2Product: " << hex << Key2Product << endl; csFifthPacket.WriteDWord(1, dwKey1Product); csFifthPacket.WriteDWord(1, dwKey1Public); //dwPu csFifthPacket.WriteDWord(0, Key1Unknown); csFifthPacket.WriteDWord(1,dwKey1OutBuffer[0]); csFifthPacket.WriteDWord(1,dwKey1OutBuffer[1]); csFifthPacket.WriteDWord(1,dwKey1OutBuffer[2]); csFifthPacket.WriteDWord(1,dwKey1OutBuffer[3]); csFifthPacket.WriteDWord(1,dwKey1OutBuffer[4]); csFifthPacket.WriteDWord(0, Key2Len); csFifthPacket.WriteDWord(1, dwKey2Product); csFifthPacket.WriteDWord(1, dwKey2Private); //dwPr csFifthPacket.WriteDWord(0, Key2Unknown); csFifthPacket.WriteDWord(1,dwKey2OutBuffer[0]); csFifthPacket.WriteDWord(1,dwKey2OutBuffer[1]); csFifthPacket.WriteDWord(1,dwKey2OutBuffer[2]); csFifthPacket.WriteDWord(1,dwKey2OutBuffer[3]); csFifthPacket.WriteDWord(1,dwKey2OutBuffer[4]); csFifthPacket.WriteString(CRExeInfo); // From CheckRevision() csFifthPacket.WriteString(CDKeyOwner); // These two sentences set the packet size word of packet to the packet // len. (Previously it was 136 instead 134). /* END OF WRITE EVERYTHING AT THE PACKET */ /* SEND csFifthPacket.packet TO BATTLE.NET */ n = SendPacket(csFifthPacket.packet, csFifthPacket.GetPacketLen()); if(n == -1) error(10, "SendPacket"); else cout << "Packet 0x51 Sent " << "Bytes: " << n << endl; /* END OF SEND PACKET TO BATTLE.NET */ return n; } void HashData(DWORD length, LPVOID outbuf, LPVOID tohash) { DWORD len = length; __asm { push ecx push edx mov ecx, outbuf mov edx, tohash push len call HashFunction pop edx pop ecx } } void RunCDkeyDecode(DWORD *Product, DWORD *CDKeyVal1, DWORD *CDKeyVal2, const char *CDKey) { __asm { push ecx push edx mov ecx, CDKey mov edx, Product push CDKeyVal2 push CDKeyVal1 call DecodeCDKeyFunction pop edx pop ecx } } LTBNSixthPacket() { int n = 0; BEFORE_RECV; n = RecvPacket(crSixthPacket.packet, 50); if(n == -1) error(9, "RecvPacket"); else cout << "Packet 6 Recv. Bytes: " << n << endl; memset(r_SID_AUTH_CHECK.AdditionalInformation, 0, sizeof(r_SID_AUTH_CHECK.AdditionalInformation)); crSixthPacket.ReadByte(&r_SID_AUTH_CHECK.IntegrityCheck); crSixthPacket.ReadByte(&r_SID_AUTH_CHECK.PacketID); crSixthPacket.ReadWord(0, &r_SID_AUTH_CHECK.PacketLen); // Im converting this dword to big endian before parsing it. crSixthPacket.ReadWord(0, &r_SID_AUTH_CHECK.Result1); crSixthPacket.ReadWord(0, &r_SID_AUTH_CHECK.Result2); crSixthPacket.ReadString(r_SID_AUTH_CHECK.AdditionalInformation); cout << endl; switch(r_SID_AUTH_CHECK.Result1) { case 0x000: cout << "Passed Challenge" << endl; break; case 0x100: cout << "Old Game Version" << endl; break; case 0x101: cout << "Invalid Version" << endl; break; case 0x200: cout << "Invalid CDKey" << endl; break; case 0x201: cout << "CDKey in use" << endl; break; case 0x202: cout << "Banned CDKey" << endl; break; case 0x203: cout << "Wrong Product" << endl; break; default: cout << "Undefined" << endl; } switch(r_SID_AUTH_CHECK.Result2) { case 0x200: cout << "Invalid CDKey" << endl; break; case 0x201: cout << "CDKey in use" << endl; break; case 0x202: cout << "Banned CDKey" << endl; break; case 0x203: cout << "Wrong Product" << endl; break; default: cout << "Undefined" << endl; } cout << "ADDITIONAL INFORMATION: " << r_SID_AUTH_CHECK.AdditionalInformation << endl; crSixthPacket.dbgShowPacket(); return n; } [/code] I'll get another packet log to see how it works now. About the first argument of WriteDWord(), if it is 0, it thinks the number is Big Endian, so it converts it to Little Endian to put it in the packet, if it is 1, it doesn't modify it. The new packet log: The first 2 logs are from the real d2 LOD client, the last log is from my program [code] FF 51 86 00 header ED E7 B4 11 client token 00 0A 00 01 exe version D5 AD 18 D6 exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key 1length 06 00 00 00 cdkey1 product D9 15 0D 00 cdkey1 value1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 value1 00 00 00 00 k2 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 35 37 00 4D 65 00 57.Me. __________________________________________________________________________ FF 51 86 00 header 1B 13 43 DF client token 00 0A 00 01 exe version DF F5 4A EE exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key 1 length 06 00 00 00 cdkey1 product D9 15 0D 00 cdkey1 value1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 value1 00 00 00 00 k1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 35 37 00 4D 65 00 57.Me. ____________________________________________________________________________________________________ FF 51 86 00 header 34 8F 63 02 client token 00 0A 00 01 exe version 76 59 2C B2 exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 k1 len 00 00 00 06 k1 product 00 0D 15 D9 k1 val1 00 00 00 00 k1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 00 00 00 0A k2 product D8 C3 9C E9 k2 val1 00 00 00 00 k2 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 30 35 2F 31 36 2F 30 34 20 32 31 3A 33 31 3A 33 36 20 31 31 39 38 38 4 21:31:36 11988 35 37 00 4D 65 00 57.Me. [/code] EDIT: Products are given in Big Endian, changed the code to convert em to Little Endian before putting em in the packet, so now the products should be well. | July 26, 2004, 10:18 PM |
z-stars | Mhh it seems that Decode Cd Key function gives everything in Big Endian, but I dont know why the second cd key doesn't match, I have looked the cd key with Onlyer's Show CdKey program. (erm it was Onlyer's I think I'm not sure now) EDIT: BTW, here is my WriteDWord function: [code] int BNETsPacket::WriteDWord(int mode, DWORD dword) { BYTE buf[5]; memset(buf, 0, sizeof(buf)); BYTE* bFourBytes = reinterpret_cast<BYTE*>(&dword); buf[3] = (bFourBytes[0]); buf[2] = (bFourBytes[1]); buf[1] = (bFourBytes[2]); buf[0] = (bFourBytes[3]); if(mode == 0) { WriteDWord(0, buf); } else if(mode == 1) { WriteDWord(1, buf); } return 0; } [/code] [code] int BNETsPacket::WriteDWord(int mode, BYTE * bytes) { if(bAutoSize == true) AllocBytes(4); if(mode == P_WM_BE) { packet[nByte2Write] = bytes[3]; packet[nByte2Write+1] = bytes[2]; packet[nByte2Write+2] = bytes[1]; packet[nByte2Write+3] = bytes[0]; } else if(mode == P_WM_LE) { packet[nByte2Write] = bytes[0]; packet[nByte2Write+1] = bytes[1]; packet[nByte2Write+2] = bytes[2]; packet[nByte2Write+3] = bytes[3]; } nByte2Write += 4; nPacketLen += 4; return 0; } [/code] EDIT: [code] #define P_WM_LE 1 #define P_WM_BE 0 [/code] | July 26, 2004, 10:34 PM |
OnlyMeat | Why dont you just use memcpy ? The amount of asm that will be generated from that code is just silly :( Using memcpy will translate to about 2 asm lines! | July 26, 2004, 11:20 PM |
z-stars | [quote author=OnlyMeat link=board=17;threadid=7821;start=75#msg72740 date=1090884008] Why dont you just use memcpy ? The amount of asm that will be generated from that code is just silly :( Using memcpy will translate to about 2 asm lines! [/quote] I dont think it would translate to 2 asm lines, but how would I use memcpy to do the same? | July 26, 2004, 11:53 PM |
UserLoser. | Insert the cdkey values as they are. Don't swap the bytes around. Little endian not big. | July 27, 2004, 12:03 AM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=75#msg72751 date=1090886599] Insert the cdkey values as they are. Don't swap the bytes around. Little endian not big. [/quote] I'm not swapping em, if mode == 0 they are given in Little Endian so it doesn't swap em. But should I swap the values returned by cdKeydecode? | July 27, 2004, 12:14 AM |
z-stars | For some reason my program's Key2 Value1 is different from the real Key2 Value 1 that my Diablo II client sends to battle.net. That's strange because I am pretty sure that the cdkey is the same (I have copy&pasted it with a ShowCDKey program) Another problem is that I don't know where CheckRevision() gets its exe info from, because the real d2 client gets different exe info. I'm passing as arguments the paths to: Game.exe, storm.dll, BnClient.dll. First 2 logs are the real client, the other logs are from my prog. [code] FF 51 86 00 header ED E7 B4 11 client token 00 0A 00 01 exe version D5 AD 18 D6 exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key 1length 06 00 00 00 cdkey1 product D9 15 0D 00 cdkey1 value1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 value1 00 00 00 00 k2 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 35 37 00 4D 65 00 57.Me. __________________________________________________________________________ FF 51 86 00 header 1B 13 43 DF client token 00 0A 00 01 exe version DF F5 4A EE exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key 1 length 06 00 00 00 cdkey1 product D9 15 0D 00 cdkey1 value1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 value1 00 00 00 00 k1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 35 37 00 4D 65 00 57.Me. ____________________________________________________________________________________________________ ___________________________________________________________________________________ FF 51 86 00 header B4 BB C2 02 c token 00 0A 00 01 exe v. 4A 04 8A D9 exe hash 02 00 00 00 nKeys 00 00 00 00 using spawn 10 00 00 00 key 1 length 00 00 00 06 key 1 product 00 0D 15 D9 key value 1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 key 2 len 00 00 00 0A key 2 product D8 C3 9C E9 key 2 value 1 00 00 00 00 key 2 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 30 35 2F 31 36 2F 30 Game.exe 05/16/0 34 20 32 31 3A 33 31 3A 33 36 20 31 31 39 38 38 4 21:31:36 11988 35 37 00 4D 65 00 57.Me. __________________________________ FF 51 86 00 header... D9 DA 69 00 client token 00 0A 00 01 exe version AF 3C 9C 00 exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key 1 length 00 00 00 00 key 1 product 00 12 F9 FB cdkey1 value1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 00 00 00 00 k2 product 00 C3 9C E9 key2 value1 00 00 00 00 key2 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 30 35 2F 31 36 2F 30 Game.exe 05/16/0 34 20 32 31 3A 33 31 3A 33 36 20 31 31 39 38 38 4 21:31:36 11988 35 37 00 4D 65 00 57.Me. [/code] | July 27, 2004, 12:29 AM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=75#msg72753 date=1090887290] But should I swap the values returned by cdKeydecode? [/quote] No!! | July 27, 2004, 12:51 AM |
Maddox | [quote author=z-stars link=board=17;threadid=7821;start=75#msg72708 date=1090874011] -The last string. D2 client sends "Game.exe 10/13/04 21:31:36 11988" while for some reason my program sends "Game.exe 05/16/04 21:31:36 11988" [/quote] https://davnit.net/bnet/vL/phpbbs/index.php?board=17;action=display;threadid=6974 | July 27, 2004, 12:56 AM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=90#msg72757 date=1090889512] [quote author=z-stars link=board=17;threadid=7821;start=75#msg72753 date=1090887290] But should I swap the values returned by cdKeydecode? [/quote] No!! [/quote] But without swapping dwKey1Product and dwKey2Product they are wrong :( | July 27, 2004, 12:57 AM |
z-stars | [quote author=Maddox link=board=17;threadid=7821;start=90#msg72760 date=1090889803] [quote author=z-stars link=board=17;threadid=7821;start=75#msg72708 date=1090874011] -The last string. D2 client sends "Game.exe 10/13/04 21:31:36 11988" while for some reason my program sends "Game.exe 05/16/04 21:31:36 11988" [/quote] https://davnit.net/bnet/vL/phpbbs/index.php?board=17;action=display;threadid=6974 [/quote] Uhm how can I fix that? or is there another better CheckVersion() function? | July 27, 2004, 1:03 AM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=90#msg72761 date=1090889844] [quote author=UserLoser. link=board=17;threadid=7821;start=90#msg72757 date=1090889512] [quote author=z-stars link=board=17;threadid=7821;start=75#msg72753 date=1090887290] But should I swap the values returned by cdKeydecode? [/quote] No!! [/quote] But without swapping dwKey1Product and dwKey2Product they are wrong :( [/quote] Just use memcpy like someone else suggested.. | July 27, 2004, 1:05 AM |
z-stars | [quote author=UserLoser. link=board=17;threadid=7821;start=90#msg72765 date=1090890326] [quote author=z-stars link=board=17;threadid=7821;start=90#msg72761 date=1090889844] [quote author=UserLoser. link=board=17;threadid=7821;start=90#msg72757 date=1090889512] [quote author=z-stars link=board=17;threadid=7821;start=75#msg72753 date=1090887290] But should I swap the values returned by cdKeydecode? [/quote] No!! [/quote] But without swapping dwKey1Product and dwKey2Product they are wrong :( [/quote] Just use memcpy like someone else suggested.. [/quote] I dont mean that my WriteDWord function doesn't work, I mean that dwKey1Product is 0x00000006, when the real client sends 0x06000000. | July 27, 2004, 1:08 AM |
UserLoser. | [quote author=z-stars link=board=17;threadid=7821;start=90#msg72767 date=1090890537] [quote author=UserLoser. link=board=17;threadid=7821;start=90#msg72765 date=1090890326] [quote author=z-stars link=board=17;threadid=7821;start=90#msg72761 date=1090889844] [quote author=UserLoser. link=board=17;threadid=7821;start=90#msg72757 date=1090889512] [quote author=z-stars link=board=17;threadid=7821;start=75#msg72753 date=1090887290] But should I swap the values returned by cdKeydecode? [/quote] No!! [/quote] But without swapping dwKey1Product and dwKey2Product they are wrong :( [/quote] Just use memcpy like someone else suggested.. [/quote] I dont mean that my WriteDWord function doesn't work, I mean that dwKey1Product is 0x00000006, when the real client sends 0x06000000. [/quote] Yes. I know that. I never had to swap bytes before because i've always used RtlMoveMemory/memcpy. Sorry, your WriteDWord function threw me off a lot | July 27, 2004, 1:15 AM |
z-stars | Mhh, I don't use memcpy, do I have to swap all the hashes too then? EDIT: And about the second cd key value1, and the ExeInfo, anyone knows why are they different than the ones the real client sends? | July 27, 2004, 1:17 AM |
Myndfyr | Guys, my god, get on AIM or something. There have been ~15 posts to this thread in the last half-hour; I watched an entire page get added to this thread while I ate a small cookie-dough blizzard from Dairy Queen. | July 27, 2004, 1:20 AM |
z-stars | Uhm I discovered something... I made this program to see if CheckRevision() works well... [code] #include <windows.h> #include <iostream> #include <fstream> #include <string> #include <sys/stat.h> #include <windows.h> #include <process.h> #include <commctrl.h> #include <winreg.h> #include <conio.h> #include "CheckRevision.h" #include "D2Test.h" using namespace std; int test1(); int main(void) { test1(); return 0; } int test1() { int i = 0; DWORD RealChecksum = 0x901CF41B; DWORD CRVersion = 0; DWORD CRChecksum = 0; char ExeInfo[5000]; memset(ExeInfo, 0, 5000); BOOL bCheckRevision = 0; bCheckRevision = CheckRevision("C:\\Archivos de programa\\Diablo II\\Game.exe", "C:\\Archivos de programa\\Diablo II\\BnClient.dll", "C:\\Archivos de programa\\Diablo II\\D2Client.dll", "A=256586614 B=432471822 C=762285261 4 A=A^S B=B+C C=C-A A=A^B", &CRVersion, &CRChecksum, ExeInfo, "IX86ver0.mpq"); if(!bCheckRevision) { cout << "CheckRevision() failed" << endl; exit(0); } cout << "CRChecksum: " << hex << htonl(CRChecksum) << endl; cout << "CRVersion: " << hex << htonl(CRVersion) << endl; cout << ExeInfo << endl; return 0; } [/code] I logged a real connection between D2 and BNet, I got ValueString and MPQ Filename, and I called CheckRevision() with these to see if the exe hash it returns is the same than battle.net's... It wasn't the same. Then, I ran the program again to see if it was random or something. It isn't random. Then, I changed D2Client.dll for storm.dll, the checksum changed... (but still not Battle.net's). And then I swapped D2Client.dll with BNetClient.dll and the checksum changed too... so does anyone know the exact files and the exact order of them to pass to CheckRevision()? EDIT: Confirmed: -The files needed are: Game.exe, Bnclient.dll, and D2client.dll -They go in that order. dwVersion and dwExeHash are given in Big Endian, so they must be converted to Little Endian to put in the packet. -ExeInfo string is still different, but as dwVersion and dwExeHash work, I suposse I could safely just copy the string D2 sends into ExeInfo. EDIT: I go to sleep, it's v late here. | July 27, 2004, 1:52 AM |
z-stars | I did the changes to CheckVersion that I wrote in the post above, and the 0x51 received packet has changed! now it is the "invalid CdKey" packet. EDIT: uhm now it also IP bans me, is that normal? | July 27, 2004, 10:37 AM |
Maddox | [quote author=z-stars link=board=17;threadid=7821;start=90#msg72763 date=1090890199] [quote author=Maddox link=board=17;threadid=7821;start=90#msg72760 date=1090889803] [quote author=z-stars link=board=17;threadid=7821;start=75#msg72708 date=1090874011] -The last string. D2 client sends "Game.exe 10/13/04 21:31:36 11988" while for some reason my program sends "Game.exe 05/16/04 21:31:36 11988" [/quote] https://davnit.net/bnet/vL/phpbbs/index.php?board=17;action=display;threadid=6974 [/quote] Uhm how can I fix that? or is there another better CheckVersion() function? [/quote] I posted how to in that thread... | July 27, 2004, 10:42 AM |
z-stars | [quote author=Maddox link=board=17;threadid=7821;start=90#msg72861 date=1090924975] [quote author=z-stars link=board=17;threadid=7821;start=90#msg72763 date=1090890199] [quote author=Maddox link=board=17;threadid=7821;start=90#msg72760 date=1090889803] [quote author=z-stars link=board=17;threadid=7821;start=75#msg72708 date=1090874011] -The last string. D2 client sends "Game.exe 10/13/04 21:31:36 11988" while for some reason my program sends "Game.exe 05/16/04 21:31:36 11988" [/quote] https://davnit.net/bnet/vL/phpbbs/index.php?board=17;action=display;threadid=6974 [/quote] Uhm how can I fix that? or is there another better CheckVersion() function? [/quote] I posted how to in that thread... [/quote] CheckVersion() seems to work fine now, I managed to generate the same ExeHash than d2 client changing the order of the files (and using fixed values I got from the d2 packet log) | July 27, 2004, 10:48 AM |
z-stars | Is this code right? I want it to find out which is the cd key that is invalid, but in the second switch() it goes to the default. [code] LTBNSixthPacket() { int n = 0; BEFORE_RECV; n = RecvPacket(crSixthPacket.packet, 50); if(n == -1) error(9, "RecvPacket"); else cout << "Packet 6 Recv. Bytes: " << n << endl; memset(r_SID_AUTH_CHECK.AdditionalInformation, 0, sizeof(r_SID_AUTH_CHECK.AdditionalInformation)); crSixthPacket.ReadByte(&r_SID_AUTH_CHECK.IntegrityCheck); crSixthPacket.ReadByte(&r_SID_AUTH_CHECK.PacketID); crSixthPacket.ReadWord(0, &r_SID_AUTH_CHECK.PacketLen); // Im converting this dword to big endian before parsing it. crSixthPacket.ReadWord(0, &r_SID_AUTH_CHECK.Result1); crSixthPacket.ReadWord(0, &r_SID_AUTH_CHECK.Result2); crSixthPacket.ReadString(r_SID_AUTH_CHECK.AdditionalInformation); cout << endl; switch(r_SID_AUTH_CHECK.Result1) { case 0x000: cout << "Passed Challenge" << endl; break; case 0x100: cout << "Old Game Version" << endl; break; case 0x101: cout << "Invalid Version" << endl; break; case 0x200: cout << "Invalid CDKey" << endl; break; case 0x201: cout << "CDKey in use" << endl; break; case 0x202: cout << "Banned CDKey" << endl; break; case 0x203: cout << "Wrong Product" << endl; break; default: cout << "Undefined" << endl; } switch(r_SID_AUTH_CHECK.Result2) { case 0x200: cout << "Invalid CDKey2" << endl; break; case 0x201: cout << "CDKey in use2" << endl; break; case 0x202: cout << "Banned CDKey2" << endl; break; case 0x203: cout << "Wrong Product2" << endl; break; default: cout << "Undefined" << endl; } cout << "ADDITIONAL INFORMATION: " << r_SID_AUTH_CHECK.AdditionalInformation << endl; crSixthPacket.dbgShowPacket(); return n; } [/code] | July 27, 2004, 12:22 PM |
z-stars | I have fixed the CDKey2 Value1 error :), but battle.net still sends me the "Invalid CD-Key" packet and it still ip bans me. (And it ip bans me for a lot of time) The new compare log: the 2 first logs are from real d2 client, the last log is from my prog. They seem to be identical... (Except the hashes and the client token of course)... [code] FF 51 86 00 header ED E7 B4 11 client token 00 0A 00 01 exe version D5 AD 18 D6 exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key 1length 06 00 00 00 cdkey1 product D9 15 0D 00 cdkey1 value1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 value1 00 00 00 00 k2 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 35 37 00 4D 65 00 57.Me. __________________________________________________________________________ FF 51 86 00 header 1B 13 43 DF client token 00 0A 00 01 exe version DF F5 4A EE exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key 1 length 06 00 00 00 cdkey1 product D9 15 0D 00 cdkey1 value1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 value1 00 00 00 00 k1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 35 37 00 4D 65 00 57.Me. ____________________________________________________________________________________________________ ___________________________________________________________________________________ FF 51 86 00 header 58 01 3F 01 client token 00 0A 00 01 exe version 5C D5 B3 27 exe hash 02 00 00 00 keys num 00 00 00 00 using spawn 10 00 00 00 key1 len 06 00 00 00 key1 product D9 15 0D 00 key1 val1 00 00 00 00 key1 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY1 HASHED DATA xx xx xx xx xx xx xx xx 10 00 00 00 k2 len 0A 00 00 00 k2 product FB F9 12 00 k2 val1 00 00 00 00 k2 unknown xx xx xx xx xx xx xx xx xx xx xx xx KEY2 HASHED DATA xx xx xx xx xx xx xx xx 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 35 37 00 4D 65 00 57.Me. [/code] The full new packet log of my program... [code] 1 Hide Hide 1 Send 0000 01 . 2 Hide Hide 50 Send 0000 FF 50 32 00 00 00 00 00 36 38 58 49 50 58 32 44 .P2.....68XIPX2D 0010 0A 00 00 00 53 45 73 65 50 23 6B 1D 88 FF FF FF ....SEseP#k..... 0020 0A 0C 00 00 0A 0C 00 00 45 53 50 00 53 70 61 69 ........ESP.Spai 0030 6E 00 n. 3 Hide Hide 8 Recv 0000 FF 25 08 00 98 F5 BB 67 .%.....g 4 Hide Hide 100 Recv 0000 FF 50 64 00 00 00 00 00 01 0C F9 CB 37 38 16 00 .Pd.........78.. 0010 00 EC D4 78 91 E7 C3 01 49 58 38 36 76 65 72 32 ...x....IX86ver2 0020 2E 6D 70 71 00 41 3D 31 30 35 34 37 39 37 38 32 .mpq.A=105479782 0030 39 20 42 3D 39 31 36 35 37 36 31 31 39 20 43 3D 9 B=916576119 C= 0040 33 38 33 34 32 37 34 31 34 20 34 20 41 3D 41 5E 383427414 4 A=A^ 0050 53 20 42 3D 42 2D 43 20 43 3D 43 5E 41 20 41 3D S B=B-C C=C^A A= 0060 41 2B 42 00 A+B. 5 Hide Hide 134 Send 0000 FF 51 86 00 58 01 3F 01 00 0A 00 01 5C D5 B3 27 .Q..X.?.....\..' 0010 02 00 00 00 00 00 00 00 10 00 00 00 06 00 00 00 ................ 0020 D9 15 0D 00 00 00 00 00 xx xx xx xx xx xx xx xx ................ 0030 xx xx xx xx xx xx xx xx xx xx xx xx 10 00 00 00 ..7...H......... 0040 0A 00 00 00 FB F9 12 00 00 00 00 00 xx xx xx xx ............MUjt 0050 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx lc.D........'NJQ 0060 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 0070 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 0080 35 37 00 4D 65 00 57.Me. 6 Hide Hide 9 Recv 0000 FF 51 09 00 00 02 00 00 00 .Q....... [/code] | July 27, 2004, 4:13 PM |
z-stars | I don't understand, now that I send a *right* exe hash, battle.net answers with a "0x51 Invalid CD Key" packet, and bans me for 30 to 60 minutes, but when I send a *wrong* exe hash, bnet just answers with a 0x51 Invalid Version packet and doesn't ban me. And now, I don't know what could be wrong to get that "Invalid CD-Key" response. Everything "static" is the same than the real client sends, also, I have tested the CheckRevision() function with fixed values and it outputs the same ExeHash than the real lod client does. Also, I have solved the CdKey2 Value 1 error I had yesterday, I assigned dwPrivate2 to it instead assigning dwPublic2... So, does anyone know what could be wrong plz? (And btw, why does bnet ban me for so long when I send it the right exe hash?) The only 0x51 values that aren't static that I haven't been able to test are the client token, some RunCDKeyDecode() values (like dwPrivates) and the Hashed CD-Keys datas, so maybe the error is something related to those. ATM In my code I get the client token using GetTickCount(), and I write the CD-Key hashed data (dwOutputBuffer) as it is, without converting it to Little Endian or without changing the order. For example, if dwOutputBuffer[0] was 01 02 03 04, and dwOutputBuffer[1] was 05 06 07 08, the packet sent to battle net would be "... 01 02 03 04 05 06 07 08..." I hope with that info someone is able to help me, BTW if you want me to post the any part of the code or any packet log just tell me. Thx for your help in advance. EDIT: I'll post again the actual code of the function that makes packet 0x51, I've made some changes to it to solve some errors. [code] // S SID_AUTH_CHECK // This function is supossed to build and send the fifth packet (0x51) // At the start of this function, csFifthPacket.packet (the packet 0x51 that // this function sends to battle.net at the end) is EMPTY. int LTBNFifthPacket() { /* Globals... */ BEFORE_SEND; int n = 0; char * CDKeyOwner = "Luis"; /* End of Globals */ /* First, load Battle.snp to do the hashing for us */ HMODULE battlesnp; battlesnp = LoadLibrary("Battle.snp"); if(!battlesnp) cout << "Couldn't load battle.snp" << endl; /* Battlesnp Loaded */ /* CHECK REVISION */ /* Call CheckRevision() to get the some of the values to send */ /* The values we get are: ExeHash and Version (dwExeHash, and dwVersion) */ /* Also, we get an ExeInfo string. (To CRExeInfo). */ DWORD dwCRVersion = 0; DWORD dwCRChecksum = 0; char CRExeInfo[5000]; memset(CRExeInfo, 0, 5000); BOOL bCheckRevision = 0; bCheckRevision = CheckRevision("C:\\Archivos de programa\\Diablo II\\Game.exe", "C:\\Archivos de programa\\Diablo II\\Bnclient.dll", "C:\\Archivos de programa\\Diablo II\\D2client.dll", r_SID_AUTH_INFO.ValueString, &dwCRVersion, &dwCRChecksum, CRExeInfo, r_SID_AUTH_INFO.IX86ver_filename); if(bCheckRevision == FALSE) { cout << "ERROR: Check Revision() Failed" << endl; system("pause"); } else cout << "CheckRevision() Success" << endl; strcpy(CRExeInfo, "Game.exe 10/13/03 08:35:30 1198857"); /*printf("dwVersion: %x || dwChecksum: %x || ExeInfo: %s", dwVersion, dwChecksum, CRExeInfo);*/ /* END OF CHECK REVISION */ /* VARIABLES TO PUT IN THE PACKET DECLARATIONS */ int x = 0; BYTE FirstByte = 0xFF; // It's always 0xFF BYTE PacketID = 0x51; // PacketId's 0x51 WORD PacketLen = 132 + strlen(CDKeyOwner); // Packet Length is 132 + ownerlen DWORD ClientToken = GetTickCount(); // I use GetTickCount() to get that DWORD ExeVersion = dwCRVersion; // From CheckRevision() DWORD ExeHash = dwCRChecksum; // From CheckRevision() DWORD CDKeyNumber = 2; // 1 D2 cd key, 1 Lod cd key. DWORD UsingOfKeys = 0; // 0 DWORD Key1Len = 0x10; // Length of D2 CdKey: 16 (0x10) DWORD Key1Num1 = x; // This is supossed to be the First Number of the first cd key. // I'm not sure how to get it. DWORD Key1Unknown = 0; // Unknown(0) DWORD Key2Len = 0x10; // Same... DWORD Key2Num1 = x; // Same... DWORD Key2Unknown = 0; // Unknown (0) /* END OF VARIABLES TO PUT IN THE PACKET DECLARATIONS */ /* DO THE SAME FOR CDKEY2 */ DWORD dwKey2Product = 0; DWORD dwKey2Private = 0; DWORD dwKey2Public = 0; RunCDkeyDecode(&dwKey2Product, &dwKey2Public, &dwKey2Private, szLODCdKey); DWORD dwKey2HashBuffer[6]; DWORD dwKey2OutBuffer[5]; dwKey2HashBuffer[0] = GetTickCount(); dwKey2HashBuffer[1] = r_SID_AUTH_INFO.Server_Token; dwKey2HashBuffer[2] = dwKey2Product; dwKey2HashBuffer[3] = dwKey2Public; dwKey2HashBuffer[4] = 0; dwKey2HashBuffer[5] = dwKey2Private; HashData(24, dwKey2OutBuffer, dwKey2HashBuffer); /* ~~ */ /* CALL RUNCDKEYDECODE */ DWORD dwKey1Product = 0; DWORD dwKey1Private = 0; DWORD dwKey1Public = 0; RunCDkeyDecode(&dwKey1Product, &dwKey1Public, &dwKey1Private, szD2CdKey); //// //cout << endl << "RUNCDKEYDECODE" << endl; //cout << "dwProduct: " << hex << dwProduct << endl; //cout << "dwPublic: " << hex << dwPublic << endl; //cout << "dwPrivate: " << hex << dwPrivate << endl; //cout << endl << endl; /* END OF CALL RUNCDKEYDECODE */ /* CALL HASHDATA FOR CDKEY1*/ DWORD dwKey1HashBuffer[6]; DWORD dwKey1OutBuffer[5]; // This is supossed to be the CDKey1 Data. dwKey1HashBuffer[0] = ClientToken; // We got this with GetTickCount() dwKey1HashBuffer[1] = r_SID_AUTH_INFO.Server_Token; // Bnet sent this in the last packet dwKey1HashBuffer[2] = dwKey1Product; // We got this with RunCDKeyDecode dwKey1HashBuffer[3] = dwKey1Public; // We got this with RunCDKeyDecode too dwKey1HashBuffer[4] = 0; // 0... dwKey1HashBuffer[5] = dwKey1Private; // Also, we got this with RunCDKeyDecode HashData(24, dwKey1OutBuffer, dwKey1HashBuffer); /* END OF CALL HASHDATA */ /* WRITE EVERYTHING IN THE PACKET */ // Info about csFifthPacket class: // The packet itself is csFifthPacket.packet and it is a // dynamically allocated BYTE array. // The position the next function will write to is stored at // nByte2Write and is increased automatically with each WriteX function // call. // WriteByte writes a byte to packet. (csFifthPacket.packet). // WriteWord and WriteDWord take 2 arguments. The first one tells // if it has to convert the Word or DWord given to Little Endian before // putting it in packet or not. If the first argument is 0, it will // convert the DWORD given to Little Endian, and then put it in the // packet. If it is 1, it will put it in the packet directly without // converting it. // WriteString() just writes a string and a null terminator to packet. csFifthPacket.WriteByte(0xFF); // header R csFifthPacket.WriteByte(0x51); csFifthPacket.WriteWord(0, 132 + strlen(CDKeyOwner)); csFifthPacket.WriteDWord(0, ClientToken); // client token R? csFifthPacket.WriteDWord(0, ExeVersion); // Exe Version R csFifthPacket.WriteDWord(0, dwCRChecksum); // Exe Hash R csFifthPacket.WriteDWord(0, CDKeyNumber); // Number of CD keys R csFifthPacket.WriteDWord(0, UsingOfKeys); // Zero R cout << "dwKey1Public: " << hex << dwKey1Public << endl; cout << "dwKey1Private: " << hex << dwKey1Private << endl; cout << "dwKey2Public: " << hex << dwKey2Public << endl; cout << "dwKey2Private: " << hex << dwKey2Private << endl; csFifthPacket.WriteDWord(0, Key1Len); // Key1 Length R cout << "dwKey1Product: " << hex << dwKey1Product << endl; cout << "dwKey2Product: " << hex << dwKey2Product << endl; csFifthPacket.WriteDWord(0, dwKey1Product); // Key1 Product R csFifthPacket.WriteDWord(0, dwKey1Public); // Key1 Number1 R csFifthPacket.WriteDWord(0, Key1Unknown); // Key1 Unknown R #if OUTPUT_TO_LE == FALSE csFifthPacket.WriteDWord(1,dwKey1OutBuffer[0]); // KEY 1 csFifthPacket.WriteDWord(1,dwKey1OutBuffer[1]); // HASHED DATA csFifthPacket.WriteDWord(1,dwKey1OutBuffer[2]); csFifthPacket.WriteDWord(1,dwKey1OutBuffer[3]); csFifthPacket.WriteDWord(1,dwKey1OutBuffer[4]); #else csFifthPacket.WriteDWord(0,dwKey1OutBuffer[4]); csFifthPacket.WriteDWord(0,dwKey1OutBuffer[3]); csFifthPacket.WriteDWord(0,dwKey1OutBuffer[2]); csFifthPacket.WriteDWord(0,dwKey1OutBuffer[1]); csFifthPacket.WriteDWord(0,dwKey1OutBuffer[0]); #endif csFifthPacket.WriteDWord(0, Key2Len); // key2 length R csFifthPacket.WriteDWord(0, dwKey2Product); // Key2 Product R csFifthPacket.WriteDWord(0, dwKey2Public); // Key 2 Number 1 R? csFifthPacket.WriteDWord(0, Key2Unknown); // Key 2 Unknown #if OUTPUT_TO_LE == FALSE csFifthPacket.WriteDWord(1,dwKey2OutBuffer[0]); // KEY 2 csFifthPacket.WriteDWord(1,dwKey2OutBuffer[1]); // HASHED DATA csFifthPacket.WriteDWord(1,dwKey2OutBuffer[2]); csFifthPacket.WriteDWord(1,dwKey2OutBuffer[3]); csFifthPacket.WriteDWord(1,dwKey2OutBuffer[4]); #else csFifthPacket.WriteDWord(0,dwKey2OutBuffer[4]); csFifthPacket.WriteDWord(0,dwKey2OutBuffer[3]); csFifthPacket.WriteDWord(0,dwKey2OutBuffer[2]); csFifthPacket.WriteDWord(0,dwKey2OutBuffer[1]); csFifthPacket.WriteDWord(0,dwKey2OutBuffer[0]); #endif csFifthPacket.WriteString(CRExeInfo); // From CheckRevision() csFifthPacket.WriteString(CDKeyOwner); // These two sentences set the packet size word of packet to the packet // len. (Previously it was 136 instead 134). /* END OF WRITE EVERYTHING AT THE PACKET */ /* SEND csFifthPacket.packet TO BATTLE.NET */ n = SendPacket(csFifthPacket.packet, csFifthPacket.GetPacketLen()); if(n == -1) error(10, "SendPacket"); else cout << "Packet 0x51 Sent " << "Bytes: " << n << endl; /* END OF SEND PACKET TO BATTLE.NET */ return n; } void HashData(DWORD length, LPVOID outbuf, LPVOID tohash) { DWORD len = length; __asm { push ecx push edx mov ecx, outbuf mov edx, tohash push len call HashFunction pop edx pop ecx } } void RunCDkeyDecode(DWORD *Product, DWORD *CDKeyVal1, DWORD *CDKeyVal2, const char *CDKey) { __asm { push ecx push edx mov ecx, CDKey mov edx, Product push CDKeyVal2 push CDKeyVal1 call DecodeCDKeyFunction pop edx pop ecx } } [/code] The CheckRevision() function is in the first page of the topic, but as I wrote, I tested it yesterday so I think it works well. I think I posted my WriteDWord() function in the sixth or seventh page of the topic. I haven't posted the full source of the class because it's kinda long but if anyone wanna see it I have no inconvenience in posting it. Also, I posted the packet logs 2 or 3 posts back. | July 27, 2004, 7:32 PM |
Kp | This is easy. The server checks if you got the right version. If you didn't, it sends invalid version and quits processing your message. If your version is right, then it checks your CD key. So, your cdkey has apparently been wrong all this time, but the server was ignoring it until recently, since you couldn't even get the version information right. | July 27, 2004, 11:24 PM |
z-stars | [quote author=Kp link=board=17;threadid=7821;start=105#msg72994 date=1090970675] This is easy. The server checks if you got the right version. If you didn't, it sends invalid version and quits processing your message. If your version is right, then it checks your CD key. So, your cdkey has apparently been wrong all this time, but the server was ignoring it until recently, since you couldn't even get the version information right. [/quote] Yeah but why does bnet get so "angry" about invalid cd keys, and it doesn't care about invalid versions? and more important, what do I do for the CD Key thing to work well? | July 27, 2004, 11:30 PM |
Myndfyr | [quote author=z-stars link=board=17;threadid=7821;start=105#msg72997 date=1090971005] Yeah but why does bnet get so "angry" about invalid cd keys, and it doesn't care about invalid versions? and more important, what do I do for the CD Key thing to work well? [/quote] I'm not sure what you mean by "angry", but Battle.net (once upon a time) took an aggressive stance about bots. Any violations of the protocol result in immediate disconnect. I imagine that having an invalid CD key is more cause for IP banning because it appears you stole their client, rather than invalid version because it appears that their client simply needs to be upgraded. | July 27, 2004, 11:43 PM |
z-stars | [quote author=Myndfyre link=board=17;threadid=7821;start=105#msg73006 date=1090971790] [quote author=z-stars link=board=17;threadid=7821;start=105#msg72997 date=1090971005] Yeah but why does bnet get so "angry" about invalid cd keys, and it doesn't care about invalid versions? and more important, what do I do for the CD Key thing to work well? [/quote] I'm not sure what you mean by "angry", but Battle.net (once upon a time) took an aggressive stance about bots. Any violations of the protocol result in immediate disconnect. I imagine that having an invalid CD key is more cause for IP banning because it appears you stole their client, rather than invalid version because it appears that their client simply needs to be upgraded. [/quote] I see, but about my prog, nobody knows why could it be failing? :( | July 27, 2004, 11:56 PM |
OnlyMeat | Here this is what i do when im testing out new packets:- (1) Packet log the real client. (2) Isolate the 0x50 packet bnet sends the real client (serialize as binary file ) (3) Load the serialized 0x50 packet into your program as if you were processing the real 0x50. Also you need to record the cookies the real client used when sending 0x51, this should'nt be a problem cuz they are sent with the packet in raw form at a fixed offset, then hardcode those cookies in your 0x51 construct for the testing duration. (4) Now Serialize the 0x51 packet your program produces in response to 0x50 (5) Now the important part compare the the real clients 0x51 with yours in a hex editor (visual studio will do) (6) the 2 packets should be exactly the same!, if not then you will see immediatly where the problem is. This procedure works very well for me, just improvise these kind of testing procedures and it makes it easier to get this stuff right first time without getting ip banned!! | July 28, 2004, 12:28 AM |
z-stars | [quote author=OnlyMeat link=board=17;threadid=7821;start=105#msg73027 date=1090974480] Here this is what i do when im testing out new packets:- (1) Packet log the real client. (2) Isolate the 0x50 packet bnet sends the real client (serialize as binary file ) (3) Load the serialized 0x50 packet into your program as if you were processing the real 0x50. Also you need to record the cookies the real client used when sending 0x51, this should'nt be a problem cuz they are sent with the packet in raw form at a fixed offset, then hardcode those cookies in your 0x51 construct for the testing duration. (4) Now Serialize the 0x51 packet your program produces in response to 0x50 (5) Now the important part compare the the real clients 0x51 with yours in a hex editor (visual studio will do) (6) the 2 packets should be exactly the same!, if not then you will see immediatly where the problem is. This procedure works very well for me, just improvise these kind of testing procedures and it makes it easier to get this stuff right first time without getting ip banned!! [/quote] I think I did something like this with CheckRevision(), but how do I get the Client Token that d2 uses? I get my prog's with GetTickCount() | July 28, 2004, 12:34 AM |
Myndfyr | [quote author=z-stars link=board=17;threadid=7821;start=105#msg73010 date=1090972611] [quote author=Myndfyre link=board=17;threadid=7821;start=105#msg73006 date=1090971790] [quote author=z-stars link=board=17;threadid=7821;start=105#msg72997 date=1090971005] Yeah but why does bnet get so "angry" about invalid cd keys, and it doesn't care about invalid versions? and more important, what do I do for the CD Key thing to work well? [/quote] I'm not sure what you mean by "angry", but Battle.net (once upon a time) took an aggressive stance about bots. Any violations of the protocol result in immediate disconnect. I imagine that having an invalid CD key is more cause for IP banning because it appears you stole their client, rather than invalid version because it appears that their client simply needs to be upgraded. [/quote] I see, but about my prog, nobody knows why could it be failing? :( [/quote] It's not written correctly? Improper debugging techniques? Random bad luck? The 0x51 Client Session Key / Client Token is a randomly-generated value. GetTickCount() would work; there are really no restrictions on it, except that it's used for hashing the CD key. | July 28, 2004, 3:54 AM |
z-stars | But how can I find what's the Client Token the real d2 client uses in a certain time? If I knew this I could try the hash cd key function with fixed values to see if they are the same than the real d2 client generates... BTW, does anyone have some working code that hashes a cd key and puts it into a rdy to send packet so I can compare with my code? | July 28, 2004, 12:02 PM |
OnlyMeat | [quote author=z-stars link=board=17;threadid=7821;start=105#msg73108 date=1091016145] But how can I find what's the Client Token the real d2 client uses in a certain time? If I knew this I could try the hash cd key function with fixed values to see if they are the same than the real d2 client generates... BTW, does anyone have some working code that hashes a cd key and puts it into a rdy to send packet so I can compare with my code? [/quote] Well if i remember correctly the seed is the first dword in the 0x51 packet the client sends, take the code i posted in the first page of this topic ( you really should have read it ) it contains the first packet entries:- [code] /////////////////////////////////////////////////////////////////////////////////// // Fill-in default version info Packet << nSeed // Seed << nVersion // Client Version << nChecksum // Checksum from files << pAuthInfo->nCDKeys // No. cd-keys << (UINT)0x00; // Spawn (BOOL) [/code] So it just should be a matter of hard coding the first DWORD in the 0x51 packet the client sends into your 0x51 generation routine and loading the serialized 0x50 packet from the original packet log. Hope this helps. | July 28, 2004, 4:18 PM |
Myndfyr | [quote author=z-stars link=board=17;threadid=7821;start=105#msg73108 date=1091016145] But how can I find what's the Client Token the real d2 client uses in a certain time? If I knew this I could try the hash cd key function with fixed values to see if they are the same than the real d2 client generates... BTW, does anyone have some working code that hashes a cd key and puts it into a rdy to send packet so I can compare with my code? [/quote] I really don't think it matters what the number is, but if you're really that concerned about it, why don't you extract the 0x51 client key value from the 0x51 C->S packet from your packet log of the actual client? This was your packet log: [code] 0000 FF 51 86 00 58 01 3F 01 00 0A 00 01 5C D5 B3 27 .Q..X.?.....\..' 0010 02 00 00 00 00 00 00 00 10 00 00 00 06 00 00 00 ................ 0020 D9 15 0D 00 00 00 00 00 xx xx xx xx xx xx xx xx ................ 0030 xx xx xx xx xx xx xx xx xx xx xx xx 10 00 00 00 ..7...H......... 0040 0A 00 00 00 FB F9 12 00 00 00 00 00 xx xx xx xx ............MUjt 0050 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx lc.D........'NJQ 0060 47 61 6D 65 2E 65 78 65 20 31 30 2F 31 33 2F 30 Game.exe 10/13/0 0070 33 20 30 38 3A 33 35 3A 33 30 20 31 31 39 38 38 3 08:35:30 11988 0080 35 37 00 4D 65 00 57.Me. [/code] The client key occurs at offset 0x04 to 0x07. With reversed byte order, it's 0x013f0158. | July 28, 2004, 4:30 PM |