EasyHook远程代码注入

    最近一段时间由于使用MinHook的API挂钩不稳定,经常因为挂钩地址错误而导致宿主进程崩溃。听同事介绍了一款智能强大的挂钩引擎EasyHook。它比微软的detours好的一点是它的x64注入支持是免费开源的。不想微软的detours,想搞x64还得购买。

    好了,闲话不多说,先下载EasyHook的开发库,当然有兴趣的同学可以下载源码进行学习。下载地址:http://easyhook.codeplex.com/releases/view/24401。我给的这个是2.6版本的。

    EasyHook提供了两种模式的注入管理。一种是托管代码的注入,另一种是非托管代码的注入。我是学习C++的,所以直接学习了例子中的非托管项目UnmanagedHook。里面给了一个简单的挂钩MessageBeep API的示例。我需要将其改造成支持远程注入的。下面先给出钩子DLL代码:

 
  1. // dllmain.cpp : 定义 DLL 应用程序的入口点。

  2. #include "stdafx.h"

  3. #include "HookApi.h"

  4. #include "easyhook.h"

  5. #include "ntstatus.h"

  6.  
  7. ptrCreateFileW realCreateFileW = NULL;

  8. ptrCreateFileA realCreateFileA = NULL;

  9. HMODULE hKernel32 = NULL;

  10. TRACED_HOOK_HANDLE hHookCreateFileW = new HOOK_TRACE_INFO();

  11. TRACED_HOOK_HANDLE hHookCreateFileA = new HOOK_TRACE_INFO();

  12. NTSTATUS statue;

  13. ULONG HookCreateFileW_ACLEntries[1] = {0};

  14. ULONG HookCreateFileA_ACLEntries[1] = {0};

  15.  
  16. int PrepareRealApiEntry()

  17. {

  18. OutputDebugString(L"PrepareRealApiEntry()\n");

  19.  
  20. // 获取真实函数地址

  21. HMODULE hKernel32 = LoadLibrary(L"Kernel32.dll");

  22. if (hKernel32 == NULL)

  23. {

  24. OutputDebugString(L"LoadLibrary(L\"Kernel32.dll\") Error\n");

  25. return -6002;

  26. }

  27. OutputDebugString(L"LoadLibrary(L\"Kernel32.dll\") OK\n");

  28.  
  29. realCreateFileW = (ptrCreateFileW)GetProcAddress(hKernel32, "CreateFileW");

  30. if (realCreateFileW == NULL)

  31. {

  32. OutputDebugString(L"(ptrCreateFileW)GetProcAddress(hKernel32, \"CreateFileW\") Error\n");

  33. return -6007;

  34. }

  35. OutputDebugString(L"(ptrCreateFileW)GetProcAddress(hKernel32, \"CreateFileW\") OK\n");

  36.  
  37. realCreateFileA = (ptrCreateFileA)GetProcAddress(hKernel32, "CreateFileA");

  38. if (realCreateFileA == NULL)

  39. {

  40. OutputDebugString(L"(ptrCreateFileA)GetProcAddress(hKernel32, \"CreateFileA\") Error\n");

  41. return -6007;

  42. }

  43. OutputDebugString(L"(ptrCreateFileA)GetProcAddress(hKernel32, \"CreateFileA\") OK\n");

  44.  
  45. return 0;

  46. }

  47.  
  48. void DoHook()

  49. {

  50. OutputDebugString(L"DoHook()\n");

  51.  
  52. statue = LhInstallHook(realCreateFileW,

  53. MyCreateFileW,

  54. /*(PVOID)0x12345678*/NULL,

  55. hHookCreateFileW);

  56. if(!SUCCEEDED(statue))

  57. {

  58. switch (statue)

  59. {

  60. case STATUS_NO_MEMORY:

  61. OutputDebugString(L"STATUS_NO_MEMORY\n");

  62. break;

  63. case STATUS_NOT_SUPPORTED:

  64. OutputDebugString(L"STATUS_NOT_SUPPORTED\n");

  65. break;

  66. case STATUS_INSUFFICIENT_RESOURCES:

  67. OutputDebugString(L"STATUS_INSUFFICIENT_RESOURCES\n");

  68. break;

  69. default:

  70. WCHAR dbgstr[512] = {0};

  71. wsprintf(dbgstr, L"%d\n", statue);

  72. OutputDebugString(dbgstr);

  73. }

  74. OutputDebugString(L"LhInstallHook(GetProcAddress(hKernel32, \"CreateFileW\"),MyCreateFileW,(PVOID)0x12345678,hHookCreateFileW); Error\n");

  75. return;

  76. }

  77. OutputDebugString(L"Hook CreateFileW OK\n");

  78.  
  79. statue = LhInstallHook(realCreateFileA,

  80. MyCreateFileA,

  81. /*(PVOID)0x12345678*/NULL,

  82. hHookCreateFileA);

  83. if(!SUCCEEDED(statue))

  84. {

  85. switch (statue)

  86. {

  87. case STATUS_NO_MEMORY:

  88. OutputDebugString(L"STATUS_NO_MEMORY\n");

  89. break;

  90. case STATUS_NOT_SUPPORTED:

  91. OutputDebugString(L"STATUS_NOT_SUPPORTED\n");

  92. break;

  93. case STATUS_INSUFFICIENT_RESOURCES:

  94. OutputDebugString(L"STATUS_INSUFFICIENT_RESOURCES\n");

  95. break;

  96. default:

  97. WCHAR dbgstr[512] = {0};

  98. wsprintf(dbgstr, L"%d\n", statue);

  99. OutputDebugString(dbgstr);

  100. }

  101. OutputDebugString(L"LhInstallHook(GetProcAddress(hKernel32, \"CreateFileA\"),MyCreateFileA,(PVOID)0x12345678,hHookCreateFileA); Error\n");

  102. return;

  103. }

  104. OutputDebugString(L"Hook CreateFileA OK\n");

  105.  
  106.  
  107. // 一定要调用这个函数,否则注入的钩子无法正常运行。

  108. LhSetExclusiveACL(HookCreateFileA_ACLEntries, 1, hHookCreateFileA);

  109. LhSetExclusiveACL(HookCreateFileW_ACLEntries, 1, hHookCreateFileW);

  110.  
  111. }

  112.  
  113. void DoneHook()

  114. {

  115. OutputDebugString(L"DoneHook()\n");

  116.  
  117. // this will also invalidate "hHook", because it is a traced handle...

  118. LhUninstallAllHooks();

  119.  
  120. // this will do nothing because the hook is already removed...

  121. LhUninstallHook(hHookCreateFileA);

  122. LhUninstallHook(hHookCreateFileW);

  123.  
  124. // now we can safely release the traced handle

  125. delete hHookCreateFileA;

  126. hHookCreateFileA = NULL;

  127.  
  128. delete hHookCreateFileW;

  129. hHookCreateFileW = NULL;

  130.  
  131. // even if the hook is removed, we need to wait for memory release

  132. LhWaitForPendingRemovals();

  133. }

  134.  
  135. BOOL APIENTRY DllMain( HMODULE hModule,

  136. DWORD ul_reason_for_call,

  137. LPVOID lpReserved

  138. )

  139. {

  140. switch (ul_reason_for_call)

  141. {

  142. case DLL_PROCESS_ATTACH:

  143. {

  144. OutputDebugString(L"DllMain::DLL_PROCESS_ATTACH\n");

  145.  
  146. // 准备好原始地址与目的地址

  147. int errCode = PrepareRealApiEntry();

  148. if (errCode != 0)

  149. {

  150. OutputDebugString(L"PrepareRealApiEntry() Error\n");

  151. return FALSE;

  152. }

  153.  
  154. // 开始挂钩

  155. DoHook();

  156.  
  157. break;

  158. }

  159. case DLL_THREAD_ATTACH:

  160. {

  161. OutputDebugString(L"DllMain::DLL_THREAD_ATTACH\n");

  162.  
  163. break;

  164. }

  165. case DLL_THREAD_DETACH:

  166. {

  167. OutputDebugString(L"DllMain::DLL_THREAD_DETACH\n");

  168.  
  169. break;

  170. }

  171.  
  172. case DLL_PROCESS_DETACH:

  173. {

  174. OutputDebugString(L"DllMain::DLL_PROCESS_DETACH\n");

  175.  
  176. // 卸载钩子

  177. DoneHook();

  178.  
  179. break;

  180. }

  181. }

  182. return TRUE;

  183. }

  184.  
  185.  
 

[cpp] view plain copy

  1. <code class="language-cpp">// HookSvr.cpp  
  2.   
  3. #include "stdafx.h"  
  4. #include "HookApi.h"  
  5. #include "easyhook.h"  
  6.   
  7. HANDLE WINAPI MyCreateFileW(  
  8.               __in     LPCWSTR lpFileName,  
  9.               __in     DWORD dwDesiredAccess,  
  10.               __in     DWORD dwShareMode,  
  11.               __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,  
  12.               __in     DWORD dwCreationDisposition,  
  13.               __in     DWORD dwFlagsAndAttributes,  
  14.               __in_opt HANDLE hTemplateFile  
  15.               )  
  16. {  
  17.     HANDLE hHandle = NULL;  
  18.   
  19.     // 执行钩子  
  20.     if (realCreateFileW == NULL)  
  21.     {  
  22.         OutputDebugString(L"realCreateFileW is NULL\n");  
  23.         return INVALID_HANDLE_VALUE;  
  24.     }  
  25.     else  
  26.     {  
  27.         OutputDebugString(L"realCreateFileW is not NULL\n");  
  28.         hHandle = (realCreateFileW)(lpFileName, dwDesiredAccess, dwShareMode,  
  29.             lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);  
  30.   
  31.         OutputDebugString(L"MyCreateFileW : ");  
  32.         OutputDebugString(lpFileName);  
  33.         OutputDebugString(L"\n");  
  34.     }  
  35.   
  36.     return hHandle;  
  37. }  
  38.   
  39. HANDLE WINAPI MyCreateFileA(  
  40.                   __in     LPCSTR lpFileName,  
  41.                   __in     DWORD dwDesiredAccess,  
  42.                   __in     DWORD dwShareMode,  
  43.                   __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,  
  44.                   __in     DWORD dwCreationDisposition,  
  45.                   __in     DWORD dwFlagsAndAttributes,  
  46.                   __in_opt HANDLE hTemplateFile  
  47.                   )  
  48. {  
  49.     HANDLE hHandle = NULL;  
  50.   
  51.     // 执行钩子  
  52.     if (realCreateFileA == NULL)  
  53.     {  
  54.         OutputDebugString(L"realCreateFileA is NULL\n");  
  55.         return INVALID_HANDLE_VALUE;  
  56.     }  
  57.     else  
  58.     {  
  59.         OutputDebugString(L"realCreateFileA is not NULL\n");  
  60.         hHandle = (realCreateFileA)(lpFileName, dwDesiredAccess, dwShareMode,  
  61.             lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);  
  62.   
  63.         OutputDebugString(L"MyCreateFileW : ");  
  64.         OutputDebugStringA(lpFileName);  
  65.         OutputDebugString(L"\n");  
  66.     }  
  67.   
  68.     return hHandle;  
  69. }</code>  


钩子这一部分我弄了比较久,主要是API不熟悉,不过好在弄好了。

 

 

 

 
  1. // HookSvr.h

  2.  
  3. #pragma once

  4. #include <Windows.h>

  5.  
  6. #ifndef _M_X64

  7. #pragma comment(lib, "EasyHook32.lib")

  8. #else

  9. #pragma comment(lib, "EasyHook64.lib")

  10. #endif

  11.  
  12. HANDLE WINAPI MyCreateFileW(

  13. __in LPCWSTR lpFileName,

  14. __in DWORD dwDesiredAccess,

  15. __in DWORD dwShareMode,

  16. __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,

  17. __in DWORD dwCreationDisposition,

  18. __in DWORD dwFlagsAndAttributes,

  19. __in_opt HANDLE hTemplateFile

  20. );

  21.  
  22. typedef HANDLE (WINAPI *ptrCreateFileW)(

  23. __in LPCWSTR lpFileName,

  24. __in DWORD dwDesiredAccess,

  25. __in DWORD dwShareMode,

  26. __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,

  27. __in DWORD dwCreationDisposition,

  28. __in DWORD dwFlagsAndAttributes,

  29. __in_opt HANDLE hTemplateFile

  30. );

  31.  
  32. extern ptrCreateFileW realCreateFileW;

  33.  
  34. HANDLE WINAPI MyCreateFileA(

  35. __in LPCSTR lpFileName,

  36. __in DWORD dwDesiredAccess,

  37. __in DWORD dwShareMode,

  38. __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,

  39. __in DWORD dwCreationDisposition,

  40. __in DWORD dwFlagsAndAttributes,

  41. __in_opt HANDLE hTemplateFile

  42. );

  43.  
  44. typedef HANDLE (WINAPI *ptrCreateFileA)(

  45. __in LPCSTR lpFileName,

  46. __in DWORD dwDesiredAccess,

  47. __in DWORD dwShareMode,

  48. __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,

  49. __in DWORD dwCreationDisposition,

  50. __in DWORD dwFlagsAndAttributes,

  51. __in_opt HANDLE hTemplateFile

  52. );

  53.  
  54. extern ptrCreateFileA realCreateFileA;


 

接下来是注入工具,这里指提供核心代码。本来EasyHook还提供了一个叫RhInjectLibrary()方法直接注入,这种方法相当稳定,推荐使用。我本来也用它,但是发现注入会失败,所以就采用了比较通用的远程注入代码,如下:

 
  1. BOOL RtlFileExists(WCHAR* InPath)

  2. {

  3. HANDLE hFile;

  4.  
  5. if((hFile = CreateFileW(InPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)

  6. return FALSE;

  7.  
  8. CloseHandle(hFile);

  9.  
  10. return TRUE;

  11. }

  12.  
  13. BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)

  14. {

  15. TOKEN_PRIVILEGES tp;

  16. HANDLE hToken;

  17. LUID luid;

  18.  
  19. if( !OpenProcessToken(GetCurrentProcess(),

  20. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,

  21. &hToken) )

  22. {

  23. return FALSE;

  24. }

  25.  
  26. if( !LookupPrivilegeValue(NULL, // lookup privilege on local system

  27. lpszPrivilege, // privilege to lookup

  28. &luid) ) // receives LUID of privilege

  29. {

  30. return FALSE;

  31. }

  32.  
  33. tp.PrivilegeCount = 1;

  34. tp.Privileges[0].Luid = luid;

  35. if( bEnablePrivilege )

  36. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

  37. else

  38. tp.Privileges[0].Attributes = 0;

  39.  
  40. // Enable the privilege or disable all privileges.

  41. if( !AdjustTokenPrivileges(hToken,

  42. FALSE,

  43. &tp,

  44. sizeof(TOKEN_PRIVILEGES),

  45. (PTOKEN_PRIVILEGES) NULL,

  46. (PDWORD) NULL) )

  47. {

  48. return FALSE;

  49. }

  50.  
  51. if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )

  52. {

  53. //The token does not have the specified privilege.

  54. return FALSE;

  55. }

  56.  
  57. return TRUE;

  58. }

  59.  
  60. typedef DWORD (WINAPI *PFNTCREATETHREADEX)

  61. (

  62. PHANDLE ThreadHandle,

  63. ACCESS_MASK DesiredAccess,

  64. LPVOID ObjectAttributes,

  65. HANDLE ProcessHandle,

  66. LPTHREAD_START_ROUTINE lpStartAddress,

  67. LPVOID lpParameter,

  68. BOOL CreateSuspended,

  69. DWORD dwStackSize,

  70. DWORD dw1,

  71. DWORD dw2,

  72. LPVOID Unknown

  73. );

  74.  
  75. BOOL MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)

  76. {

  77. HANDLE hThread = NULL;

  78. FARPROC pFunc = NULL;

  79. BOOL bHook;

  80.  
  81. // 判断系统版本

  82. OSVERSIONINFO osvi;

  83. //BOOL bIsWindowsXPorLater;

  84.  
  85. ZeroMemory(&osvi, sizeof(OSVERSIONINFO));

  86. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

  87.  
  88. GetVersionEx(&osvi);

  89.  
  90. if (osvi.dwMajorVersion == 6)

  91. {

  92. bHook = TRUE;

  93. }

  94. else

  95. {

  96. bHook = FALSE;

  97. }

  98.  
  99. if(bHook) // Vista, 7, Server2008

  100. {

  101. pFunc = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCreateThreadEx");

  102. if( pFunc == NULL )

  103. {

  104. //GetLastError());

  105. return FALSE;

  106. }

  107.  
  108. OutputDebugString(L"MyCreateRemoteThread");

  109. ((PFNTCREATETHREADEX)pFunc)(&hThread,

  110. 0x1FFFFF,

  111. NULL,

  112. hProcess,

  113. pThreadProc,

  114. pRemoteBuf,

  115. FALSE,

  116. NULL,

  117. NULL,

  118. NULL,

  119. NULL);

  120. if( hThread == NULL )

  121. {

  122. return FALSE;

  123. }

  124. }

  125. else // 2000, XP, Server2003

  126. {

  127. hThread = CreateRemoteThread(hProcess,

  128. NULL,

  129. 0,

  130. pThreadProc,

  131. pRemoteBuf,

  132. 0,

  133. NULL);

  134. if( hThread == NULL )

  135. {

  136. return FALSE;

  137. }

  138. }

  139.  
  140. if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )

  141. {

  142. return FALSE;

  143. }

  144.  
  145. return TRUE;

  146. }

  147.  
  148. BOOL InjectDll(DWORD dwPID, const wchar_t *szDllName)

  149. {

  150. HANDLE hProcess = NULL;

  151. LPVOID pRemoteBuf = NULL;

  152. FARPROC pThreadProc = NULL;

  153. DWORD dwBufSize = wcslen(szDllName)*sizeof(wchar_t)+2;

  154.  
  155. if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )

  156. {

  157. return FALSE;

  158. }

  159.  
  160. pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,

  161. MEM_COMMIT, PAGE_READWRITE);

  162.  
  163. WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName,

  164. dwBufSize, NULL);

  165.  
  166. pThreadProc = GetProcAddress(GetModuleHandle(L"kernel32.dll"),

  167. "LoadLibraryW");

  168.  
  169. if( !MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pThreadProc, pRemoteBuf) )

  170. {

  171. return FALSE;

  172. }

  173.  
  174. VirtualFreeEx(hProcess, pRemoteBuf, dwBufSize, MEM_RELEASE);

  175. CloseHandle(hProcess);

  176. return TRUE;

  177. }

  178.  
  179. int DoInject(DWORD aPid, const WCHAR *aFullpath)

  180. {

  181. if (wcslen(aFullpath) <= 0)

  182. {

  183. return -1;

  184. }

  185.  
  186. //判断dll是否存在

  187. HANDLE hFile = CreateFile(aFullpath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

  188. if(hFile != INVALID_HANDLE_VALUE)

  189. {

  190. DWORD dwsize = GetFileSize(hFile, NULL);

  191. CloseHandle(hFile);

  192. if (dwsize < 10)

  193. {

  194. return -2;

  195. }

  196. }

  197. else

  198. {

  199. return -3;

  200. }

  201.  
  202. BOOL bSuc=SetPrivilege(SE_DEBUG_NAME, TRUE);

  203. bSuc=InjectDll((DWORD)aPid, aFullpath);

  204. if (bSuc)

  205. {

  206. return -4;

  207. }

  208.  
  209. return 0;

  210. }

  211.  
  212.  
  213. // 真实注入的时候应该这样调用

  214. DoInject(m_processId, L"E:\\src\\easyhook\\trunk\\Debug\\x86\\HookSvr.dll");

  215.  
  216.  


这样就能保证注入的钩子能正常工作了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值