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