OSDN Git Service

receive return code of injected code by GetExitCodeThread()
[yamy/yamy.git] / fixscancodemap.cpp
1 #include "fixscancodemap.h"\r
2 #include "registry.h"\r
3 #include "misc.h"\r
4 #include <tchar.h>\r
5 #include <tlhelp32.h>\r
6 \r
7 typedef HMODULE (WINAPI *FpGetModuleHandleW)(LPCWSTR);\r
8 typedef FARPROC (WINAPI *FpGetProcAddress)(HMODULE, LPCSTR);\r
9 typedef BOOL (WINAPI *FpUpdatePerUserSystemParameters)(DWORD, BOOL);\r
10 typedef HANDLE (WINAPI *FpOpenProcess)(DWORD, BOOL, DWORD);\r
11 typedef BOOL (WINAPI *FpOpenProcessToken)(HANDLE, DWORD, PHANDLE);\r
12 typedef BOOL (WINAPI *FpImpersonateLoggedOnUser)(HANDLE);\r
13 typedef BOOL (WINAPI *FpRevertToSelf)(VOID);\r
14 typedef BOOL (WINAPI *FpCloseHandle)(HANDLE);\r
15 \r
16 typedef struct {\r
17         DWORD pid_;\r
18         TCHAR advapi32_[64];\r
19         CHAR impersonateLoggedOnUser_[32];\r
20         CHAR revertToSelf_[32];\r
21         CHAR openProcessToken_[32];\r
22         FpGetModuleHandleW pGetModuleHandle;\r
23         FpGetProcAddress pGetProcAddress;\r
24         FpUpdatePerUserSystemParameters pUpdate;\r
25         FpOpenProcess pOpenProcess;\r
26         FpCloseHandle pCloseHandle;\r
27 } InjectInfo;\r
28 \r
29 #pragma runtime_checks( "", off )\r
30 static DWORD invokeFunc(InjectInfo *info)\r
31 {\r
32         BOOL ret;\r
33         HANDLE hToken;\r
34         HMODULE hAdvapi32;\r
35         FpImpersonateLoggedOnUser pImpersonateLoggedOnUser;\r
36         FpRevertToSelf pRevertToSelf;\r
37         FpOpenProcessToken pOpenProcessToken;\r
38 \r
39         hAdvapi32 = info->pGetModuleHandle(info->advapi32_);\r
40 \r
41         pImpersonateLoggedOnUser = (FpImpersonateLoggedOnUser)info->pGetProcAddress(hAdvapi32, info->impersonateLoggedOnUser_);\r
42         pRevertToSelf = (FpRevertToSelf)info->pGetProcAddress(hAdvapi32, info->revertToSelf_);\r
43         pOpenProcessToken = (FpOpenProcessToken)info->pGetProcAddress(hAdvapi32, info->openProcessToken_);\r
44 \r
45         HANDLE hProcess = info->pOpenProcess(PROCESS_QUERY_INFORMATION, FALSE, info->pid_);\r
46         if (hProcess == NULL) {\r
47                 return 1;\r
48         }\r
49 \r
50         ret = pOpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE , &hToken);\r
51         if (ret == FALSE) {\r
52                 return 2;\r
53         }\r
54 \r
55         ret = pImpersonateLoggedOnUser(hToken);\r
56         if (ret == FALSE) {\r
57                 return 3;\r
58         }\r
59 \r
60         info->pUpdate(0, 1);\r
61 \r
62         ret = pRevertToSelf();\r
63         if (ret == FALSE) {\r
64                 return 4;\r
65         }\r
66 \r
67         info->pCloseHandle(hToken);\r
68         info->pCloseHandle(hProcess);\r
69         return 0;\r
70 }\r
71 static void afterFunc(void){}\r
72 #pragma runtime_checks( "", restore )\r
73 \r
74 int FixScancodeMap::acquirePrivileges()\r
75 {\r
76         int ret = 0;\r
77         HANDLE hToken = NULL;\r
78 \r
79         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {\r
80                 ret = 1;\r
81                 goto exit;\r
82         }\r
83 \r
84         LUID luid;\r
85         if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {\r
86                 ret = 2;\r
87                 goto exit;\r
88         }\r
89 \r
90         TOKEN_PRIVILEGES tk_priv;\r
91         tk_priv.PrivilegeCount = 1;\r
92         tk_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
93         tk_priv.Privileges[0].Luid = luid;\r
94 \r
95         if (!AdjustTokenPrivileges(hToken, FALSE, &tk_priv, 0, NULL, NULL)) {\r
96                 ret = 3;\r
97                 goto exit;\r
98         }\r
99 \r
100 exit:\r
101         if (hToken != NULL) {\r
102             CloseHandle(hToken);\r
103         }\r
104         return ret;\r
105 }\r
106 \r
107 \r
108 DWORD FixScancodeMap::getWinLogonPid()\r
109 {\r
110     DWORD pid = 0;\r
111         DWORD mySessionId = 0;\r
112 \r
113         if (ProcessIdToSessionId(GetCurrentProcessId(), &mySessionId) == FALSE) {\r
114                 return 0;\r
115         }\r
116 \r
117         HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\r
118         if (hSnap == INVALID_HANDLE_VALUE) {\r
119                 return 0;\r
120         }\r
121 \r
122         PROCESSENTRY32 pe;\r
123         pe.dwSize = sizeof(pe);\r
124 \r
125     BOOL bResult = Process32First(hSnap, &pe);\r
126         while (bResult){\r
127                 if (!_tcscmp(pe.szExeFile, _T("winlogon.exe"))) {\r
128                         DWORD sessionId;\r
129 \r
130                         if (ProcessIdToSessionId(pe.th32ProcessID, &sessionId) != FALSE) {\r
131                                 if (sessionId == mySessionId) {\r
132                                         pid = pe.th32ProcessID;\r
133                                         break;\r
134                                 }\r
135                         }\r
136                 }\r
137                 bResult = Process32Next(hSnap, &pe);\r
138         }\r
139 \r
140         CloseHandle(hSnap);\r
141         return pid;\r
142 }\r
143 \r
144 \r
145 int FixScancodeMap::injectThread(DWORD dwPID)\r
146 {\r
147         int ret = 0;\r
148         DWORD err = 0;\r
149         BOOL wFlag;\r
150 \r
151         HANDLE hProcess = NULL;\r
152         LPVOID remoteMem = NULL;\r
153         LPVOID remoteInfo = NULL;\r
154         DWORD invokeFuncAddr = (DWORD)invokeFunc;\r
155         DWORD afterFuncAddr = (DWORD)afterFunc;\r
156         DWORD memSize =  afterFuncAddr - invokeFuncAddr;\r
157         InjectInfo info;\r
158         HMODULE hMod;\r
159 \r
160         info.pid_ = GetCurrentProcessId();\r
161 \r
162         memcpy(&info.advapi32_, _T("advapi32.dll"), sizeof(info.advapi32_));\r
163         memcpy(&info.impersonateLoggedOnUser_, "ImpersonateLoggedOnUser", sizeof(info.impersonateLoggedOnUser_));\r
164         memcpy(&info.revertToSelf_, "RevertToSelf", sizeof(info.revertToSelf_));\r
165         memcpy(&info.openProcessToken_, "OpenProcessToken", sizeof(info.openProcessToken_));\r
166 \r
167         hMod = GetModuleHandle(_T("user32.dll"));\r
168         if (hMod != NULL) {\r
169                 info.pUpdate = (FpUpdatePerUserSystemParameters)GetProcAddress(hMod, "UpdatePerUserSystemParameters");\r
170                 if (info.pUpdate == NULL) {\r
171                         return 1;\r
172                 }\r
173         }\r
174 \r
175         hMod = GetModuleHandle(_T("kernel32.dll"));\r
176         if (hMod != NULL) {\r
177                 info.pGetModuleHandle = (FpGetModuleHandleW)GetProcAddress(hMod, "GetModuleHandleW");\r
178                 if (info.pGetModuleHandle == NULL) {\r
179                         return 1;\r
180                 }\r
181 \r
182                 info.pGetProcAddress = (FpGetProcAddress)GetProcAddress(hMod, "GetProcAddress");\r
183                 if (info.pGetProcAddress == NULL) {\r
184                         return 1;\r
185                 }\r
186 \r
187                 info.pOpenProcess = (FpOpenProcess)GetProcAddress(hMod, "OpenProcess");\r
188                 if (info.pOpenProcess == NULL) {\r
189                         return 1;\r
190                 }\r
191 \r
192                 info.pCloseHandle = (FpCloseHandle)GetProcAddress(hMod, "CloseHandle");\r
193                 if (info.pCloseHandle == NULL) {\r
194                         return 1;\r
195                 }\r
196         }\r
197 \r
198         if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) == NULL) {\r
199                 ret = 1;\r
200                 goto exit;\r
201         }\r
202 \r
203         remoteMem = VirtualAllocEx(hProcess, NULL, memSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
204         if (remoteMem == NULL) {\r
205                 ret = 2;\r
206                 err = GetLastError();\r
207                 goto exit;\r
208         }\r
209 \r
210         wFlag = WriteProcessMemory(hProcess, remoteMem, (char*)invokeFunc, memSize, (SIZE_T*)0);\r
211         if (wFlag == FALSE) {\r
212                 ret = 3;\r
213                 goto exit;\r
214         }\r
215 \r
216         remoteInfo = VirtualAllocEx(hProcess, NULL, sizeof(info), MEM_COMMIT, PAGE_READWRITE);\r
217         if (remoteInfo == NULL) {\r
218                 ret = 2;\r
219                 err = GetLastError();\r
220                 goto exit;\r
221         }\r
222 \r
223         wFlag = WriteProcessMemory(hProcess, remoteInfo, (char*)&info, sizeof(info), (SIZE_T*)0);\r
224         if (wFlag == FALSE) {\r
225                 ret = 3;\r
226                 goto exit;\r
227         }\r
228 \r
229 #if 0\r
230         TCHAR buf[1024];\r
231 \r
232         _stprintf_s(buf, sizeof(buf)/sizeof(buf[0]),\r
233                 _T("execute UpdatePerUserSystemParameters(), inject code to winlogon.exe?\r\n")\r
234                 _T("invokeFunc=0x%p\r\n")\r
235                 _T("afterFunc=0x%p\r\n")\r
236                 _T("afterFunc - invokeFunc=%d\r\n")\r
237                 _T("remoteMem=0x%p\r\n")\r
238                 _T("remoteInfo=0x%p(size: %d)\r\n"),\r
239                 invokeFunc, afterFunc, memSize, remoteMem, remoteInfo, sizeof(info));\r
240         if (MessageBox((HWND)NULL, buf, _T("upusp"), MB_OKCANCEL | MB_ICONSTOP) == IDCANCEL) {\r
241                 (info.pUpdate)(0, 1);\r
242                 goto exit;\r
243         }\r
244 #endif\r
245 \r
246         HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, \r
247                 (LPTHREAD_START_ROUTINE)remoteMem, remoteInfo, 0, NULL);\r
248         if (hThread == NULL) {\r
249                 ret = 4;\r
250                 goto exit;\r
251         }\r
252 \r
253         if (WaitForSingleObject(hThread, 5000) == WAIT_TIMEOUT) {\r
254                 ret = 5;\r
255                 goto exit;\r
256         }\r
257         DWORD result = -1;\r
258         GetExitCodeThread(hThread, &result);\r
259         ret = result;\r
260         CloseHandle(hThread);\r
261 \r
262 exit:\r
263         if (remoteMem != NULL) {\r
264                 VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);\r
265         }\r
266 \r
267         if (remoteInfo != NULL) {\r
268                 VirtualFreeEx(hProcess, remoteInfo, 0, MEM_RELEASE);\r
269         }\r
270 \r
271         if (hProcess != NULL) {\r
272                 CloseHandle(hProcess);\r
273         }\r
274 \r
275         return ret;\r
276 }\r
277 \r
278 int FixScancodeMap::update()\r
279 {\r
280         MINIMIZEDMETRICS mm;\r
281         int result = 0;\r
282 \r
283         if (acquirePrivileges()) {\r
284                 result = 1;\r
285                 goto exit;\r
286         }\r
287 \r
288         DWORD dwPID;\r
289         if ((dwPID = getWinLogonPid()) == 0) {\r
290                 result = 1;\r
291                 goto exit;\r
292         }\r
293 \r
294         memset(&mm, 0, sizeof(mm));\r
295         mm.cbSize = sizeof(mm);\r
296         SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(mm), &mm, 0);\r
297 \r
298         if (injectThread(dwPID)) {\r
299                 result = 1;\r
300                 goto exit;\r
301         }\r
302 \r
303         SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, sizeof(mm), &mm, 0);\r
304 \r
305 exit:\r
306         return result;\r
307 }\r
308 \r
309 int FixScancodeMap::fix()\r
310 {\r
311         ScancodeMap *origMap, *fixMap;\r
312         Registry reg(HKEY_CURRENT_USER, _T("Keyboard Layout"));\r
313         // Windows7 RC not support Scancode Map on HKCU?\r
314         //Registry reg(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout"));\r
315         DWORD origSize, fixSize;\r
316         bool ret;\r
317         int result = 0;\r
318 \r
319         // save original Scancode Map\r
320         ret = reg.read(_T("Scancode Map"), NULL, &origSize, NULL, 0);\r
321         if (ret) {\r
322                 origMap = reinterpret_cast<ScancodeMap*>(malloc(origSize));\r
323                 if (origMap == NULL) {\r
324                         result = 1;\r
325                         goto exit;\r
326                 }\r
327 \r
328                 ret = reg.read(_T("Scancode Map"), reinterpret_cast<BYTE*>(origMap), &origSize, NULL, 0);\r
329                 if (ret == false) {\r
330                         result = 1;\r
331                         goto exit;\r
332                 }\r
333 \r
334                 fixSize = origSize;\r
335                 fixMap = reinterpret_cast<ScancodeMap*>(malloc(origSize + s_fixEntryNum * sizeof(s_fixEntry[0])));\r
336                 if (fixMap == NULL) {\r
337                         result = 1;\r
338                         goto exit;\r
339                 }\r
340 \r
341                 memcpy_s(fixMap, origSize + s_fixEntryNum, origMap, origSize);\r
342         } else {\r
343                 origSize = 0;\r
344                 origMap = NULL;\r
345 \r
346                 fixSize = sizeof(ScancodeMap);\r
347                 fixMap = reinterpret_cast<ScancodeMap*>(malloc(sizeof(ScancodeMap) + s_fixEntryNum * sizeof(s_fixEntry[0])));\r
348                 if (fixMap == NULL) {\r
349                         result = 1;\r
350                         goto exit;\r
351                 }\r
352 \r
353                 fixMap->header1 = 0;\r
354                 fixMap->header2 = 0;\r
355                 fixMap->count = 1;\r
356                 fixMap->entry[0] = 0;\r
357         }\r
358 \r
359         for (DWORD i = 0; i < s_fixEntryNum; i++) {\r
360                 bool skip = false;\r
361 \r
362                 if (origMap) {\r
363                         for (DWORD j = 0; j < origMap->count; j++) {\r
364                                 if (HIWORD(s_fixEntry[i]) == HIWORD(origMap->entry[j])) {\r
365                                         skip = true;\r
366                                 }\r
367                         }\r
368                 }\r
369 \r
370                 if (skip) {\r
371                         // s_fixEntry[i] found in original Scancode Map, so don't fix it\r
372                         continue;\r
373                 }\r
374 \r
375                 // add fix entry to fixMap\r
376                 fixMap->entry[fixMap->count - 1] = s_fixEntry[i];\r
377                 fixMap->entry[fixMap->count] = 0;\r
378                 fixMap->count++;\r
379                 fixSize += 4;\r
380         }\r
381 \r
382         ret = reg.write(_T("Scancode Map"), reinterpret_cast<BYTE*>(fixMap), fixSize);\r
383         if (ret == false) {\r
384                 result = 1;\r
385                 goto exit;\r
386         }\r
387 \r
388         result = update();\r
389 \r
390         if (origMap) {\r
391                 ret = reg.write(_T("Scancode Map"), reinterpret_cast<BYTE*>(origMap), origSize);\r
392         } else {\r
393                 ret = reg.remove(_T("Scancode Map"));\r
394         }\r
395         if (ret == false) {\r
396                 result = 1;\r
397                 goto exit;\r
398         }\r
399 \r
400 exit:\r
401         free(origMap);\r
402         origMap = NULL;\r
403 \r
404         free(fixMap);\r
405         fixMap = NULL;\r
406 \r
407         return result;\r
408 }\r
409 \r
410 int FixScancodeMap::restore()\r
411 {\r
412         return update();\r
413 }\r
414 \r
415 const DWORD FixScancodeMap::s_fixEntryNum = 4;\r
416 const DWORD FixScancodeMap::s_fixEntry[] = {\r
417         0x003ae03a,\r
418         0x0029e029,\r
419         0x0070e070,\r
420         0x003b001e,\r
421 };\r
422 \r