Subversion Repositories WoWGM

Rev

Rev 32 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 tristanc 1
#include "Bootstrap.h"
2
 
3
//===========================================================================
4
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
5
{
6
    // Check WowGM's compatibility with the client version
7
    CheckBuildCompatibility();
8
 
9
    EnableSeDebugPrivilege();
10
 
11
    ExtractResource(hInstance, DLL_RESOURCEID, DLL_FILENAME);
12
 
13
    PROCESS_INFORMATION processInformation = CreateWowProcess(GetCommandLine());
14
	Sleep(2000);
15
    InjectDLL(processInformation.dwProcessId);
16
 
17
    // Wait for the client to exit and clean up...
18
    WaitForSingleObject(processInformation.hProcess, INFINITE);
19
    DeleteFile(DLL_FILENAME);
20
    return 0;
21
}
22
 
23
//===========================================================================
24
void CheckBuildCompatibility()
25
{
26
    ClientVersion wowGmVersion = {}, wowVersion = {};
27
    LPCSTR wowFilename = GetWowClientFileName();
28
    LPCSTR wowGmFilename = DLL_FILENAME;
29
 
30
    // Wow version checking
31
    DWORD hVersionInfo = 0;
32
    DWORD cbVersionInfo = GetFileVersionInfoSize(wowFilename, &hVersionInfo);
33
    if (cbVersionInfo > 0)
34
    {
35
        char* rgchVersionInfo = new char[cbVersionInfo];
36
        if (GetFileVersionInfo(wowFilename, hVersionInfo, cbVersionInfo, rgchVersionInfo))
37
        {
38
            UINT cbFixedFileInfo;
39
            VS_FIXEDFILEINFO* pffiFixedFileInfo;
40
 
41
            if (VerQueryValue(rgchVersionInfo, "\\", (void**)&pffiFixedFileInfo, &cbFixedFileInfo))
42
            {
43
                wowVersion.m_major = HIWORD(pffiFixedFileInfo->dwFileVersionMS);
44
                wowVersion.m_minor = LOWORD(pffiFixedFileInfo->dwFileVersionMS);
45
                wowVersion.m_revision = HIWORD(pffiFixedFileInfo->dwFileVersionLS);
46
                wowVersion.m_build = LOWORD(pffiFixedFileInfo->dwFileVersionLS);
47
            }
48
        }
49
        delete[] rgchVersionInfo;
50
    }
51
 
52
    // WowGM version checking: hardcoded in the meantime
53
    wowGmVersion = GetGmClientVersion();
54
    if (wowGmVersion.m_build == wowVersion.m_build)
55
        return; // WowGM is compatible with the targeted Wow client version;
56
 
57
    // Build the MessageBox output strings
58
    char szVersion[250];
59
    sprintf(szVersion,
60
        "Incompatible client version:\n"
61
        "Expected: %d.%d.%d (build %d)\n"
62
        "You have: %d.%d.%d (build %d)",
63
        wowVersion.m_major, wowVersion.m_minor, wowVersion.m_revision, wowVersion.m_build,
64
        wowGmVersion.m_major, wowGmVersion.m_minor, wowGmVersion.m_revision, wowGmVersion.m_build);
65
 
66
    // Display the MessageBox and exit
67
    MessageBox(0, szVersion, "WowGM Error", MB_OK);
68
    ExitProcess(420);
69
}
70
 
71
BOOL EnableSeDebugPrivilege () {
72
  HANDLE hToken = NULL;
73
  LUID luid;
74
 
75
  if (!OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
76
    return FALSE;
77
 
78
  if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
79
    return FALSE;
80
 
81
  TOKEN_PRIVILEGES tokenPriv = {};
82
  tokenPriv.PrivilegeCount = 1;
83
  tokenPriv.Privileges[0].Luid = luid;
84
  tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
85
  if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
86
    return FALSE;
87
 
88
  return TRUE;
89
}
90
 
91
void ExtractResource(const HINSTANCE hInstance, WORD resourceID, LPCSTR szFilename)
92
{
93
    /* Find and load the resource file: */
94
    /* Right now, this is hardcoded to extract DLL files... */
95
    HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(resourceID), "DLL");
96
    if (hResource == NULL)
97
        return ErrorExit("FindResource");
98
 
99
    HGLOBAL hFileResource = LoadResource(hInstance, hResource);
100
    if (hFileResource == NULL)
101
        return ErrorExit("LoadResource");
102
 
103
    /* Open and map this to a disk file... */
104
    LPVOID lpFile = LockResource(hFileResource);
105
    DWORD dwSize = SizeofResource(hInstance, hResource);
106
 
107
    /* Open the file and filemap... */
108
    HANDLE hFile = CreateFile(szFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
109
    HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwSize, NULL);
110
    if (hFileMap == NULL)
111
        return ErrorExit("CreateFileMapping");
112
 
113
    LPVOID lpAddress = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
114
    if (lpAddress == NULL)
115
        return ErrorExit("MapViewOfFile");
116
 
117
    /* Write the file... */
118
    CopyMemory(lpAddress, lpFile, dwSize);
119
 
120
    /* Clean up... */
121
    UnmapViewOfFile(lpAddress);
122
    CloseHandle(hFileMap);
123
    CloseHandle(hFile);
124
}
125
 
126
void ErrorExit(LPSTR lpszFunction)
127
{
128
    /* Retrieve the system error message for the last error code */
129
 
130
    LPVOID lpMsgBuf = NULL;
131
    LPVOID lpDisplayBuf = NULL;
132
    DWORD dw = GetLastError();
133
 
134
    FormatMessage(
135
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
136
        FORMAT_MESSAGE_FROM_SYSTEM |
137
        FORMAT_MESSAGE_IGNORE_INSERTS,
138
        NULL,
139
        dw,
140
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
141
        (LPSTR)&lpMsgBuf,
142
        0, NULL);
143
 
144
    /* Display the error message and exit the process */
145
 
146
    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
147
        (strlen((LPSTR)lpMsgBuf) + strlen(lpszFunction) + 40) * sizeof(CHAR));
148
 
149
    StringCchPrintf((LPSTR)lpDisplayBuf,
150
        LocalSize(lpDisplayBuf) / sizeof(CHAR),
151
        "%s failed with error %d: %s",
152
        lpszFunction, dw, lpMsgBuf);
153
    MessageBox(NULL, (LPSTR)lpDisplayBuf, "Error", MB_OK);
154
 
155
    LocalFree(lpMsgBuf);
156
    LocalFree(lpDisplayBuf);
157
    DeleteFile(DLL_FILENAME);
158
    ExitProcess(dw);
159
}
160
 
161
 
162
PROCESS_INFORMATION CreateWowProcess(LPSTR lpCmdLine)
163
{
164
    /* Initialize memory for our new process... */
165
    STARTUPINFO si;
166
    ZeroMemory(&si, sizeof(si));
167
    si.cb = sizeof(si);
168
    PROCESS_INFORMATION pi;
169
    ZeroMemory(&pi, sizeof(pi));
170
 
171
    /* Create the WoW process... */
172
    if (!CreateProcess(GetWowClientFileName(),    // Module name
173
        lpCmdLine,      // Command line
174
        NULL,           // Process handle not inheritable
175
        NULL,           // Thread handle not inheritable
176
        FALSE,          // Set handle inheritance to FALSE
177
        0,              // No creation flags
178
        NULL,           // Use parent's environment block
179
        NULL,           // Use parent's starting directory 
180
        &si,            // Pointer to STARTUPINFO structure
181
        &pi)           // Pointer to PROCESS_INFORMATION structure
182
        )
183
    {
184
        /* Failed to create the process: Clean up and error out */
185
        CloseHandle(pi.hProcess);
186
        CloseHandle(pi.hThread);
187
        ErrorExit("CreateProcess");
188
    }
189
    return pi;
190
}
191
 
192
//===========================================================================
193
void InjectDLL(DWORD dwid)
194
{
195
    /* Open a handle to the target process... */
196
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwid);
197
 
198
    LPCSTR dllPath = DLL_FILENAME;
199
    SIZE_T size = strlen(dllPath) + 1;
200
 
201
    /* Allocate memory for the dllpath in the target process: */
202
    /* length of the path = string + null terminator */
203
    LPVOID pPath = VirtualAllocEx(hProcess, NULL, size,
204
        MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
205
 
206
    /* Write the path to the address of the memory we just allocated in the target process... */
207
    WriteProcessMemory(hProcess, pPath, (LPVOID)dllPath, size, NULL);
208
 
209
    /* Create a Remote Thread in the target process which */
210
    /* calls LoadLibraryA as our dllpath as an argument->program loads our dll */
211
    HANDLE hLoadThread = CreateRemoteThread(hProcess, NULL, 0,
212
        (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32.dll"),
213
            "LoadLibraryA"), pPath, 0, NULL);
214
 
215
    /* Wait for the execution of our loader thread to finish... */
216
    WaitForSingleObject(hLoadThread, INFINITE);
217
 
218
    /* Free the memory allocated for our DLL path */
219
    VirtualFreeEx(hProcess, pPath, size, MEM_RELEASE);
220
}
221
 
222
LPSTR GetProcessNameById(DWORD processID)
223
{
224
    CHAR szProcessName[MAX_PATH] = "<unknown>";
225
    LPSTR result = szProcessName;
226
 
227
    /* Get a handle to the process... */
228
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
229
        PROCESS_VM_READ,
230
        FALSE, processID);
231
 
232
    /* Retrieve the process name for the given PID... */
233
    if (NULL != hProcess)
234
    {
235
        HMODULE hMod;
236
        DWORD cbNeeded;
237
 
238
        if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),
239
            &cbNeeded))
240
        {
241
            GetModuleBaseName(hProcess, hMod, szProcessName,
242
                sizeof(szProcessName) / sizeof(CHAR));
243
        }
244
    }
245
 
246
    /* Release the handle to the process. */
247
    CloseHandle(hProcess);
248
 
249
    result = szProcessName;
250
    return result;
251
}
252
 
253
HWND FindWindowByName(LPCSTR name)
254
{
255
    HWND window = NULL;
256
    window = FindWindowA(NULL, name);
257
    return window;
258
}