i wanted to release the TCD-Fixer as a standalone program.
It is for fixing the Hashes in the TCS.tcd ( which the TClient checks at the start ( if the SHA-1 Hashes are different it cries ) ).
It is open source so i release it ( also in the .rar file ).
You should be able to use C++ correctly to use this.
If you have questions ( about how i've figured that out? ) or something like this you can feel free to ask me ( For reversing you need knowledge in ASM ).
TCS.h
Code:
/* TCS.h coded and reversed by Ten$ion ( 2014 ) You can use this but put my name into th credits. */ #ifndef __TCS__H #define __TCS__H #include <Windows.h> #include <iostream> #include <vector> #include "SHA1.h" #pragma comment(lib, "advapi32.lib") class CTCS { private: //TCD-Entry Struct typedef struct tcd_entry { char* c_szTCDName; char* c_szSHA1; bool bNewSHA1; } T_TCDEntry; //Variables SHA1 sha1; //SHA-1 BYTE b_MagicByte; //Magic Byte from File char* c_szTCDPath; //Path to the TCD-Folder char* c_szFilePath; //Path to the TCS-File ( or whatever you've named it ) std::vector<T_TCDEntry> tTCD; //TCD-Entries void ShowLastError(); int Decrypt(BYTE* bInput, DWORD dwLen); int Encrypt(BYTE* bInput, DWORD dwLen); int SplitData(BYTE* bInput, DWORD dwLen); CTCS::T_TCDEntry HashFile(const char* c_szFileName); int Compare(); public: CTCS(char* c_szTCDPath){ this->c_szTCDPath = c_szTCDPath; }; bool Open(const char* c_szFileName); bool FixFiles(); }; #endif
TCS.cpp
Code:
/* TCS.cpp coded and reversed by Ten$ion ( 2014 ) You can use this but put my name into th credits. */ #include "TCS.h" /* Prints the last error */ void CTCS::ShowLastError() { char* szError = new char[MAX_PATH]; DWORD dwLastError = GetLastError(); FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, dwLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szError, MAX_PATH, 0); std::cout << "[Error]: " << szError << std::endl; } /* Opens the TCS-File c_szFileName => TCS.tcd or whatever you've named it. */ bool CTCS::Open(const char* c_szFileName) { char* szFilePath = new char[MAX_PATH]; BYTE* bBuffer; FILE* f; int iLen = 0; sprintf(szFilePath, "%s\\Tcd\\%s", c_szTCDPath, c_szFileName); if ((f = fopen(szFilePath, "r+b"))) { fseek(f, 0, SEEK_END); iLen = ftell(f); fseek(f, 0, SEEK_SET); bBuffer = new BYTE[iLen]; fread(bBuffer, iLen, 1, f); fclose(f); if (Decrypt(bBuffer, iLen) != -1) { c_szFilePath = szFilePath; SplitData(bBuffer, iLen); if (Compare() == 0) { tTCD.clear(); std::cout << "[Info]: There is no need to fix the files!" << std::endl; return false; } return true; } } ShowLastError(); return false; } /* Fixes the SHA-1 Hashes from the files and saves it. */ bool CTCS::FixFiles() { FILE* f; std::string strData = ""; char* c_szBuf = new char[MAX_PATH]; BYTE* b_EncBuf; int iLen = 0; sprintf(c_szBuf, "%d", tTCD.size()); strData = c_szBuf; strData += " "; for (int i = 0; i < tTCD.size(); i++) { sprintf(c_szBuf, "%s %s ", tTCD.at(i).c_szTCDName, tTCD.at(i).c_szSHA1); strData.append(c_szBuf); std::cout << "[Info]: Added : " << tTCD.at(i).c_szTCDName << std::endl; } if (strData.length() > 0xFE) { strData.insert(0, 1, 0xFF); strData.insert(1, 2, strData.length()); } else { strData.insert(0, 1, strData.length()); } b_EncBuf = (BYTE*)malloc(strData.length() + b_MagicByte); memcpy(b_EncBuf, strData.c_str(), strData.length()); memset(b_EncBuf + strData.length(), b_MagicByte, b_MagicByte); if ((iLen = Encrypt(b_EncBuf, strData.length() + b_MagicByte)) != -1) { if ((f = fopen(c_szFilePath, "w+b"))) { fwrite(b_EncBuf, iLen, 1, f); fclose(f); free(b_EncBuf); std::cout << "[Info]: Fixed Files" << std::endl; return true; } } free(b_EncBuf); return false; } /* Decrypts the TCS file. */ int CTCS::Decrypt(BYTE* bInput, DWORD dwLen) { const BYTE b_Key[34] = { 0x34, 0x53, 0x74, 0x6F, 0x72, 0x79, 0x5F, 0x4F, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x5F, 0x54, 0x43, 0x44, 0x5F, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x5F, 0x4B, 0x65, 0x79, 0x5F, 0x56, 0x61, 0x6C, 0x75, 0x65}; char c_szContainer[MAX_PATH]; HCRYPTHASH hHash = 0; HCRYPTKEY hKey = 0; HCRYPTPROV hProv = 0; GUID p_guid; CoCreateGuid(&p_guid); sprintf(c_szContainer, "%.8X-%.4X-%.4X-%.2X%.2X-%.2X%.2X%.2X%.2X%.2X%.2X", p_guid.Data1, p_guid.Data2, p_guid.Data3, p_guid.Data4[0], p_guid.Data4[1], p_guid.Data4[2], p_guid.Data4[3], p_guid.Data4[4], p_guid.Data4[5], p_guid.Data4[6], p_guid.Data4[7]); if (!CryptAcquireContextA(&hProv, c_szContainer, MS_ENHANCED_PROV_A, PROV_RSA_FULL, 8)) { ShowLastError(); return -1; } if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { ShowLastError(); return -1; } if (CryptHashData(hHash, b_Key, 34, 0)) { if (CryptDeriveKey(hProv, CALG_RC2, hHash, CRYPT_EXPORTABLE, &hKey)) { if (CryptDecrypt(hKey, 0, 0, 0, bInput, &dwLen)) { b_MagicByte = bInput[dwLen-1]; CryptReleaseContext(hProv, 8); CryptDestroyHash(hHash); CryptDestroyKey(hKey); return dwLen; } } } ShowLastError(); return -1; } /* Encrypts the TCS-File */ int CTCS::Encrypt(BYTE* bInput, DWORD dwLen) { const BYTE b_Key[34] = { 0x34, 0x53, 0x74, 0x6F, 0x72, 0x79, 0x5F, 0x4F, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x5F, 0x54, 0x43, 0x44, 0x5F, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6F, 0x5F, 0x4B, 0x65, 0x79, 0x5F, 0x56, 0x61, 0x6C, 0x75, 0x65 }; char c_szContainer[MAX_PATH]; HCRYPTHASH hHash = 0; HCRYPTKEY hKey = 0; HCRYPTPROV hProv = 0; GUID p_guid; CoCreateGuid(&p_guid); sprintf(c_szContainer, "%.8X-%.4X-%.4X-%.2X%.2X-%.2X%.2X%.2X%.2X%.2X%.2X", p_guid.Data1, p_guid.Data2, p_guid.Data3, p_guid.Data4[0], p_guid.Data4[1], p_guid.Data4[2], p_guid.Data4[3], p_guid.Data4[4], p_guid.Data4[5], p_guid.Data4[6], p_guid.Data4[7]); if (!CryptAcquireContextA(&hProv, c_szContainer, MS_ENHANCED_PROV_A, PROV_RSA_FULL, 8)) { ShowLastError(); return -1; } if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { ShowLastError(); return -1; } if (CryptHashData(hHash, b_Key, 34, 0)) { if (CryptDeriveKey(hProv, CALG_RC2, hHash, CRYPT_EXPORTABLE, &hKey)) { if (CryptEncrypt(hKey, 0, 0, 0, bInput, &dwLen, dwLen+512)) { CryptReleaseContext(hProv, 8); CryptDestroyHash(hHash); CryptDestroyKey(hKey); return dwLen; } } } ShowLastError(); return -1; } /* Splits the decrypted data into the TCD-Entries */ int CTCS::SplitData(BYTE* bInput, DWORD dwLen) { int i_pos = 0, i_start = 0, i_end = 0, i_count = 0; CTCS::T_TCDEntry te = {}; char* szBuf = new char[MAX_PATH]; tTCD.clear(); while (bInput[i_pos] > 0x39 || bInput[i_pos] < 0x30) i_pos++; i_count = strtol((char*)bInput + i_pos, (char**)NULL, 10); for (int i = 0; i < i_count; i++) { memset(&te, 0, sizeof(CTCS::T_TCDEntry)); te.c_szTCDName = new char[MAX_PATH]; te.c_szSHA1 = new char[40]; while (bInput[i_pos] != 0x54) //'T' i_pos++; i_start = i_pos; i_end = i_pos + 1; while (bInput[i_end] != 0x20) // ' ' i_end++; memcpy(te.c_szTCDName, bInput + i_start, (i_end - i_start)); te.c_szTCDName[(i_end - i_start)] = '\0'; i_start = i_end + 1; i_end = i_end + 2; while (bInput[i_end] != 0x20) // ' ' i_end++; memcpy(te.c_szSHA1, bInput + i_start, (i_end - i_start)); te.c_szSHA1[(i_end - i_start)] = '\0'; tTCD.push_back(te); i_pos = i_end; } return tTCD.size(); } /* Creates a SHA-1 Hash from a file. */ CTCS::T_TCDEntry CTCS::HashFile(const char* c_szFileName) { unsigned int sha_int[5]; char* c_szFilePath; char c; char* bFinalHash = new char[MAX_PATH]; int iLen = 0; FILE* f; CTCS::T_TCDEntry te = {}; memset(bFinalHash, 0, MAX_PATH); sha1.Reset(); c_szFilePath = new char[MAX_PATH]; sprintf(c_szFilePath, "%s\\Tcd\\%s", c_szTCDPath, c_szFileName); if (!(f = fopen(c_szFilePath, "rb"))) { return{ "", "" }; } c = fgetc(f); while (!feof(f)) { sha1.Input(c); c = fgetc(f); } fclose(f); if (!sha1.Result(sha_int)) { std::cout << "[Error]: Couldn't compute hash." << std::endl; return{ "", "" }; } for (int i = 0; i < 5; i++) { sprintf(bFinalHash, "%s%08X", bFinalHash, sha_int[i]); } te.c_szTCDName = new char[MAX_PATH]; te.c_szSHA1 = new char[40]; memcpy(te.c_szTCDName, c_szFileName, strlen(c_szFileName)); te.c_szTCDName[strlen(c_szFileName)] = '\0'; memcpy(te.c_szSHA1, bFinalHash, strlen(bFinalHash)); te.c_szSHA1[strlen(bFinalHash)] = '\0'; return te; } /* Compares the Hashes to see if they are different if yes, the hash will be changed and the bNewSHA1 boolean is set to true. */ int CTCS::Compare() { int i_count = 0; CTCS::T_TCDEntry te_hash; CTCS::T_TCDEntry te_real; for (int i = 0; i < tTCD.size(); i++) { te_hash = HashFile(tTCD.at(i).c_szTCDName); te_real = tTCD.at(i); if (strcmp(te_hash.c_szSHA1, te_real.c_szSHA1)) { te_hash.bNewSHA1 = true; tTCD.at(i) = te_hash; i_count++; std::cout << "[Info]: " << te_real.c_szTCDName << " got a different hash!" << std::endl; } } return i_count; }
Password: epvp_tension
Regards.