分享

实现DLL内存补丁,DLL劫持技术([Symanli原创])

 guoliyan1 2012-02-04
 在自己品读了kanxue大哥的加密解密之后,不禁想在论坛上写篇这样的文章.大伙都知道,在windows下当一个可执行文件运行时,Windows加载器将可执行模块映射到进程的地址空间中,加载器分析可执行模块的输入表,并设法找出任何需要的DLL,并将它们映射到进程的地址空间中。由于输入表是根据DLL名来进行查找,首先是查找当前目录下有没这文件,没有话在去查找系统目录C:\\Windows\\system32有没这文件,所以我们可以完全趁这个机会去劫持DLL,把他劫持下来后就可以在里面进行我们要做的事情。例如:
1.//补丁前,程序运行方式如下
1.jpg

1.//补丁后,程序运行方式如下
2.jpg

为了让我们自己开发的补丁DLL有导出函数,我们可以用 #parma comment(..),如:
  1. #pragma comment(linker, "/EXPORT:testadd=_TESTDLLLIB_testadd,@1")
复制代码
我写了个DLL,分别是补丁前和补丁后,我把代码贴出来,大家可以自己研究研究。

1.补丁前DLL。
  1. //tstDll.dll 补丁前
  2. //By symanli
  3. #include "stdafx.h"
  4. #include "dll.h"
  5. BOOL APIENTRY DllMain( HANDLE hModule,
  6.                        DWORD  ul_reason_for_call,
  7.                        LPVOID lpReserved
  8.                                          )
  9. {
  10.     return TRUE;
  11. }
  12. //原始函数
  13. int testadd(int a,int b)
  14. {
  15.         ::MessageBox(NULL,"这是补丁前的DLL","TODO",MB_OK);
  16.         return a+b;
  17. }
复制代码
2.补丁后
  1. //这是补丁代码。by symanli
  2. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3. // 头文件
  4. #include <Windows.h>
  5. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  6. // 宏定义
  7. #define EXTERNC extern "C"
  8. #define NAKED __declspec(naked)
  9. #define EXPORT __declspec(dllexport)

  10. #define ALCPP EXPORT NAKED
  11. #define ALSTD EXTERNC EXPORT NAKED void __stdcall
  12. #define ALCFAST EXTERNC EXPORT NAKED void __fastcall
  13. #define ALCDECL EXTERNC NAKED void __cdecl
  14. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  15. // TESTDLLLIB 命名空间
  16. namespace TESTDLLLIB
  17. {
  18.         HMODULE m_hModule = NULL;        // 原始模块句柄
  19.         DWORD m_dwReturn[1] = {0};        // 原始函数返回地址
  20.        
  21.        
  22.         // 加载原始模块
  23.         inline BOOL WINAPI Load()
  24.         {
  25.                 TCHAR tzPath[MAX_PATH];
  26.                 TCHAR tzTemp[MAX_PATH * 2];
  27.                
  28.                 //将原始DLL名改成其他的名字,我们用LoadLibrary去加载他。
  29.                 lstrcpy(tzPath, TEXT("tstDllold.dll"));
  30.                 m_hModule = LoadLibrary(tzPath);
  31.                 if (m_hModule == NULL)
  32.                 {
  33.                         wsprintf(tzTemp, TEXT("无法加载 %s,程序无法正常运行。"), tzPath);
  34.                         MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
  35.                 }
  36.                
  37.                 return (m_hModule != NULL);       
  38.         }
  39.        
  40.         // 释放原始模块
  41.         inline VOID WINAPI Free()
  42.         {
  43.                 if (m_hModule)
  44.                 {
  45.                         FreeLibrary(m_hModule);
  46.                 }
  47.         }
  48.        
  49.         // 获取原始函数地址
  50.         FARPROC WINAPI GetAddress(PCSTR pszProcName)
  51.         {
  52.                 FARPROC fpAddress;
  53.                 CHAR szProcName[16];
  54.                 TCHAR tzTemp[MAX_PATH];
  55.                
  56.                 fpAddress = GetProcAddress(m_hModule, pszProcName);
  57.                 if (fpAddress == NULL)
  58.                 {
  59.                         if (HIWORD(pszProcName) == 0)
  60.                         {
  61.                                 wsprintf(szProcName, "%d", pszProcName);
  62.                                 pszProcName = szProcName;
  63.                         }
  64.                        
  65.                         wsprintf(tzTemp, TEXT("无法找到函数 %hs,程序无法正常运行。"), pszProcName);
  66.                         MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
  67.                         ExitProcess(-2);
  68.                 }
  69.                
  70.                 return fpAddress;
  71.         }
  72. }
  73. using namespace TESTDLLLIB;

  74. // 入口函数
  75. BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
  76. {
  77.         if (dwReason == DLL_PROCESS_ATTACH)
  78.         {
  79.                 DisableThreadLibraryCalls(hModule);
  80.                
  81.                 for (INT i = 0; i < sizeof(m_dwReturn) / sizeof(DWORD); i++)
  82.                 {
  83.                         m_dwReturn[i] = TlsAlloc();
  84.                 }
  85.                
  86.                 return Load();
  87.         }
  88.         else if (dwReason == DLL_PROCESS_DETACH)
  89.         {
  90.                 for (INT i = 0; i < sizeof(m_dwReturn) / sizeof(DWORD); i++)
  91.                 {
  92.                         TlsFree(m_dwReturn[i]);
  93.                 }
  94.                
  95.                 Free();
  96.         }
  97.        
  98.         return TRUE;
  99. }
  100. // 导出函数
  101. ALCDECL TESTDLLLIB_testadd(void)
  102. {
  103.         ::MessageBox(NULL,"这是补丁后的DLL","TODO",MB_OK);
  104.         // 保存返回地址到 TLS
  105.         //__asm PUSH m_dwReturn[0 * TYPE long];
  106.         //__asm CALL DWORD PTR [TlsSetValue];
  107.        
  108.         // 调用原始函数
  109.         GetAddress("testadd");
  110.         __asm JMP EAX;
  111.         // 获取返回地址并返回

  112. //         __asm PUSH EAX;
  113. //         __asm PUSH m_dwReturn[0 * TYPE long];
  114. //         __asm CALL DWORD PTR [TlsGetValue];
  115. //         __asm XCHG EAX, [ESP];
  116. //         __asm RET;

  117. }
  118. #pragma comment(linker, "/EXPORT:testadd=_TESTDLLLIB_testadd,@1")
  119. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
复制代码
  1. //exe调用代码
  2. #pragma  comment(lib,"tstDll.lib")//导入先前DLL的lib,就是最原始的LIB
  3. void CTstExeDlg::OnButton1()
  4. {
  5.         // TODO: Add your control notification handler code here
  6.         int _sum =testadd(10,20);
  7.         CString szSum;
  8.         szSum.Format("结果是:[%d]",_sum);
  9.         AfxMessageBox(szSum);
  10. }
复制代码
3.结果
1.补丁前:
3.jpg

2.补丁后
4.jpg


别的我就不多了。我写了个例子程序,可以下载来研究下。大家通过这种原理可以做出类似劫持其他应用程序的程序。希望斑竹加精哦。哈哈

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多