OSDN Git Service

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