Files
FC1/CrySystem/DataProbe.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

872 lines
23 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2001-2004.
// -------------------------------------------------------------------------
// File name: DataProbe.cpp
// Version: v1.00
// Created: 19/1/2004 by Timur.
// Compilers: Visual Studio.NET 2003
// Description: This is authentication functions, this code is not for public release!!
// -------------------------------------------------------------------------
// History:
//
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Timur.
// This is authentication functions, this code is not for public release!!
//////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#if defined(LINUX)
#include <CryLibrary.h>
#endif
#include "DataProbe.h"
#include "zlib\zlib.h"
#include "ISystem.h"
#include "CryFile.h"
#include "md5.h"
//#define FARCRY_EXE_CRC_CHECK
#if !defined(LINUX)
extern HMODULE gDLLHandle;
#endif
// embedd searchable string.
//#pragma comment( exestr, "CScriptObjectEntity:...." )
#define TEST_NAME_END 28
const char test_name[] = "Cannot find attached entity.\0....";
// Check Up to 1 Mb of data.
#define MAX_PROBE_SIZE uint64(1000000)
//#define XOR_VALUE_64 0xB1A72C931C38E5F2
#define ADLER_32_BASE 65521L /* largest prime smaller than 65536 */
#define ADLER_32_NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
#define ADLER_32 SpecialFunc1
#define CRC_32 SpecialFunc2
#define CRC_64 SpecialFunc3
/* ========================================================================= */
static unsigned int ADLER_32( unsigned int adler, const char *buf, unsigned int len)
{
unsigned int s1 = adler & 0xFFFF;
unsigned int s2 = (adler >> 16) & 0xFFFF;
int k;
if (!buf)
return 1L;
while (len > 0) {
k = len < ADLER_32_NMAX ? len : ADLER_32_NMAX;
len -= k;
while (k >= 16)
{
DO16(buf);
buf += 16;
k -= 16;
}
if (k != 0) do {
s1 += *buf++;
s2 += s1;
} while (--k);
s1 %= ADLER_32_BASE;
s2 %= ADLER_32_BASE;
}
return (s2 << 16) | s1;
}
#define AUTODIN_IIREV 0xEDB88320
#define POLY64REV 0xd800000000000000ULL
//////////////////////////////////////////////////////////////////////////
// Calculate CRC32 of buffer.
//////////////////////////////////////////////////////////////////////////
static unsigned int CRC_32( const char *buf,unsigned int len )
{
static unsigned int Table[256];
static int init = 0;
unsigned int code = 0xFFFFFFFF;
if (!init) {
int i;
init = 1;
for (i = 0; i <= 255; i++) {
int j;
unsigned int part = i;
for (j = 0; j < 8; j++) {
if (part & 1)
part = (part >> 1) ^ AUTODIN_IIREV;
else
part >>= 1;
}
Table[i] = part;
}
}
while (len--)
{
unsigned int temp1 = code >> 8;
unsigned int temp2 = Table[(code ^ (unsigned int )*buf) & 0xff];
code = temp1 ^ temp2;
buf += 1;
}
return code;
}
//////////////////////////////////////////////////////////////////////////
// Calculate CRC64 of buffer.
//////////////////////////////////////////////////////////////////////////
static uint64 CRC_64( const char *buf,unsigned int len )
{
static uint64 Table[256];
uint64 code = 0;
static int init = 0;
if (!init) {
int i;
init = 1;
for (i = 0; i <= 255; i++) {
int j;
uint64 part = i;
for (j = 0; j < 8; j++) {
if (part & 1)
part = (part >> 1) ^ POLY64REV;
else
part >>= 1;
}
Table[i] = part;
}
}
while (len--)
{
uint64 temp1 = code >> 8;
uint64 temp2 = Table[(code ^ (uint64)*buf) & 0xff];
code = temp1 ^ temp2;
buf += 1;
}
return code;
}
/*
void encipher(unsigned int *src,unsigned int *trg,int len,unsigned int *key )
{
unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3;
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3];
while (nlen--) {
register unsigned int y=v[0],z=v[1],n=32,sum=0;
while(n-->0) { sum += delta; y += (z << 4)+a ^ z+sum ^ (z >> 5)+b; z += (y << 4)+c ^ y+sum ^ (y >> 5)+d; }
w[0]=y; w[1]=z;
v+=2,w+=2;
}
}
void decipher(unsigned int *src,unsigned int *trg,int len,unsigned int *key )
{
unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3;
register unsigned delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3];
while (nlen--) {
register unsigned int y=v[0],z=v[1],sum=0xC6EF3720,n=32;
while(n-->0) { z -= (y << 4)+c ^ y+sum ^ (y >> 5)+d; y -= (z << 4)+a ^ z+sum ^ (z >> 5)+b; sum -= delta; }
w[0]=y; w[1]=z;
v+=2,w+=2;
}
}
*/
// src and trg can be the same pointer (in place encryption)
// len must be in bytes and must be multiple of 8 byts (64bits).
// key is 128bit: int key[4] = {n1,n2,n3,n4};
// void encipher(unsigned int *const v,unsigned int *const w,const unsigned int *const k )
#define TEA_ENCODE( src,trg,len,key ) {\
register unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3; \
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3]; \
while (nlen--) {\
register unsigned int y=v[0],z=v[1],n=32,sum=0; \
while(n-->0) { sum += delta; y += (z << 4)+a ^ z+sum ^ (z >> 5)+b; z += (y << 4)+c ^ y+sum ^ (y >> 5)+d; } \
w[0]=y; w[1]=z; v+=2,w+=2; }}
// src and trg can be the same pointer (in place decryption)
// len must be in bytes and must be multiple of 8 byts (64bits).
// key is 128bit: int key[4] = {n1,n2,n3,n4};
// void decipher(unsigned int *const v,unsigned int *const w,const unsigned int *const k)
#define TEA_DECODE( src,trg,len,key ) {\
register unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3; \
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3]; \
while (nlen--) { \
register unsigned int y=v[0],z=v[1],sum=0xC6EF3720,n=32; \
while(n-->0) { z -= (y << 4)+c ^ y+sum ^ (y >> 5)+d; y -= (z << 4)+a ^ z+sum ^ (z >> 5)+b; sum -= delta; } \
w[0]=y; w[1]=z; v+=2,w+=2; }}
//////////////////////////////////////////////////////////////////////////
// CDataProbe implementation.
//////////////////////////////////////////////////////////////////////////
CDataProbe::CDataProbe()
{
if (test_name[0]) // Make sure string is linked.
m_pRandAlloc = 0;
m_pRandAlloc = 0;
// Add current module. must be CrySystem.dll
SModuleInfo module;
module.filename = string("CrySystem")+string(".dll");
module.handle = (void*)test_name;
#if !defined(LINUX)
module.handle = gDLLHandle;
m_loadedModules.push_back(module);
#endif
#ifdef WIN32
char sPath[_MAX_PATH];
char dir[_MAX_DIR];
char drive[_MAX_DRIVE];
GetModuleFileName( GetModuleHandle(NULL),sPath,sizeof(sPath) );
_splitpath( sPath,drive,dir,NULL,NULL);
_makepath( sPath,drive,dir,NULL,NULL);
m_sBinPath = sPath;
#endif
}
CDataProbe::~CDataProbe()
{
}
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::GetDataCode( char *pBuf,int nSize,SDataProbeContext &ctx )
{
uint64 nCode = ((uint64)rand()) | (((uint64)rand())<<16) | (((uint64)rand())<<32) | (((uint64)rand())<<48);
nCode = 0; //@TODO: Comment out this later, 0 only for debugging.
// Hash readed data with choosen algorithm, store result into 64bit nCode.
switch ((ctx.nCodeInfo) & 7)
{
case DATAPROBE_CRC32:
{
nCode = CRC_32( pBuf,nSize );
nCode = nCode | ((~nCode) << 32);
}
break;
case DATAPROBE_CRC64:
{
nCode = CRC_64( pBuf,nSize );
}
break;
case DATAPROBE_ADLER32:
{
unsigned int code = ADLER_32(0L, 0, 0);
nCode = ADLER_32( 1,pBuf,ctx.nSize );
nCode = nCode | ((~nCode) << 32);
}
break;
case DATAPROBE_PURE_CRC32:
{
ctx.nCode = CRC_32( pBuf,nSize );
return true;
}
break;
case DATAPROBE_MD5:
{
char md5[16];
GetMD5( (char*)pBuf,nSize,md5 );
nCode = *((uint64*)md5);
return true;
}
break;
default:
{
nCode = CRC_32( pBuf,nSize );
nCode = nCode | ((~nCode) << 32);
}
}
// scramble code not to look like crc or alike.
int tkey[4] = {2985634234,378634893,387681212,436851212};
TEA_ENCODE( (unsigned int*)&nCode,(unsigned int*)&nCode,8,(unsigned int*)tkey );
ctx.nCode = nCode;
return true;
}
//////////////////////////////////////////////////////////////////////////
uint32 CDataProbe::GetHash( const char *sString )
{
return CRC_32( sString,strlen(sString) );
}
//////////////////////////////////////////////////////////////////////////
uint32 CDataProbe::GetHash( const void *buffer,int len )
{
return CRC_32( (const char*)buffer,len );
}
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::GetCode( SDataProbeContext &ctx )
{
if (ctx.nSize <= 0)
return false;
if (ctx.pBuffer)
{
return GetDataCode( (char*)ctx.pBuffer,ctx.nSize,ctx );
}
// Try to open file and hash it.
FILE *file = fopen( ctx.sFilename.c_str(),"rb" );
if (file)
{
fseek( file,0,SEEK_END );
unsigned int nFileSize = ftell(file);
if (ctx.nOffset >= nFileSize)
{
fclose(file);
return false;
}
ctx.nSize = min( ctx.nSize,nFileSize-ctx.nOffset );
if (fseek( file,ctx.nOffset,SEEK_SET ) != 0)
{
fclose( file );
return false;
}
char *pBuf = (char*)malloc( ctx.nSize );
if (fread( pBuf,ctx.nSize,1,file ) != 1)
{
free( pBuf );
fclose(file);
return false;
}
// Hash readed data with choosen algorithm, store result into 64bit nCode.
bool bOk = GetDataCode( pBuf,ctx.nSize,ctx );
free( pBuf );
fclose(file);
return bOk;
}
else
{
// Real file on disk not found... so check against one in the pak.
// Try to open file and hash it.
CCryFile cryfile;
if (cryfile.Open( ctx.sFilename.c_str(),"rb" ))
{
unsigned int nFileSize = cryfile.GetLength();
if (ctx.nOffset >= nFileSize)
{
return false;
}
ctx.nSize = min( ctx.nSize,nFileSize-ctx.nOffset );
if (cryfile.Seek( ctx.nOffset,SEEK_SET ) != 0)
{
return false;
}
char *pBuf = (char*)malloc( ctx.nSize );
if (cryfile.Read( pBuf,ctx.nSize ) != ctx.nSize)
{
free( pBuf );
return false;
}
// Hash readed data with choosen algorithm, store result into 64bit nCode.
bool bOk = GetDataCode( pBuf,ctx.nSize,ctx );
free( pBuf );
return bOk;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////
inline int64 GetRandom( int64 nRange )
{
return (int64(nRange) * int64(rand())) / RAND_MAX;
}
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::GetRandomFileProbe( SDataProbeContext &ctx,bool bAtEnd )
{
// Try to open file and hash it.
FILE *file = fopen( ctx.sFilename.c_str(),"rb" );
if (file)
{
fseek( file,0,SEEK_END );
int64 nFileSize = ftell(file);
// Choose any random size.
int64 nOffset = 0;
int64 nSize = GetRandom( MAX_PROBE_SIZE ) + 100;
if (bAtEnd)
{
// Prefare probe near the file end.
nSize = min( nSize,nFileSize-1 );
// Choose offset.
nOffset = nFileSize - nSize - GetRandom( 1000 );
}
else
{
nOffset = GetRandom( nFileSize - nSize );
if (nFileSize < MAX_PROBE_SIZE)
{
// Choose small random offset from both sides.
int nOffset1 = 0;
int nOffset2 = 0;
do {
nOffset1 = GetRandom( 1000 );
nOffset2 = GetRandom( 1000 );
} while (nOffset1+nOffset2 >= nFileSize+1);
nOffset = nOffset1;
nSize = nFileSize - nOffset2 - nOffset1;
}
}
if (nOffset < 0)
nOffset = 0;
if (nSize < 0)
nSize = nFileSize;
ctx.nSize = nSize;
ctx.nOffset = nOffset;
fclose(file);
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
void CDataProbe::RandSeed( uint32 seed )
{
m_rand.Seed( seed );
}
uint32 CDataProbe::GetRand()
{
return m_rand.Rand();
}
float CDataProbe::GetRand( float fMin,float fMax )
{
return m_rand.Rand( fMin,fMax );
}
//////////////////////////////////////////////////////////////////////////
// Timur.
// This is FarCry.exe authentication function, this code is not for public release!!
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::CheckLoader( void *pFunc )
{
const char *sKey = "Timur Davidenko";
typedef void (*AuthFunction)( void *data );
AuthFunction pCheckFunc = (AuthFunction)pFunc;
unsigned int data1[8];
unsigned int data2[8];
memcpy( data1,sKey,8 );
#ifdef FARCRY_EXE_CRC_CHECK
// Comment out after alpha master.
if (!CheckLoaderFC())
{
int *p = 0;
*p = 1;
return false;
}
#endif // FARCRY_EXE_CRC_CHECK
// data1 is filled with 32 bytes of random data.
// It is then encrypted with key1 and send to supplied check function.
// Function is supposed to uncrypt the data, and encrypt it again with key2.
// when function returns we should be able to uncrypt the data with key2 and compare with original.
// if it fails, we possibly running from the not authorized loader.
// set of keys (one for farcry.exe second for dedicated server).
int keys[6][4] = {
{1873613783,235688123,812763783,1745863682},
{1897178562,734896899,156436554,902793442},
{1178362782,223786232,371615531,90884141},
{89158165, 1389745433,971685123,785741042},
{389623487,373673863,657846392,378467832},
{1982697467,3278962783,278963782,287678311},
};
m_rand.Seed( GetTickCount() );
// Data assumed to be 32 bytes (8 ints).
for (int i = 0; i < 8; i++)
{
data1[i] = m_rand.Rand();
}
//////////////////////////////////////////////////////////////////////////
// First try... key0,key1
//////////////////////////////////////////////////////////////////////////
TEA_ENCODE( data1,data2,32,(unsigned int*)keys[0] );
pCheckFunc( data2 );
TEA_DECODE( data2,data2,32,(unsigned int*)keys[1] );
// Now check data1 and data2.
if (memcmp( data1,data2,32 ) == 0)
{
// Authentication passed.
return true;
}
//////////////////////////////////////////////////////////////////////////
// Second try... key2,key3
//////////////////////////////////////////////////////////////////////////
TEA_ENCODE( data1,data2,32,(unsigned int*)keys[2] );
pCheckFunc( data2 );
TEA_DECODE( data2,data2,32,(unsigned int*)keys[3] );
// Now check data1 and data2.
if (memcmp( data1,data2,32 ) == 0)
{
// Authentication passed.
return true;
}
//////////////////////////////////////////////////////////////////////////
// Third try... key4,key5
//////////////////////////////////////////////////////////////////////////
TEA_ENCODE( data1,data2,32,(unsigned int*)keys[4] );
pCheckFunc( data2 );
TEA_DECODE( data2,data2,32,(unsigned int*)keys[5] );
// Now check data1 and data2.
if (memcmp( data1,data2,32 ) == 0)
{
// Authentication passed.
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::CheckLoaderFC()
{
#ifdef FARCRY_EXE_CRC_CHECK
// Open exe file.
CCryFile file;
// crysystem.dll
string fsysname = string("c")+"r"+"y"+"s"+"y"+"s"+"t"+"e"+"m"+"."+"d"+"l"+"l";
// farcry.exe
string fcname = string("f")+"a"+"r"+"c"+"r"+"y"+"."+"e"+"x"+"e";
if (!file.Open( (m_sBinPath + fsysname).c_str(),"rb" ))
return false;
int nLen = file.GetLength();
char *pBuffer = new char[nLen+16];
file.Read( pBuffer,nLen );
// find embedded string.
int nStrLen = strlen(test_name)+1;
CryLogAlways( "Len=%d",nStrLen );
//nStrLen = TEST_NAME_END;
unsigned int nStoredCode = 0;
memcpy( &nStoredCode,test_name+nStrLen,sizeof(nStoredCode) );
bool bFound = false;
unsigned int nCode = 0;
for (int i = 0; i < nLen-nStrLen-32; i++)
{
if (memcmp(pBuffer+i,test_name,nStrLen) == 0)
{
// Found!
// Read code.
memcpy( &nStoredCode,pBuffer+i+nStrLen,sizeof(nCode) );
bFound = true;
break;
}
}
if (!bFound)
return false;
// Now compare code to the farcry.exe.
SDataProbeContext ctx;
ctx.nCodeInfo = DATAPROBE_PURE_CRC32;
ctx.sFilename = m_sBinPath + fcname;
ctx.nSize = 10000000;
if (!GetCode(ctx))
return false;
unsigned int nCurrentCode = ctx.nCode; // Invert of CRC32
nCurrentCode = ~nCurrentCode; // Invert of CRC32
// Codes must match.
if (nCurrentCode != nStoredCode)
return false;
delete []pBuffer;
#endif // FARCRY_EXE_CRC_CHECK
CryLogComment( "Init Loader" );
return true;
}
//////////////////////////////////////////////////////////////////////////
int CDataProbe::Compress( void *dest,unsigned int &destLen,const void *source, unsigned int sourceLen,int level )
{
unsigned long dlen = destLen;
int res = ::compress2( (Bytef*)dest,&dlen,(const Bytef*)source,sourceLen,level );
destLen = dlen;
return res;
}
//////////////////////////////////////////////////////////////////////////
int CDataProbe::Uncompress( void *dest,unsigned int &destLen,const void *source, unsigned int sourceLen )
{
unsigned long dlen = destLen;
int res = ::uncompress( (Bytef*)dest,&dlen,(const Bytef*)source,sourceLen );
destLen = dlen;
return res;
}
void CDataProbe::RandomAlloc()
{
#ifndef _DEBUG
RandSeed( GetTickCount() );
m_pRandAlloc = malloc( (GetRand() & 0xFFF) ); // do a random allocation to make debugging harder.
#endif
}
#if !defined(LINUX)
//////////////////////////////////////////////////////////////////////////
// Get address of executable code RAM for loaded DLL or EXE.
//////////////////////////////////////////////////////////////////////////
static void GetModuleCodeAddress( void *base,void **pCodeStartAddress,int *nCodeSize )
{
const IMAGE_DOS_HEADER *dos_head = (IMAGE_DOS_HEADER*)base;
assert(base);
assert(pCodeStartAddress);
assert(nCodeSize);
*pCodeStartAddress = 0;
*nCodeSize = 0;
#include <pshpack1.h> // no padding.
const struct PEHeader
{
DWORD signature;
IMAGE_FILE_HEADER _head;
IMAGE_OPTIONAL_HEADER opt_head;
IMAGE_SECTION_HEADER *section_header; // actual number in NumberOfSections
}
*header;
#include <poppack.h>
if (dos_head->e_magic != IMAGE_DOS_SIGNATURE)
{
// Wrong pointer, not to PE header.
return;
}
// verify DOS-EXE-Header
// after end of DOS-EXE-Header: offset to PE-Header
header = (PEHeader*)(const void *)((char *)dos_head + dos_head->e_lfanew);
if (IsBadReadPtr(header, sizeof(*header))) // start of PE-Header
{
// (no PE header, probably DOS executable)
return;
}
/*
CryLog( "[CodeModule] base: %x",base );
CryLog( "[CodeModule] base of code: %x",header->opt_head.BaseOfCode );
CryLog( "[CodeModule] size of code: %x",header->opt_head.SizeOfCode );
*/
void *pCodeAddress = (char*)base + header->opt_head.BaseOfCode;
if (IsBadReadPtr(pCodeAddress, header->opt_head.SizeOfCode ))
{
// Something wrong..., cant read code memory, skip it.
return;
}
*pCodeStartAddress = pCodeAddress;
*nCodeSize = header->opt_head.SizeOfCode;
/*
{
int sect;
const IMAGE_SECTION_HEADER *section_header;
for (sect = 0, section_header = header->section_header; sect < header->_head.NumberOfSections; sect++, section_header++)
{
}
}
*/
}
#endif //LINUX
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::GetRandomModuleProbe( SDataProbeContext &ctx )
{
#ifndef WIN32
return false; // Not WIN32
#else // WIN32
if (!ctx.pModuleBaseAddress)
{
// Try to find module handle from filename.
HMODULE hModule = GetModuleHandle( ctx.sFilename.c_str() );
if (!hModule)
return false;
ctx.pModuleBaseAddress = hModule;
}
void *pCodeAddress = 0;
int nCodeSize = 0;
// Get code sections pointers.
GetModuleCodeAddress( ctx.pModuleBaseAddress,&pCodeAddress,&nCodeSize );
if (!pCodeAddress || nCodeSize == 0)
return false;
// Choose small random offset from both sides.
int nOffset1 = 0;
int nOffset2 = 0;
do {
nOffset1 = GetRandom( 1000 );
nOffset2 = GetRandom( 1000 );
} while (nOffset1+nOffset2 >= nCodeSize+1);
ctx.pBuffer = pCodeAddress;
ctx.nOffset = nOffset1;
ctx.nSize = nCodeSize - nOffset1 - nOffset2;
if (IsBadReadPtr( (char*)pCodeAddress+nOffset1,ctx.nSize))
{
// Something wrong..., cant read code memory, skip it.
return false;
}
/*
//////////////////////////////////////////////////////////////////////////
// Write this to file....
CryLog( "[CodeModule] %s, base: %x",ctx.sFilename.c_str(),ctx.pModuleBaseAddress );
char *pBuf = (char*)malloc(ctx.nSize + 128);
memset(pBuf,0,ctx.nSize+64);
memcpy(pBuf,(char*)ctx.pBuffer+ctx.nOffset,ctx.nSize);
FILE *file;
if (!GetISystem()->IsDedicated())
file = fopen( (ctx.sFilename+".client_code").c_str(),"wb" );
else
file = fopen( (ctx.sFilename+".server_code").c_str(),"wb" );
fwrite( pBuf,ctx.nSize,1,file );
fclose(file);
unsigned int nCode = CRC_32( pBuf,ctx.nSize );
CryLog( "Code CRC32=%u, offset=%d,size=%d",nCode,ctx.nOffset,ctx.nSize );
free(pBuf);
//////////////////////////////////////////////////////////////////////////
*/
return true;
#endif //WIN32
}
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::GetModuleProbe( SDataProbeContext &ctx )
{
#ifndef WIN32
return false; // Not WIN32
#else // WIN32
if (!ctx.pModuleBaseAddress)
{
// Try to find module handle from filename.
HMODULE hModule = GetModuleHandle( ctx.sFilename.c_str() );
if (!hModule)
return false;
ctx.pModuleBaseAddress = hModule;
}
void *pCodeAddress = 0;
int nCodeSize = 0;
// Get code sections pointers.
GetModuleCodeAddress( ctx.pModuleBaseAddress,&pCodeAddress,&nCodeSize );
if (!pCodeAddress || nCodeSize == 0)
return false;
ctx.pBuffer = pCodeAddress;
if (IsBadReadPtr( (char*)pCodeAddress+ctx.nOffset,ctx.nSize))
{
// Something wrong..., cant read code memory, skip it.
return false;
}
/*
//////////////////////////////////////////////////////////////////////////
// Write this to file....
CryLog( "[CodeModule] %s, base: %x",ctx.sFilename.c_str(),ctx.pModuleBaseAddress );
char *pBuf = (char*)malloc(ctx.nSize + 128);
memset(pBuf,0,ctx.nSize+64);
memcpy(pBuf,(char*)ctx.pBuffer+ctx.nOffset,ctx.nSize);
FILE *file;
if (!GetISystem()->IsDedicated())
file = fopen( (ctx.sFilename+".client_code").c_str(),"wb" );
else
file = fopen( (ctx.sFilename+".server_code").c_str(),"wb" );
fwrite( pBuf,ctx.nSize,1,file );
fclose(file);
unsigned int nCode = CRC_32( pBuf,ctx.nSize );
CryLog( "Code CRC32=%u, offset=%d,size=%d",nCode,ctx.nOffset,ctx.nSize );
free(pBuf);
//////////////////////////////////////////////////////////////////////////
*/
return true;
#endif //WIN32
}
//////////////////////////////////////////////////////////////////////////
int CDataProbe::GetLoadedModules( SModuleInfo **pModules )
{
*pModules = 0;
int numModules = m_loadedModules.size();
if (numModules > 0)
{
*pModules = &m_loadedModules[0];
}
return numModules;
}
//////////////////////////////////////////////////////////////////////////
void CDataProbe::AddModule( SModuleInfo &moduleInfo )
{
m_loadedModules.push_back(moduleInfo);
}
//////////////////////////////////////////////////////////////////////////
void CDataProbe::AESDecryptBuffer( const char *pSrcBuffer,int nSrcSize,char *pDestBuffer,int &nDestSize,const char *sKey )
{
nDestSize = nSrcSize;
memcpy( pDestBuffer,pSrcBuffer,nSrcSize );
}
//////////////////////////////////////////////////////////////////////////
void CDataProbe::GetMD5( const char *pSrcBuffer,int nSrcSize,char signatureMD5[16] )
{
//#if !defined(LINUX)
struct MD5Context md5c;
MD5Init(&md5c);
MD5Update(&md5c, (unsigned char*)pSrcBuffer,nSrcSize );
MD5Final( (unsigned char*)signatureMD5, &md5c);
//#endif
}