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.







