首页
社区
课程
招聘
[旧帖] [分享]实现DLL内存补丁,DLL劫持技术(申请邀请码) 0.00雪花
发表于: 2011-8-27 13:42 4000

[旧帖] [分享]实现DLL内存补丁,DLL劫持技术(申请邀请码) 0.00雪花

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

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


为了让我们自己开发的补丁DLL有导出函数,我们可以用 #parma comment(..),如:
#pragma comment(linker, "/EXPORT:testadd=_TESTDLLLIB_testadd,@1")

我写了个DLL,分别是补丁前和补丁后,我把代码贴出来。
1.补丁前DLL。
//tstDll.dll 补丁前
//By symanli
#include "stdafx.h"
#include "dll.h"
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                                         )
{
    return TRUE;
}
//原始函数
int testadd(int a,int b)
{
        ::MessageBox(NULL,"这是补丁前的DLL","TODO",MB_OK);
        return a+b;
}

2.补丁后
//这是补丁代码。by symanli
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 头文件
#include <Windows.h>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 宏定义
#define EXTERNC extern "C"
#define NAKED __declspec(naked)
#define EXPORT __declspec(dllexport)

#define ALCPP EXPORT NAKED
#define ALSTD EXTERNC EXPORT NAKED void __stdcall
#define ALCFAST EXTERNC EXPORT NAKED void __fastcall
#define ALCDECL EXTERNC NAKED void __cdecl
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TESTDLLLIB 命名空间
namespace TESTDLLLIB
{
        HMODULE m_hModule = NULL;        // 原始模块句柄
        DWORD m_dwReturn[1] = {0};        // 原始函数返回地址
        
        
        // 加载原始模块
        inline BOOL WINAPI Load()
        {
                TCHAR tzPath[MAX_PATH];
                TCHAR tzTemp[MAX_PATH * 2];
                
                //将原始DLL名改成其他的名字,我们用LoadLibrary去加载他。
                lstrcpy(tzPath, TEXT("tstDllold.dll"));
                m_hModule = LoadLibrary(tzPath);
                if (m_hModule == NULL)
                {
                        wsprintf(tzTemp, TEXT("无法加载 %s,程序无法正常运行。"), tzPath);
                        MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
                }
                
                return (m_hModule != NULL);        
        }
        
        // 释放原始模块
        inline VOID WINAPI Free()
        {
                if (m_hModule)
                {
                        FreeLibrary(m_hModule);
                }
        }
        
        // 获取原始函数地址
        FARPROC WINAPI GetAddress(PCSTR pszProcName)
        {
                FARPROC fpAddress;
                CHAR szProcName[16];
                TCHAR tzTemp[MAX_PATH];
                
                fpAddress = GetProcAddress(m_hModule, pszProcName);
                if (fpAddress == NULL)
                {
                        if (HIWORD(pszProcName) == 0)
                        {
                                wsprintf(szProcName, "%d", pszProcName);
                                pszProcName = szProcName;
                        }
                        
                        wsprintf(tzTemp, TEXT("无法找到函数 %hs,程序无法正常运行。"), pszProcName);
                        MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
                        ExitProcess(-2);
                }
                
                return fpAddress;
        }
}
using namespace TESTDLLLIB;

// 入口函数
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
        if (dwReason == DLL_PROCESS_ATTACH)
        {
                DisableThreadLibraryCalls(hModule);
                
                for (INT i = 0; i < sizeof(m_dwReturn) / sizeof(DWORD); i++)
                {
                        m_dwReturn[i] = TlsAlloc();
                }
                
                return Load();
        }
        else if (dwReason == DLL_PROCESS_DETACH)
        {
                for (INT i = 0; i < sizeof(m_dwReturn) / sizeof(DWORD); i++)
                {
                        TlsFree(m_dwReturn[i]);
                }
                
                Free();
        }
        
        return TRUE;
}
// 导出函数
ALCDECL TESTDLLLIB_testadd(void)
{
        ::MessageBox(NULL,"这是补丁后的DLL","TODO",MB_OK);
        // 保存返回地址到 TLS
        //__asm PUSH m_dwReturn[0 * TYPE long];
        //__asm CALL DWORD PTR [TlsSetValue];
        
        // 调用原始函数
        GetAddress("testadd");
        __asm JMP EAX;
        // 获取返回地址并返回

//         __asm PUSH EAX;
//         __asm PUSH m_dwReturn[0 * TYPE long];
//         __asm CALL DWORD PTR [TlsGetValue];
//         __asm XCHG EAX, [ESP];
//         __asm RET;

}
#pragma comment(linker, "/EXPORT:testadd=_TESTDLLLIB_testadd,@1")
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

3.exe调用代码
//exe调用代码
#pragma  comment(lib,"tstDll.lib")//导入先前DLL的lib,就是最原始的LIB
void CTstExeDlg::OnButton1() 
{
        // TODO: Add your control notification handler code here
        int _sum =testadd(10,20);
        CString szSum;
        szSum.Format("结果是:[%d]",_sum);
        AfxMessageBox(szSum);
}

4.看看结果
1.补丁前:

2.补丁后:


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

点击下载例子: DLL.rar

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (13)
雪    币: 86
活跃值: (1188)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
跟海风的DLL劫持技术 一个样,没啥区别
2011-8-27 14:01
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
2011-8-30 10:11
0
雪    币: 90
活跃值: (82)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
不错。很古老很实用的东西。
不过邀请码估计得不到,版主审核好像很严格。

得搞点有深度的玩意儿。可好东东又不想放出,纠结。
2011-8-30 11:53
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
2011-8-30 12:46
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
留个地,转回来学习
2012-12-20 21:37
0
雪    币: 484
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
留名,支持
2012-12-20 21:46
0
雪    币: 38
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
楼主辛苦了,学习。
2012-12-21 07:49
0
雪    币: 74
活跃值: (748)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
学习,感谢分享
2012-12-21 10:16
0
雪    币: 15
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
学习啦,感谢分享!
2013-1-4 15:31
0
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
太高深了看不懂!
2013-1-4 18:05
0
雪    币: 150
活跃值: (1105)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
听好的东西
2015-4-13 16:40
0
雪    币: 20
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
学习了!!谢楼主分享!
2015-4-15 15:06
0
雪    币: 397
活跃值: (59)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
对新手来说,写的真不错。
2015-12-1 11:44
0
游客
登录 | 注册 方可回帖
返回
//