上一篇文章我们实现的隐藏进程如果重新打开任务管理器或者被隐藏的进程就没有隐藏的效果了。为了弥补这个问题,我们不仅需要钩取当前运行的所有进程,还要钩取将来运行的所有进程。由于所有的进程都是由父进程使用CreateProcess创建的,所以只要钩取父进程(通常是explorer.exe)的CreateProcess将dll注入所有子进程就可以实现了。要注意下面两个问题。
1.CreateProcess同样有CreateProcessA和CreateProcessW两个版本。
2.为了使得dll文件能注入所有运行进程,首先要把dll复制到%windir%文件夹中,在XP中也就是C:\WINDOWS\system32。


HideProc2.cpp

[cpp] view plaincopy
  1. #include "windows.h"
  2. #include "stdio.h"
  3. #include "tlhelp32.h"
  4. #include "tchar.h"
  5. enum {INJECTION_MODE = 0, EJECTION_MODE};
  6. BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
  7. {
  8. TOKEN_PRIVILEGES tp;
  9. HANDLE hToken;
  10. LUID luid;
  11. if( !OpenProcessToken(GetCurrentProcess(),
  12. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  13. &hToken) )
  14. {
  15. printf("OpenProcessToken error: %u\n", GetLastError());
  16. return FALSE;
  17. }
  18. if( !LookupPrivilegeValue(NULL,            // lookup privilege on local system
  19. lpszPrivilege,   // privilege to lookup
  20. &luid) )         // receives LUID of privilege
  21. {
  22. printf("LookupPrivilegeValue error: %u\n", GetLastError() );
  23. return FALSE;
  24. }
  25. tp.PrivilegeCount = 1;
  26. tp.Privileges[0].Luid = luid;
  27. if( bEnablePrivilege )
  28. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  29. else
  30. tp.Privileges[0].Attributes = 0;
  31. // Enable the privilege or disable all privileges.
  32. if( !AdjustTokenPrivileges(hToken,
  33. FALSE,
  34. &tp,
  35. sizeof(TOKEN_PRIVILEGES),
  36. (PTOKEN_PRIVILEGES) NULL,
  37. (PDWORD) NULL) )
  38. {
  39. printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
  40. return FALSE;
  41. }
  42. if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
  43. {
  44. printf("The token does not have the specified privilege. \n");
  45. return FALSE;
  46. }
  47. return TRUE;
  48. }
  49. BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
  50. {
  51. HANDLE                  hProcess, hThread;
  52. LPVOID                  pRemoteBuf;
  53. DWORD                   dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);
  54. LPTHREAD_START_ROUTINE  pThreadProc;
  55. if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
  56. {
  57. printf("OpenProcess(%d) failed!!!\n", dwPID);
  58. return FALSE;
  59. }
  60. pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,
  61. MEM_COMMIT, PAGE_READWRITE);
  62. WriteProcessMemory(hProcess, pRemoteBuf,
  63. (LPVOID)szDllPath, dwBufSize, NULL);
  64. pThreadProc = (LPTHREAD_START_ROUTINE)
  65. GetProcAddress(GetModuleHandle(L"kernel32.dll"),
  66. "LoadLibraryW");
  67. hThread = CreateRemoteThread(hProcess, NULL, 0,
  68. pThreadProc, pRemoteBuf, 0, NULL);
  69. WaitForSingleObject(hThread, INFINITE);
  70. VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
  71. CloseHandle(hThread);
  72. CloseHandle(hProcess);
  73. return TRUE;
  74. }
  75. BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath)
  76. {
  77. BOOL                    bMore = FALSE, bFound = FALSE;
  78. HANDLE                  hSnapshot, hProcess, hThread;
  79. MODULEENTRY32           me = { sizeof(me) };
  80. LPTHREAD_START_ROUTINE  pThreadProc;
  81. if( INVALID_HANDLE_VALUE ==
  82. (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) )
  83. return FALSE;
  84. bMore = Module32First(hSnapshot, &me);
  85. for( ; bMore ; bMore = Module32Next(hSnapshot, &me) )
  86. {
  87. if( !_tcsicmp(me.szModule, szDllPath) ||
  88. !_tcsicmp(me.szExePath, szDllPath) )
  89. {
  90. bFound = TRUE;
  91. break;
  92. }
  93. }
  94. if( !bFound )
  95. {
  96. CloseHandle(hSnapshot);
  97. return FALSE;
  98. }
  99. if( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
  100. {
  101. printf("OpenProcess(%d) failed!!!\n", dwPID);
  102. CloseHandle(hSnapshot);
  103. return FALSE;
  104. }
  105. pThreadProc = (LPTHREAD_START_ROUTINE)
  106. GetProcAddress(GetModuleHandle(L"kernel32.dll"),
  107. "FreeLibrary");
  108. hThread = CreateRemoteThread(hProcess, NULL, 0,
  109. pThreadProc, me.modBaseAddr, 0, NULL);
  110. WaitForSingleObject(hThread, INFINITE);
  111. CloseHandle(hThread);
  112. CloseHandle(hProcess);
  113. CloseHandle(hSnapshot);
  114. return TRUE;
  115. }
  116. BOOL InjectAllProcess(int nMode, LPCTSTR szDllPath)
  117. {
  118. DWORD                   dwPID = 0;
  119. HANDLE                  hSnapShot = INVALID_HANDLE_VALUE;
  120. PROCESSENTRY32          pe;
  121. // Get the snapshot of the system
  122. pe.dwSize = sizeof( PROCESSENTRY32 );
  123. hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );
  124. // find process
  125. Process32First(hSnapShot, &pe);
  126. do
  127. {
  128. dwPID = pe.th32ProcessID;
  129. if( dwPID < 100 )
  130. continue;
  131. if( nMode == INJECTION_MODE )
  132. InjectDll(dwPID, szDllPath);
  133. else
  134. EjectDll(dwPID, szDllPath);
  135. } while( Process32Next(hSnapShot, &pe) );
  136. CloseHandle(hSnapShot);
  137. return TRUE;
  138. }
  139. int _tmain(int argc, TCHAR* argv[])
  140. {
  141. int nMode = INJECTION_MODE;
  142. if( argc != 3 )
  143. {
  144. printf("\n Usage  : HideProc2.exe <-hide|-show> <dll path>\n\n");
  145. return 1;
  146. }
  147. // change privilege
  148. SetPrivilege(SE_DEBUG_NAME, TRUE);
  149. // Inject(Eject) Dll to all process
  150. if( !_tcsicmp(argv[1], L"-show") )
  151. nMode = EJECTION_MODE;
  152. InjectAllProcess(nMode, argv[2]);
  153. return 0;
  154. }

stealth2.cpp

[cpp] view plaincopy
  1. #include "windows.h"
  2. #include "stdio.h"
  3. #include "tchar.h"
  4. #define STR_MODULE_NAME                 (L"stealth2.dll")
  5. #define STR_HIDE_PROCESS_NAME           (L"notepad.exe")
  6. #define STATUS_SUCCESS                  (0x00000000L)
  7. typedef LONG NTSTATUS;
  8. typedef enum _SYSTEM_INFORMATION_CLASS {
  9. SystemBasicInformation = 0,
  10. SystemPerformanceInformation = 2,
  11. SystemTimeOfDayInformation = 3,
  12. SystemProcessInformation = 5,
  13. SystemProcessorPerformanceInformation = 8,
  14. SystemInterruptInformation = 23,
  15. SystemExceptionInformation = 33,
  16. SystemRegistryQuotaInformation = 37,
  17. SystemLookasideInformation = 45
  18. } SYSTEM_INFORMATION_CLASS;
  19. typedef struct _SYSTEM_PROCESS_INFORMATION {
  20. ULONG NextEntryOffset;
  21. BYTE Reserved1[52];
  22. PVOID Reserved2[3];
  23. HANDLE UniqueProcessId;
  24. PVOID Reserved3;
  25. ULONG HandleCount;
  26. BYTE Reserved4[4];
  27. PVOID Reserved5[11];
  28. SIZE_T PeakPagefileUsage;
  29. SIZE_T PrivatePageCount;
  30. LARGE_INTEGER Reserved6[6];
  31. } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
  32. typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)(
  33. SYSTEM_INFORMATION_CLASS SystemInformationClass,
  34. PVOID SystemInformation,
  35. ULONG SystemInformationLength,
  36. PULONG ReturnLength);
  37. typedef BOOL (WINAPI *PFCREATEPROCESSA)(
  38. LPCTSTR lpApplicationName,
  39. LPTSTR lpCommandLine,
  40. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  41. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  42. BOOL bInheritHandles,
  43. DWORD dwCreationFlags,
  44. LPVOID lpEnvironment,
  45. LPCTSTR lpCurrentDirectory,
  46. LPSTARTUPINFO lpStartupInfo,
  47. LPPROCESS_INFORMATION lpProcessInformation
  48. );
  49. typedef BOOL (WINAPI *PFCREATEPROCESSW)(
  50. LPCTSTR lpApplicationName,
  51. LPTSTR lpCommandLine,
  52. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  53. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  54. BOOL bInheritHandles,
  55. DWORD dwCreationFlags,
  56. LPVOID lpEnvironment,
  57. LPCTSTR lpCurrentDirectory,
  58. LPSTARTUPINFO lpStartupInfo,
  59. LPPROCESS_INFORMATION lpProcessInformation
  60. );
  61. BYTE g_pOrgCPA[5] = {0,};
  62. BYTE g_pOrgCPW[5] = {0,};
  63. BYTE g_pOrgZwQSI[5] = {0,};
  64. BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes)
  65. {
  66. FARPROC pFunc;
  67. DWORD dwOldProtect, dwAddress;
  68. BYTE pBuf[5] = {0xE9, 0, };
  69. PBYTE pByte;
  70. pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
  71. pByte = (PBYTE)pFunc;
  72. if( pByte[0] == 0xE9 )
  73. return FALSE;
  74. VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  75. memcpy(pOrgBytes, pFunc, 5);
  76. dwAddress = (DWORD)pfnNew - (DWORD)pFunc - 5;
  77. memcpy(&pBuf[1], &dwAddress, 4);
  78. memcpy(pFunc, pBuf, 5);
  79. VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
  80. return TRUE;
  81. }
  82. BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes)
  83. {
  84. FARPROC pFunc;
  85. DWORD dwOldProtect;
  86. PBYTE pByte;
  87. pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
  88. pByte = (PBYTE)pFunc;
  89. if( pByte[0] != 0xE9 )
  90. return FALSE;
  91. VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  92. memcpy(pFunc, pOrgBytes, 5);
  93. VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
  94. return TRUE;
  95. }
  96. BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
  97. {
  98. TOKEN_PRIVILEGES tp;
  99. HANDLE hToken;
  100. LUID luid;
  101. if( !OpenProcessToken(GetCurrentProcess(),
  102. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  103. &hToken) )
  104. {
  105. printf("OpenProcessToken error: %u\n", GetLastError());
  106. return FALSE;
  107. }
  108. if( !LookupPrivilegeValue(NULL,             // lookup privilege on local system
  109. lpszPrivilege,    // privilege to lookup
  110. &luid) )          // receives LUID of privilege
  111. {
  112. printf("LookupPrivilegeValue error: %u\n", GetLastError() );
  113. return FALSE;
  114. }
  115. tp.PrivilegeCount = 1;
  116. tp.Privileges[0].Luid = luid;
  117. if( bEnablePrivilege )
  118. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  119. else
  120. tp.Privileges[0].Attributes = 0;
  121. // Enable the privilege or disable all privileges.
  122. if( !AdjustTokenPrivileges(hToken,
  123. FALSE,
  124. &tp,
  125. sizeof(TOKEN_PRIVILEGES),
  126. (PTOKEN_PRIVILEGES) NULL,
  127. (PDWORD) NULL) )
  128. {
  129. printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
  130. return FALSE;
  131. }
  132. if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
  133. {
  134. printf("The token does not have the specified privilege. \n");
  135. return FALSE;
  136. }
  137. return TRUE;
  138. }
  139. BOOL InjectDll2(HANDLE hProcess, LPCTSTR szDllName)
  140. {
  141. HANDLE hThread;
  142. LPVOID pRemoteBuf;
  143. DWORD dwBufSize = (DWORD)(_tcslen(szDllName) + 1) * sizeof(TCHAR);
  144. FARPROC pThreadProc;
  145. pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,
  146. MEM_COMMIT, PAGE_READWRITE);
  147. if( pRemoteBuf == NULL )
  148. return FALSE;
  149. WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName,
  150. dwBufSize, NULL);
  151. pThreadProc = GetProcAddress(GetModuleHandleA("kernel32.dll"),
  152. "LoadLibraryW");
  153. hThread = CreateRemoteThread(hProcess, NULL, 0,
  154. (LPTHREAD_START_ROUTINE)pThreadProc,
  155. pRemoteBuf, 0, NULL);
  156. WaitForSingleObject(hThread, INFINITE);
  157. VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
  158. CloseHandle(hThread);
  159. return TRUE;
  160. }
  161. NTSTATUS WINAPI NewZwQuerySystemInformation(
  162. SYSTEM_INFORMATION_CLASS SystemInformationClass,
  163. PVOID SystemInformation,
  164. ULONG SystemInformationLength,
  165. PULONG ReturnLength)
  166. {
  167. NTSTATUS status;
  168. FARPROC pFunc;
  169. PSYSTEM_PROCESS_INFORMATION pCur, pPrev;
  170. char szProcName[MAX_PATH] = {0,};
  171. unhook_by_code("ntdll.dll", "ZwQuerySystemInformation", g_pOrgZwQSI);
  172. pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"),
  173. "ZwQuerySystemInformation");
  174. status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)
  175. (SystemInformationClass, SystemInformation,
  176. SystemInformationLength, ReturnLength);
  177. if( status != STATUS_SUCCESS )
  178. goto __NTQUERYSYSTEMINFORMATION_END;
  179. if( SystemInformationClass == SystemProcessInformation )
  180. {
  181. pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;
  182. while(TRUE)
  183. {
  184. if(pCur->Reserved2[1] != NULL)
  185. {
  186. if(!_tcsicmp((PWSTR)pCur->Reserved2[1], STR_HIDE_PROCESS_NAME))
  187. {
  188. if(pCur->NextEntryOffset == 0)
  189. pPrev->NextEntryOffset = 0;
  190. else
  191. pPrev->NextEntryOffset += pCur->NextEntryOffset;
  192. }
  193. else
  194. pPrev = pCur;
  195. }
  196. if(pCur->NextEntryOffset == 0)
  197. break;
  198. pCur = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pCur + pCur->NextEntryOffset);
  199. }
  200. }
  201. __NTQUERYSYSTEMINFORMATION_END:
  202. hook_by_code("ntdll.dll", "ZwQuerySystemInformation",
  203. (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);
  204. return status;
  205. }
  206. BOOL WINAPI NewCreateProcessA(
  207. LPCTSTR lpApplicationName,
  208. LPTSTR lpCommandLine,
  209. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  210. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  211. BOOL bInheritHandles,
  212. DWORD dwCreationFlags,
  213. LPVOID lpEnvironment,
  214. LPCTSTR lpCurrentDirectory,
  215. LPSTARTUPINFO lpStartupInfo,
  216. LPPROCESS_INFORMATION lpProcessInformation
  217. )
  218. {
  219. BOOL bRet;
  220. FARPROC pFunc;
  221. unhook_by_code("kernel32.dll", "CreateProcessA", g_pOrgCPA);
  222. pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessA");
  223. bRet = ((PFCREATEPROCESSA)pFunc)(lpApplicationName,
  224. lpCommandLine,
  225. lpProcessAttributes,
  226. lpThreadAttributes,
  227. bInheritHandles,
  228. dwCreationFlags,
  229. lpEnvironment,
  230. lpCurrentDirectory,
  231. lpStartupInfo,
  232. lpProcessInformation);
  233. if( bRet )
  234. InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);
  235. hook_by_code("kernel32.dll", "CreateProcessA",
  236. (PROC)NewCreateProcessA, g_pOrgCPA);
  237. return bRet;
  238. }
  239. BOOL WINAPI NewCreateProcessW(
  240. LPCTSTR lpApplicationName,
  241. LPTSTR lpCommandLine,
  242. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  243. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  244. BOOL bInheritHandles,
  245. DWORD dwCreationFlags,
  246. LPVOID lpEnvironment,
  247. LPCTSTR lpCurrentDirectory,
  248. LPSTARTUPINFO lpStartupInfo,
  249. LPPROCESS_INFORMATION lpProcessInformation
  250. )
  251. {
  252. BOOL bRet;
  253. FARPROC pFunc;
  254. unhook_by_code("kernel32.dll", "CreateProcessW", g_pOrgCPW);
  255. pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessW");
  256. bRet = ((PFCREATEPROCESSW)pFunc)(lpApplicationName,
  257. lpCommandLine,
  258. lpProcessAttributes,
  259. lpThreadAttributes,
  260. bInheritHandles,
  261. dwCreationFlags,
  262. lpEnvironment,
  263. lpCurrentDirectory,
  264. lpStartupInfo,
  265. lpProcessInformation);
  266. if( bRet )
  267. InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);
  268. hook_by_code("kernel32.dll", "CreateProcessW",
  269. (PROC)NewCreateProcessW, g_pOrgCPW);
  270. return bRet;
  271. }
  272. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
  273. {
  274. char            szCurProc[MAX_PATH] = {0,};
  275. char            *p = NULL;
  276. GetModuleFileNameA(NULL, szCurProc, MAX_PATH);
  277. p = strrchr(szCurProc, '\\');
  278. if( (p != NULL) && !_stricmp(p+1, "HideProc2.exe") )
  279. return TRUE;
  280. SetPrivilege(SE_DEBUG_NAME, TRUE);
  281. switch( fdwReason )
  282. {
  283. case DLL_PROCESS_ATTACH :
  284. hook_by_code("kernel32.dll", "CreateProcessA",
  285. (PROC)NewCreateProcessA, g_pOrgCPA);
  286. hook_by_code("kernel32.dll", "CreateProcessW",
  287. (PROC)NewCreateProcessW, g_pOrgCPW);
  288. hook_by_code("ntdll.dll", "ZwQuerySystemInformation",
  289. (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);
  290. break;
  291. case DLL_PROCESS_DETACH :
  292. unhook_by_code("kernel32.dll", "CreateProcessA",
  293. g_pOrgCPA);
  294. unhook_by_code("kernel32.dll", "CreateProcessW",
  295. g_pOrgCPW);
  296. unhook_by_code("ntdll.dll", "ZwQuerySystemInformation",
  297. g_pOrgZwQSI);
  298. break;
  299. }
  300. return TRUE;
  301. }

但是每当程序内部调用CreateProcess时NewCreateProcess都会反复执行脱钩/挂钩操作,不仅会造成整体性能低下,在多线程环境下还会产生运行时错误。使用Hot Patch技术修改7个字节代码,比修改5个字节代码更加稳定。先来看看常用API代码的起始部分,以CreateProcessA为例。

API代码以2个字节的MOV EDI,EDI指令开始,上方还有5个nop指令,一共7个字节没有意义的指令,这就是为了方便打热补丁用的。将API起始代码前的5个字节修改为FAR JMP指令,然后将API起始代码处的2个字节修改为SHORT JMP指令跳转到前面FAR JMP处。
我们来分析一下源代码,看看是怎么实现的。
因为HideProc2.cpp不需要改动,所以主要讲解stealth3.cpp。首先分析hook_by_hotpatch函数。

[cpp] view plaincopy
  1. BOOL hook_by_hotpatch(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew)
  2. {
  3. FARPROC pFunc;
  4. DWORD dwOldProtect, dwAddress;
  5. BYTE pBuf[5] = { 0xE9, 0, };
  6. BYTE pBuf2[2] = { 0xEB, 0xF9 };
  7. PBYTE pByte;
  8. pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
  9. pByte = (PBYTE)pFunc;
  10. if( pByte[0] == 0xEB )
  11. return FALSE;
  12. VirtualProtect((LPVOID)((DWORD)pFunc - 5), 7, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  13. dwAddress = (DWORD)pfnNew - (DWORD)pFunc;
  14. memcpy(&pBuf[1], &dwAddress, 4);
  15. memcpy((LPVOID)((DWORD)pFunc - 5), pBuf, 5);
  16. memcpy(pFunc, pBuf2, 2);
  17. VirtualProtect((LPVOID)((DWORD)pFunc - 5), 7, dwOldProtect, &dwOldProtect);
  18. return TRUE;
  19. }

计算一下JMP XXXXXXXX和JMP YY的地址。
XXXXXXXX
=要跳转的地址-当前指令地址-当前指令长度(5)
=(DWORD)pfnNew-((DWORD)pFunc-5)-5
=(DWORD)pfnNew-(DWORD)pFunc
YY
=要跳转的地址-当前指令地址-当前指令长度(2)
=(pFunc-5)-pFunc-2=-7=0xF9
YY的值是固定的,硬编码到源代码里面就可以了。
接下来是unhook_by_hotpatch函数,它用来恢复修改后的指令。这些指令同样是固定的,所以还是硬编码到源代码里面。

[cpp] view plaincopy
  1. BOOL unhook_by_hotpatch(LPCSTR szDllName, LPCSTR szFuncName)
  2. {
  3. FARPROC pFunc;
  4. DWORD dwOldProtect;
  5. PBYTE pByte;
  6. BYTE pBuf[5] = { 0x90, 0x90, 0x90, 0x90, 0x90 };
  7. BYTE pBuf2[2] = { 0x8B, 0xFF };
  8. pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
  9. pByte = (PBYTE)pFunc;
  10. if( pByte[0] != 0xEB )
  11. return FALSE;
  12. VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  13. memcpy((LPVOID)((DWORD)pFunc - 5), pBuf, 5);
  14. memcpy(pFunc, pBuf2, 2);
  15. VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
  16. return TRUE;
  17. }

最后是NewCreateProcessA函数。和前面不同的是,NewCreateProcessA中不再需要调用unhook_by_code和hook_by_code函数,而是添加了计算pFunc的语句,用来跳过API起始位置处的JMP YY指令,使得能够达到与调用原API一样的效果。

[cpp] view plaincopy
  1. BOOL WINAPI NewCreateProcessA(
  2. LPCTSTR lpApplicationName,
  3. LPTSTR lpCommandLine,
  4. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  5. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  6. BOOL bInheritHandles,
  7. DWORD dwCreationFlags,
  8. LPVOID lpEnvironment,
  9. LPCTSTR lpCurrentDirectory,
  10. LPSTARTUPINFO lpStartupInfo,
  11. LPPROCESS_INFORMATION lpProcessInformation
  12. )
  13. {
  14. BOOL bRet;
  15. FARPROC pFunc;
  16. pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessA");
  17. pFunc = (FARPROC)((DWORD)pFunc + 2);
  18. bRet = ((PFCREATEPROCESSA)pFunc)(lpApplicationName,
  19. lpCommandLine,
  20. lpProcessAttributes,
  21. lpThreadAttributes,
  22. bInheritHandles,
  23. dwCreationFlags,
  24. lpEnvironment,
  25. lpCurrentDirectory,
  26. lpStartupInfo,
  27. lpProcessInformation);
  28. if( bRet )
  29. InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);
  30. return bRet;
  31. }

完整的代码如下。

[cpp] view plaincopy
  1. #include "windows.h"
  2. #include "stdio.h"
  3. #include "tchar.h"
  4. #define STR_MODULE_NAME                 (L"stealth3.dll")
  5. #define STR_HIDE_PROCESS_NAME           (L"notepad.exe")
  6. #define STATUS_SUCCESS                  (0x00000000L)
  7. typedef LONG NTSTATUS;
  8. typedef enum _SYSTEM_INFORMATION_CLASS {
  9. SystemBasicInformation = 0,
  10. SystemPerformanceInformation = 2,
  11. SystemTimeOfDayInformation = 3,
  12. SystemProcessInformation = 5,
  13. SystemProcessorPerformanceInformation = 8,
  14. SystemInterruptInformation = 23,
  15. SystemExceptionInformation = 33,
  16. SystemRegistryQuotaInformation = 37,
  17. SystemLookasideInformation = 45
  18. } SYSTEM_INFORMATION_CLASS;
  19. typedef struct _SYSTEM_PROCESS_INFORMATION {
  20. ULONG NextEntryOffset;
  21. BYTE Reserved1[52];
  22. PVOID Reserved2[3];
  23. HANDLE UniqueProcessId;
  24. PVOID Reserved3;
  25. ULONG HandleCount;
  26. BYTE Reserved4[4];
  27. PVOID Reserved5[11];
  28. SIZE_T PeakPagefileUsage;
  29. SIZE_T PrivatePageCount;
  30. LARGE_INTEGER Reserved6[6];
  31. } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
  32. typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)(
  33. SYSTEM_INFORMATION_CLASS SystemInformationClass,
  34. PVOID SystemInformation,
  35. ULONG SystemInformationLength,
  36. PULONG ReturnLength);
  37. typedef BOOL (WINAPI *PFCREATEPROCESSA)(
  38. LPCTSTR lpApplicationName,
  39. LPTSTR lpCommandLine,
  40. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  41. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  42. BOOL bInheritHandles,
  43. DWORD dwCreationFlags,
  44. LPVOID lpEnvironment,
  45. LPCTSTR lpCurrentDirectory,
  46. LPSTARTUPINFO lpStartupInfo,
  47. LPPROCESS_INFORMATION lpProcessInformation
  48. );
  49. typedef BOOL (WINAPI *PFCREATEPROCESSW)(
  50. LPCTSTR lpApplicationName,
  51. LPTSTR lpCommandLine,
  52. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  53. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  54. BOOL bInheritHandles,
  55. DWORD dwCreationFlags,
  56. LPVOID lpEnvironment,
  57. LPCTSTR lpCurrentDirectory,
  58. LPSTARTUPINFO lpStartupInfo,
  59. LPPROCESS_INFORMATION lpProcessInformation
  60. );
  61. BYTE g_pOrgZwQSI[5] = {0,};
  62. BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes)
  63. {
  64. FARPROC pFunc;
  65. DWORD dwOldProtect, dwAddress;
  66. BYTE pBuf[5] = {0xE9, 0, };
  67. PBYTE pByte;
  68. pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
  69. pByte = (PBYTE)pFunc;
  70. if( pByte[0] == 0xE9 )
  71. return FALSE;
  72. VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  73. memcpy(pOrgBytes, pFunc, 5);
  74. dwAddress = (DWORD)pfnNew - (DWORD)pFunc - 5;
  75. memcpy(&pBuf[1], &dwAddress, 4);
  76. memcpy(pFunc, pBuf, 5);
  77. VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
  78. return TRUE;
  79. }
  80. BOOL hook_by_hotpatch(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew)
  81. {
  82. FARPROC pFunc;
  83. DWORD dwOldProtect, dwAddress;
  84. BYTE pBuf[5] = { 0xE9, 0, };
  85. BYTE pBuf2[2] = { 0xEB, 0xF9 };
  86. PBYTE pByte;
  87. pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
  88. pByte = (PBYTE)pFunc;
  89. if( pByte[0] == 0xEB )
  90. return FALSE;
  91. VirtualProtect((LPVOID)((DWORD)pFunc - 5), 7, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  92. dwAddress = (DWORD)pfnNew - (DWORD)pFunc;
  93. memcpy(&pBuf[1], &dwAddress, 4);
  94. memcpy((LPVOID)((DWORD)pFunc - 5), pBuf, 5);
  95. memcpy(pFunc, pBuf2, 2);
  96. VirtualProtect((LPVOID)((DWORD)pFunc - 5), 7, dwOldProtect, &dwOldProtect);
  97. return TRUE;
  98. }
  99. BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes)
  100. {
  101. FARPROC pFunc;
  102. DWORD dwOldProtect;
  103. PBYTE pByte;
  104. pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
  105. pByte = (PBYTE)pFunc;
  106. if( pByte[0] != 0xE9 )
  107. return FALSE;
  108. VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  109. memcpy(pFunc, pOrgBytes, 5);
  110. VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
  111. return TRUE;
  112. }
  113. BOOL unhook_by_hotpatch(LPCSTR szDllName, LPCSTR szFuncName)
  114. {
  115. FARPROC pFunc;
  116. DWORD dwOldProtect;
  117. PBYTE pByte;
  118. BYTE pBuf[5] = { 0x90, 0x90, 0x90, 0x90, 0x90 };
  119. BYTE pBuf2[2] = { 0x8B, 0xFF };
  120. pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
  121. pByte = (PBYTE)pFunc;
  122. if( pByte[0] != 0xEB )
  123. return FALSE;
  124. VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  125. memcpy((LPVOID)((DWORD)pFunc - 5), pBuf, 5);
  126. memcpy(pFunc, pBuf2, 2);
  127. VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
  128. return TRUE;
  129. }
  130. BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
  131. {
  132. TOKEN_PRIVILEGES tp;
  133. HANDLE hToken;
  134. LUID luid;
  135. if( !OpenProcessToken(GetCurrentProcess(),
  136. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  137. &hToken) )
  138. {
  139. printf("OpenProcessToken error: %u\n", GetLastError());
  140. return FALSE;
  141. }
  142. if( !LookupPrivilegeValue(NULL,
  143. lpszPrivilege,
  144. &luid) )
  145. {
  146. printf("LookupPrivilegeValue error: %u\n", GetLastError() );
  147. return FALSE;
  148. }
  149. tp.PrivilegeCount = 1;
  150. tp.Privileges[0].Luid = luid;
  151. if( bEnablePrivilege )
  152. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  153. else
  154. tp.Privileges[0].Attributes = 0;
  155. if( !AdjustTokenPrivileges(hToken,
  156. FALSE,
  157. &tp,
  158. sizeof(TOKEN_PRIVILEGES),
  159. (PTOKEN_PRIVILEGES) NULL,
  160. (PDWORD) NULL) )
  161. {
  162. printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
  163. return FALSE;
  164. }
  165. if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
  166. {
  167. printf("The token does not have the specified privilege. \n");
  168. return FALSE;
  169. }
  170. return TRUE;
  171. }
  172. BOOL InjectDll2(HANDLE hProcess, LPCTSTR szDllName)
  173. {
  174. HANDLE hThread;
  175. LPVOID pRemoteBuf;
  176. DWORD dwBufSize = (DWORD)(_tcslen(szDllName) + 1) * sizeof(TCHAR);
  177. FARPROC pThreadProc;
  178. pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,
  179. MEM_COMMIT, PAGE_READWRITE);
  180. if( pRemoteBuf == NULL )
  181. return FALSE;
  182. WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName,
  183. dwBufSize, NULL);
  184. pThreadProc = GetProcAddress(GetModuleHandleA("kernel32.dll"),
  185. "LoadLibraryW");
  186. hThread = CreateRemoteThread(hProcess, NULL, 0,
  187. (LPTHREAD_START_ROUTINE)pThreadProc,
  188. pRemoteBuf, 0, NULL);
  189. WaitForSingleObject(hThread, INFINITE);
  190. VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
  191. CloseHandle(hThread);
  192. return TRUE;
  193. }
  194. NTSTATUS WINAPI NewZwQuerySystemInformation(
  195. SYSTEM_INFORMATION_CLASS SystemInformationClass,
  196. PVOID SystemInformation,
  197. ULONG SystemInformationLength,
  198. PULONG ReturnLength)
  199. {
  200. NTSTATUS status;
  201. FARPROC pFunc;
  202. PSYSTEM_PROCESS_INFORMATION pCur, pPrev;
  203. char szProcName[MAX_PATH] = {0,};
  204. unhook_by_code("ntdll.dll", "ZwQuerySystemInformation", g_pOrgZwQSI);
  205. pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"),
  206. "ZwQuerySystemInformation");
  207. status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)
  208. (SystemInformationClass, SystemInformation,
  209. SystemInformationLength, ReturnLength);
  210. if( status != STATUS_SUCCESS )
  211. goto __NTQUERYSYSTEMINFORMATION_END;
  212. if( SystemInformationClass == SystemProcessInformation )
  213. {
  214. pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;
  215. while(TRUE)
  216. {
  217. if(pCur->Reserved2[1] != NULL)
  218. {
  219. if(!_tcsicmp((PWSTR)pCur->Reserved2[1], STR_HIDE_PROCESS_NAME))
  220. {
  221. if(pCur->NextEntryOffset == 0)
  222. pPrev->NextEntryOffset = 0;
  223. else
  224. pPrev->NextEntryOffset += pCur->NextEntryOffset;
  225. }
  226. else
  227. pPrev = pCur;
  228. }
  229. if(pCur->NextEntryOffset == 0)
  230. break;
  231. pCur = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pCur + pCur->NextEntryOffset);
  232. }
  233. }
  234. __NTQUERYSYSTEMINFORMATION_END:
  235. hook_by_code("ntdll.dll", "ZwQuerySystemInformation",
  236. (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);
  237. return status;
  238. }
  239. BOOL WINAPI NewCreateProcessA(
  240. LPCTSTR lpApplicationName,
  241. LPTSTR lpCommandLine,
  242. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  243. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  244. BOOL bInheritHandles,
  245. DWORD dwCreationFlags,
  246. LPVOID lpEnvironment,
  247. LPCTSTR lpCurrentDirectory,
  248. LPSTARTUPINFO lpStartupInfo,
  249. LPPROCESS_INFORMATION lpProcessInformation
  250. )
  251. {
  252. BOOL bRet;
  253. FARPROC pFunc;
  254. pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessA");
  255. pFunc = (FARPROC)((DWORD)pFunc + 2);
  256. bRet = ((PFCREATEPROCESSA)pFunc)(lpApplicationName,
  257. lpCommandLine,
  258. lpProcessAttributes,
  259. lpThreadAttributes,
  260. bInheritHandles,
  261. dwCreationFlags,
  262. lpEnvironment,
  263. lpCurrentDirectory,
  264. lpStartupInfo,
  265. lpProcessInformation);
  266. if( bRet )
  267. InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);
  268. return bRet;
  269. }
  270. BOOL WINAPI NewCreateProcessW(
  271. LPCTSTR lpApplicationName,
  272. LPTSTR lpCommandLine,
  273. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  274. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  275. BOOL bInheritHandles,
  276. DWORD dwCreationFlags,
  277. LPVOID lpEnvironment,
  278. LPCTSTR lpCurrentDirectory,
  279. LPSTARTUPINFO lpStartupInfo,
  280. LPPROCESS_INFORMATION lpProcessInformation
  281. )
  282. {
  283. BOOL bRet;
  284. FARPROC pFunc;
  285. pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessW");
  286. pFunc = (FARPROC)((DWORD)pFunc + 2);
  287. bRet = ((PFCREATEPROCESSW)pFunc)(lpApplicationName,
  288. lpCommandLine,
  289. lpProcessAttributes,
  290. lpThreadAttributes,
  291. bInheritHandles,
  292. dwCreationFlags,
  293. lpEnvironment,
  294. lpCurrentDirectory,
  295. lpStartupInfo,
  296. lpProcessInformation);
  297. if( bRet )
  298. InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);
  299. return bRet;
  300. }
  301. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
  302. {
  303. char            szCurProc[MAX_PATH] = {0,};
  304. char            *p = NULL;
  305. GetModuleFileNameA(NULL, szCurProc, MAX_PATH);
  306. p = strrchr(szCurProc, '\\');
  307. if( (p != NULL) && !_stricmp(p+1, "HideProc2.exe") )
  308. return TRUE;
  309. SetPrivilege(SE_DEBUG_NAME, TRUE);
  310. switch( fdwReason )
  311. {
  312. case DLL_PROCESS_ATTACH :
  313. hook_by_hotpatch("kernel32.dll", "CreateProcessA",
  314. (PROC)NewCreateProcessA);
  315. hook_by_hotpatch("kernel32.dll", "CreateProcessW",
  316. (PROC)NewCreateProcessW);
  317. hook_by_code("ntdll.dll", "ZwQuerySystemInformation",
  318. (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);
  319. break;
  320. case DLL_PROCESS_DETACH :
  321. unhook_by_hotpatch("kernel32.dll", "CreateProcessA");
  322. unhook_by_hotpatch("kernel32.dll", "CreateProcessW");
  323. unhook_by_code("ntdll.dll", "ZwQuerySystemInformation",
  324. g_pOrgZwQSI);
  325. break;
  326. }
  327. return TRUE;
  328. }

逆向工程核心原理读书笔记-API钩取之隐藏进程(二)相关推荐

  1. 逆向工程核心原理读书笔记-API钩取之隐藏进程(一)

    简评: 整体看了下代码,其实就是应用层的inline hook, 钩子勾住ntdll.dll里面的ZwQuerySystemInformation函数, xp环境测试成功了,win7测试失败了,不知道 ...

  2. 逆向工程核心原理读书笔记-API钩取之IE浏览器连接控制

    我们通过一个示例来练习钩取IE8的InternetConnect函数,用IE8连接指定网站时,使之连接到另一个网站.和以前钩取CreateProcess不同,这次我们钩取更低级的ZwResumeThr ...

  3. 逆向工程核心原理读书笔记-API钩取之记事本小写转大写

    我们通过一个示例来练习钩取Notepad.exe的WriteFile,保存文件时将小写字母全部转换为大写字母.下面我们先测试一下代码. 运行notepad.exe并查看PID. 在命令行窗口中输入命令 ...

  4. 逆向工程核心原理读书笔记-API钩取之计算器显示中文数字

    我们通过一个示例来练习向计算机进程插入用户的DLL文件,钩取负责向计算器显示文本的SetWindowTextW,使得计算器中显示中文数字而不是原来的阿拉伯数字.钩取前后的原理图如下所示. 下面我们先测 ...

  5. 逆向工程核心原理读书笔记-代码注入

    代码注入是一种向目标进程插入独立运行代码并使之运行的技术,它一般调用CreateRemoteThread()API以远程线程形式运行插入的代码,所以也被称为线程注入. 和DLL注入相比代码注入占用内存 ...

  6. 逆向工程核心原理学习笔记(三):检索API方法

    打开OD,载入程序 鼠标右键,如图. 然后就可以看到程序调用的所有API函数,便于分析. 找到messagebox函数,双击进去,就是函数所在反汇编地址了

  7. 逆向工程核心原理学习笔记(四):检索API方法2-设置断点

    同样,还是用我们的那个helloworld小程序,然后,如图所示,查找所有模块的名称 然后,结果如图所示 在这个界面,我们敲键盘字母,messagebox,一个一个敲出来,就会自己跳到相应的地址,如图 ...

  8. 逆向工程核心原理学习笔记(一):寻找程序的主函数(Main)

    转自:http://blog.csdn.net/qq_36810340/article/details/70169640 首先编译release版本的helloword程序,代码如下: 编译完成,拖进 ...

  9. 逆向工程核心原理学习笔记(十四):栈帧1

    栈帧的话,直接截了一些图,大家看一下就好了,理解起来很简单,就是简单的参数转存. 看完之后,我们需要用一个小程序来进一步学习我们的栈帧了. 下载地址:http://t.cn/RaUSglI 代码写法: ...

最新文章

  1. opengl 教程(21) 聚光灯
  2. Dubbo序列化对象
  3. JZOJ 5390. 【NOIP2017提高A组模拟9.26】逗气
  4. OceanBase架构浅析(一)
  5. 3.odoo的学习(odoo中的视图:tree视图、form视图、search视图)
  6. LVS:三种负载均衡方式比较+另三种负载均衡方式
  7. 关于“Exchange Server 地址列表服务未能响应”的错误解决方法。
  8. R12应付款模块的费用报表(Expense Report)处理流程
  9. Luogu P1963 [NOI2009]变换序列(二分图匹配)
  10. 折腾Java设计模式之状态模式
  11. 一份超详细的VTD安装指南(内容含如何安装ubuntu系统及如何在ubuntu中安装显卡驱动)
  12. 元胞自动机python代码_Python实现元胞自动机(康威生命游戏)
  13. 电机功率与转矩/扭矩的关系
  14. 深圳再添新高校!“深圳海洋大学”,正式获批!
  15. 代理服务器和IP加速器之间有什么关系?
  16. 运维的工作内容是什么?有哪几种分类?
  17. 【DBA】 Oracle 学习路线
  18. Thread.currentThread().interrupt()和Thread.interrupted()和Thread.currentThread().isInterrupted()
  19. php 易信公众开发,易信公众平台接口代码分享
  20. 单片机延时程序的实现

热门文章

  1. MybatisPlus添加操作
  2. AdminLTE基本使用介绍
  3. RocketMQ的存储之消息的同步、异步刷盘
  4. 字符串-字符串的查找和替换
  5. 垃圾回收机制之复制算法
  6. webflux系列--源码解析二
  7. rlm sql mysql.so_UBUUTU7.10上安装配置freeradius+mysql+rp-pppoe手记
  8. 全国首家工资总额负面清单管理试点企业获批
  9. 张首晟:量子计算、人工智能与区块链
  10. java并发编程学习5--forkJoin