core/CrazyDebugger.cpp
changeset 2040 a2738afc53a1
parent 1952 b7aa2b626807
child 2041 1ba9eb0f85c7
     1.1 --- a/core/CrazyDebugger.cpp	Thu May 08 23:43:02 2008 +0000
     1.2 +++ b/core/CrazyDebugger.cpp	Fri May 09 08:04:27 2008 +0000
     1.3 @@ -29,12 +29,74 @@
     1.4   * Version: $Id$
     1.5   */
     1.6  
     1.7 -#if 0
     1.8  #include "sm_globals.h"
     1.9  #include "sourcemm_api.h"
    1.10  #include "Tlhelp32.h"
    1.11  #include "LibrarySys.h"
    1.12  #include "minidump.h"
    1.13 +#include "sm_stringutil.h"
    1.14 +
    1.15 +bool HookImportAddrTable(BYTE *base, const char *func, DWORD hookfunc, char *err, size_t maxlength)
    1.16 +{
    1.17 +	IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)base;
    1.18 +	if (dos->e_magic != IMAGE_DOS_SIGNATURE)
    1.19 +	{
    1.20 +		UTIL_Format(err, maxlength, "%s", "Could not detect valid DOS signature");
    1.21 +		return (err == NULL) ? true : false;
    1.22 +	}
    1.23 +
    1.24 +	IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(base + dos->e_lfanew);
    1.25 +	if (nt->Signature != IMAGE_NT_SIGNATURE)
    1.26 +	{
    1.27 +		UTIL_Format(err, maxlength, "%s", "Could not detect valid NT signature");
    1.28 +		return false;
    1.29 +	}
    1.30 +
    1.31 +	IMAGE_IMPORT_DESCRIPTOR *desc = 
    1.32 +		(IMAGE_IMPORT_DESCRIPTOR *)
    1.33 +		(base + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    1.34 +	if (base == (BYTE *)desc)
    1.35 +	{
    1.36 +		UTIL_Format(err, maxlength, "%s", "Could not find IAT");
    1.37 +		return false;
    1.38 +	}
    1.39 +
    1.40 +	bool entryFound = false;
    1.41 +	while (desc->Name)
    1.42 +	{
    1.43 +		if (desc->FirstThunk != 0)
    1.44 +		{
    1.45 +			IMAGE_THUNK_DATA *data = (IMAGE_THUNK_DATA *)(base + desc->OriginalFirstThunk);
    1.46 +			DWORD *iat = (DWORD *)(base + desc->FirstThunk);
    1.47 +			while (data->u1.Function)
    1.48 +			{
    1.49 +				if ((data->u1.Ordinal & IMAGE_ORDINAL_FLAG32) != IMAGE_ORDINAL_FLAG32)
    1.50 +				{
    1.51 +					IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME *)(base + data->u1.AddressOfData);
    1.52 +					if (strcmp((char *)import->Name, func) == 0)
    1.53 +					{
    1.54 +						DWORD oldprot, oldprot2;
    1.55 +						VirtualProtect(iat, 4, PAGE_READWRITE, &oldprot);
    1.56 +						*iat = hookfunc;
    1.57 +						VirtualProtect(iat, 4, oldprot, &oldprot2);
    1.58 +						entryFound = true;
    1.59 +					}
    1.60 +				}
    1.61 +				data++;
    1.62 +				iat++;
    1.63 +			}
    1.64 +		}
    1.65 +		desc++;
    1.66 +	}
    1.67 +
    1.68 +	if (!entryFound)
    1.69 +	{
    1.70 +		UTIL_Format(err, maxlength, "Could not find IAT entry for %s", func);
    1.71 +		return false;
    1.72 +	}
    1.73 +
    1.74 +	return true;
    1.75 +}
    1.76  
    1.77  BOOL
    1.78  WINAPI
    1.79 @@ -62,6 +124,24 @@
    1.80  	return GetProcAddress(hModule, lpProcName);
    1.81  }
    1.82  
    1.83 +HMODULE WINAPI LoadLibraryEx2(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
    1.84 +{
    1.85 +	HMODULE lib = LoadLibraryEx(lpFileName, hFile, dwFlags);
    1.86 +
    1.87 +	/* Steam.dll seems to get loaded using an abs path, thus the use of stristr() */
    1.88 +	if (stristr(lpFileName, "steam.dll"))
    1.89 +	{
    1.90 +		char err[64];
    1.91 +		if (!HookImportAddrTable((BYTE *)lib, "GetProcAddress", (DWORD)GetProcAddress2, err, sizeof(err)))
    1.92 +		{
    1.93 +			Error("[SM] %s in steam.dll\n", err);
    1.94 +			return NULL;
    1.95 +		}
    1.96 +	}
    1.97 +
    1.98 +	return lib;
    1.99 +}
   1.100 +
   1.101  class CrazyWindowsDebugger : public SMGlobalClass
   1.102  {
   1.103  public:
   1.104 @@ -69,6 +149,9 @@
   1.105  	{
   1.106  		HANDLE hModuleList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
   1.107  		MODULEENTRY32 me32;
   1.108 +		BYTE *engine = NULL;
   1.109 +		BYTE *steam = NULL;
   1.110 +		char err[64];
   1.111  
   1.112  		me32.dwSize = sizeof(MODULEENTRY32);
   1.113  
   1.114 @@ -77,69 +160,42 @@
   1.115  			Error("Could not initialize crazy debugger!");
   1.116  		}
   1.117  
   1.118 -		bool found = false;
   1.119 -
   1.120  		do
   1.121  		{
   1.122 -			if (strcasecmp(me32.szModule, "steam.dll") == 0)
   1.123 +			if (strcasecmp(me32.szModule, "engine.dll") == 0)
   1.124  			{
   1.125 -				IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)me32.modBaseAddr;
   1.126 -				if (dos->e_magic != IMAGE_DOS_SIGNATURE)
   1.127 -				{
   1.128 -					Error("[SM] Could not detect steam.dll with valid DOS signature");
   1.129 -				}
   1.130 -				char *base = (char *)dos;
   1.131 -				IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(base + dos->e_lfanew);
   1.132 -				if (nt->Signature != IMAGE_NT_SIGNATURE)
   1.133 -				{
   1.134 -					Error("[SM] Could not detect steam.dll with valid NT signature");
   1.135 -				}
   1.136 -				IMAGE_IMPORT_DESCRIPTOR *desc = 
   1.137 -					(IMAGE_IMPORT_DESCRIPTOR *)
   1.138 -					(base + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
   1.139 -				if (base == (char *)desc)
   1.140 -				{
   1.141 -					Error("[SM] Could not find the steam.dll IAT");
   1.142 -				}
   1.143 -				while (desc->Name)
   1.144 -				{
   1.145 -					if (desc->FirstThunk != 0)
   1.146 -					{
   1.147 -						IMAGE_THUNK_DATA *data = (IMAGE_THUNK_DATA *)(base + desc->OriginalFirstThunk);
   1.148 -						DWORD *iat = (DWORD *)(base + desc->FirstThunk);
   1.149 -						while (data->u1.Function)
   1.150 -						{
   1.151 -							if ((data->u1.Ordinal & IMAGE_ORDINAL_FLAG32) != IMAGE_ORDINAL_FLAG32)
   1.152 -							{
   1.153 -								IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME *)(base + data->u1.AddressOfData);
   1.154 -								if (strcmp((char *)import->Name, "GetProcAddress") == 0)
   1.155 -								{
   1.156 -									DWORD oldprot, oldprot2;
   1.157 -									VirtualProtect(iat, 4, PAGE_READWRITE, &oldprot);
   1.158 -									*iat = (DWORD)GetProcAddress2;
   1.159 -									VirtualProtect(iat, 4, oldprot, &oldprot2);
   1.160 -									found = true;
   1.161 -									goto _end;
   1.162 -								}
   1.163 -							}
   1.164 -							data++;
   1.165 -							iat++;
   1.166 -						}
   1.167 -					}
   1.168 -					desc++;
   1.169 -				}
   1.170 +				engine = me32.modBaseAddr;
   1.171 +			}
   1.172 +			else if (strcasecmp(me32.szModule, "steam.dll") == 0)
   1.173 +			{
   1.174 +				/* Steam.dll is loaded by engine.dll, so we can exit the loop here */
   1.175 +				steam = me32.modBaseAddr;
   1.176  				break;
   1.177  			}
   1.178  		} while  (Module32Next(hModuleList, &me32));
   1.179  
   1.180 -_end:
   1.181 +		CloseHandle(hModuleList);
   1.182  
   1.183 -		if (!found)
   1.184 +		/* This really should not happen, but ... */
   1.185 +		if (!engine)
   1.186  		{
   1.187 -			Error("Could not find steam.dll's GetProcAddress IAT entry");
   1.188 +			Error("[SM] Could not find engine.dll\n");
   1.189  		}
   1.190  
   1.191 -		CloseHandle(hModuleList);
   1.192 +		/* Steam.dll isn't loaded yet */
   1.193 +		if (!steam)
   1.194 +		{
   1.195 +			if (!HookImportAddrTable(engine, "LoadLibraryExA", (DWORD)LoadLibraryEx2, err, sizeof(err)))
   1.196 +			{
   1.197 +				Error("[SM] %s in engine.dll)\n", err);
   1.198 +			}
   1.199 +		}
   1.200 +		else
   1.201 +		{
   1.202 +			if (!HookImportAddrTable(steam, "GetProcAddress", (DWORD)GetProcAddress2, err, sizeof(err)))
   1.203 +			{
   1.204 +				Error("[SM] %s in steam.dll)\n", err);
   1.205 +			}
   1.206 +		}
   1.207  	}
   1.208  } s_CrazyDebugger;
   1.209 -#endif