OSDN Git Service

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