实现DLL内存补丁,DLL劫持技术



在windows下当一个可执行文件运行时,Windows加载器将可执行模块映射到进程的地址空间中,加载器分析可执行模块的输入表,并设法找出任何需要的DLL,并将它们映射到进程的地址空间中。由于输入表是根据DLL名来进行查找,首先是查找当前目录下有没这文件,没有话在去查找系统目录C:\\Windows\\system32有没这文件,所以我们可以完全趁这个机会去劫持DLL,把他劫持下来后就可以在里面进行我们要做的事情。


为了让我们自己开发的补丁DLL有导出函数,我们可以用 #parma comment(..),如:


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



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.补丁后DLL

//这是补丁代码。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")


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);
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值