extensions/sdktools/vglobals.cpp
changeset 2535 b3bfd3c1ad9f
parent 2289 44045ead61cd
child 2746 8d68569b9648
     1.1 --- a/extensions/sdktools/vglobals.cpp	Sat Jan 17 13:45:51 2009 +1300
     1.2 +++ b/extensions/sdktools/vglobals.cpp	Thu Jan 22 15:20:45 2009 -0600
     1.3 @@ -83,12 +83,49 @@
     1.4  }
     1.5  #endif
     1.6  
     1.7 -bool vcmp(const void *_addr1, const void *_addr2, size_t len)
     1.8 +size_t UTIL_StringToSignature(const char *str, char buffer[], size_t maxlength)
     1.9  {
    1.10 -	unsigned char *addr1 = (unsigned char *)_addr1;
    1.11 -	unsigned char *addr2 = (unsigned char *)_addr2;
    1.12 +	size_t real_bytes = 0;
    1.13 +	size_t length = strlen(str);
    1.14  
    1.15 -	for (size_t i=0; i<len; i++)
    1.16 +	for (size_t i=0; i<length; i++)
    1.17 +	{
    1.18 +		if (real_bytes >= maxlength)
    1.19 +		{
    1.20 +			break;
    1.21 +		}
    1.22 +		buffer[real_bytes++] = (unsigned char)str[i];
    1.23 +		if (str[i] == '\\'
    1.24 +			&& str[i+1] == 'x')
    1.25 +		{
    1.26 +			if (i + 3 >= length)
    1.27 +			{
    1.28 +				continue;
    1.29 +			}
    1.30 +			/* Get the hex part */
    1.31 +			char s_byte[3];
    1.32 +			int r_byte;
    1.33 +			s_byte[0] = str[i+2];
    1.34 +			s_byte[1] = str[i+3];
    1.35 +			s_byte[2] = '\n';
    1.36 +			/* Read it as an integer */
    1.37 +			sscanf(s_byte, "%x", &r_byte);
    1.38 +			/* Save the value */
    1.39 +			buffer[real_bytes-1] = (unsigned char)r_byte;
    1.40 +			/* Adjust index */
    1.41 +			i += 3;
    1.42 +		}
    1.43 +	}
    1.44 +
    1.45 +	return real_bytes;
    1.46 +}
    1.47 +
    1.48 +bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len)
    1.49 +{
    1.50 +	unsigned char *addr1 = (unsigned char *) addr;
    1.51 +	unsigned char *addr2 = (unsigned char *) sig;
    1.52 +
    1.53 +	for (size_t i = 0; i < len; i++)
    1.54  	{
    1.55  		if (addr2[i] == '*')
    1.56  			continue;
    1.57 @@ -100,34 +137,20 @@
    1.58  }
    1.59  
    1.60  #if defined PLATFORM_WINDOWS
    1.61 -	/* Thanks to DS for the sigs */
    1.62 -	#define ISERVER_WIN_SIG				"\x8B\x44\x24\x2A\x50\xB9\x2A\x2A\x2A\x2A\xE8"
    1.63 -	#define ISERVER_WIN_SIG_LEN			11
    1.64  void GetIServer()
    1.65  {
    1.66 +	const char *sigstr;
    1.67 +	char sig[32];
    1.68 +	size_t siglen;
    1.69  	int offset;
    1.70  	void *vfunc = NULL;
    1.71  
    1.72 -	/* Get the offset into CreateFakeClient */
    1.73 -	if (!g_pGameConf->GetOffset("sv", &offset))
    1.74 -	{
    1.75 -		return;
    1.76 -	}
    1.77  #if defined METAMOD_PLAPI_VERSION
    1.78  	/* Get the CreateFakeClient function pointer */
    1.79  	if (!(vfunc=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient)))
    1.80  	{
    1.81  		return;
    1.82  	}
    1.83 -
    1.84 -	/* Check if we're on the expected function */
    1.85 -	if (!vcmp(vfunc, ISERVER_WIN_SIG, ISERVER_WIN_SIG_LEN))
    1.86 -	{
    1.87 -		return;
    1.88 -	}
    1.89 -
    1.90 -	/* Finally we have the interface we were looking for */
    1.91 -	iserver = *reinterpret_cast<IServer **>(reinterpret_cast<unsigned char *>(vfunc) + offset);
    1.92  #else
    1.93  	/* Get the interface manually */
    1.94  	SourceHook::MemFuncInfo info = {true, -1, 0, 0};
    1.95 @@ -139,14 +162,33 @@
    1.96  		void **vtable = *reinterpret_cast<void ***>(enginePatch->GetThisPtr() + info.thisptroffs + info.vtbloffs);
    1.97  		vfunc = vtable[info.vtblindex];
    1.98  	}
    1.99 -	/* Check if we're on the expected function */
   1.100 -	if (!vcmp(vfunc, ISERVER_WIN_SIG, ISERVER_WIN_SIG_LEN))
   1.101 +#endif
   1.102 +
   1.103 +	/* Get signature string for IVEngineServer::CreateFakeClient() */
   1.104 +	sigstr = g_pGameConf->GetKeyValue("CreateFakeClient_Windows");
   1.105 +
   1.106 +	if (!sigstr)
   1.107  	{
   1.108  		return;
   1.109  	}
   1.110  
   1.111 +	/* Convert signature string to signature bytes */
   1.112 +	siglen = UTIL_StringToSignature(sigstr, sig, sizeof(sig));
   1.113 +
   1.114 +	/* Check if we're on the expected function */
   1.115 +	if (!UTIL_VerifySignature(vfunc, sig, siglen))
   1.116 +	{
   1.117 +		return;
   1.118 +	}
   1.119 +
   1.120 +	/* Get the offset into CreateFakeClient */
   1.121 +	if (!g_pGameConf->GetOffset("sv", &offset))
   1.122 +	{
   1.123 +		return;
   1.124 +	}
   1.125 +
   1.126 +	/* Finally we have the interface we were looking for */
   1.127  	iserver = *reinterpret_cast<IServer **>(reinterpret_cast<unsigned char *>(vfunc) + offset);
   1.128 -#endif
   1.129  }
   1.130  #elif defined PLATFORM_POSIX
   1.131  void GetIServer()