MFC:Win32-Dll及MFC-Dll编写调用
阅读原文时间:2023年07月13日阅读:1

一、win32-dll

1、编写

代码例如以下:

Math.h

#ifdef MATH_EXPORTS
#define MATH_API __declspec(dllexport)
#else
#define MATH_API __declspec(dllimport)
#endif

extern MATH_API double PI;

MATH_API int Add(int a ,int b);

MATH_API int Sub(int a, int b);

MATH_API int Mod(int a, int b);

Math.cpp

#include "stdafx.h"
#include "Math.h"
MATH_API double PI = 3.1415926;
MATH_API int Add(int a,int b)
{
return a + b;
}
MATH_API int Sub(int a, int b)
{
return a - b;
}
MATH_API int Mod(int a, int b)
{
return a % b;
}

Math.def(这个须要自己手动新建项中加入)

LIBRARY "Math"
DESCRIPTION "ADD SUB MOD"
EXPORTS
Add @1
Sub @2
Mod @3
PI DATA

2、调用

初始化这些:

typedef int(\*M\_add)(int, int);  
typedef int(\*M\_sub)(int, int);  
typedef int(\*M\_mod)(int, int);  
M\_add myadd;  
M\_sub mysub;  
M\_mod mymod;

HINSTANCE hinst;

hinst = ::LoadLibrary(_T("Math.dll"));

void CMathTestDlg::OnBnClickedAdd()
{
ASSERT(hinst);
myadd = (M_add)::GetProcAddress(hinst,"Add");
int a = 15, b = 6;
int res = myadd(a,b);
CString str;
str.Format(_T("a+b=%d"), res);
AfxMessageBox(str);
}
void CMathTestDlg::OnBnClickedSub()
{
ASSERT(hinst);
mysub = (M_sub)::GetProcAddress(hinst, "Sub");
int a = 15, b = 6;
int res = mysub(a, b);
CString str;
str.Format(_T("a-b=%d"), res);
AfxMessageBox(str);
}
void CMathTestDlg::OnBnClickedMod()
{
ASSERT(hinst);
mymod = (M_mod)::GetProcAddress(hinst, "Mod");
int a = 15, b = 6;
int res = mymod(a, b);
CString str;
str.Format(_T("a求余b=%d"), res);
AfxMessageBox(str);
}

二、MFC-dll

1、MFC-Dll会在载入的时候,调用InitInstance中的代码,退出载入时,调用ExitInstance中的代码

2、声明部分

//不同Instance共享的该变量hinst
#pragma data_seg("SHARED")
static HINSTANCE hinst = NULL; //本dll的实例句柄 (MFCMath.dll)
#pragma data_seg()
#pragma comment(linker, "/section:SHARED,RWS")

HANDLE hProcess = NULL; //所处进程的句柄
BOOL bHook = FALSE; //是否Hook了函数
BOOL inject_status = FALSE; //是否对API进行了Hook
BYTE OldCode[5]; //老的系统API入口代码
BYTE NewCode[5]; //要跳转的API代码 (jmp xxxx)
typedef int (*M_add)(int a, int b); //Math.dll中的Add函数定义
M_add m_add; //Math.dll中的Add函数
FARPROC pf_add; //指向Add函数的远指针

void HookOn(); //开启钩子
void HookOff(); //关闭钩子
void Inject(); //详细进行注射,替换入口的函数
int Myadd(int a, int b); //我们定义的新的add()函数

3、InitInstance中的代码,载入时执行

BOOL CMFCMathApp::InitInstance()
{
hinst = AfxGetInstanceHandle(); //本dll句柄
hProcess = OpenProcess(PROCESS_ALL_ACCESS,NULL,::GetCurrentProcessId());
Inject();
return CWinApp::InitInstance();
}

4、ExitInstance中的代码,退出时执行

int CMFCMathApp::ExitInstance()
{
if (bHook)
HookOff();
return CWinApp::ExitInstance();
}

5、其它代码

void Inject()
{
if (inject_status == FALSE) {
inject_status = TRUE;
HMODULE hmod = ::LoadLibrary(_T("Math.dll"));//加载原Math.dll
m_add = (M_add)::GetProcAddress(hmod, "Add");
pf_add = (FARPROC)m_add;
if (pf_add == NULL) {
AfxMessageBox(L"注入失败");
}
_asm
{
lea edi, OldCode
mov esi, pf_add
cld
movsd
movsb
}

    NewCode\[0\] = 0xe9;//第一个字节0xe9相当于jmp指令  
                      //获取Myadd()的相对地址  
    \_asm  
    {  
        lea eax, Myadd  
        mov ebx, pf\_add  
            sub eax, ebx  
            sub eax, 5  
            mov dword ptr\[NewCode + 1\], eax  
    }  
    HookOn();  
    AfxMessageBox(L"注入成功");  
}  

}
void HookOn()
{
ASSERT(hProcess != NULL);
DWORD dwTemp = 0;
DWORD dwOldProtect;

//将内存保护模式改为可写,老模式保存入dwOldProtect  
VirtualProtectEx(hProcess, pf\_add, 5, PAGE\_READWRITE, &dwOldProtect);  
//将所属进程中add的前5个字节改为Jmp Myadd  
WriteProcessMemory(hProcess, pf\_add, NewCode, 5, 0);  
//将内存保护模式改回为dwOldProtect  
VirtualProtectEx(hProcess, pf\_add, 5, dwOldProtect, &dwTemp);

bHook = TRUE;  

}
//将所属进程中add()的入口代码恢复
void HookOff()
{
ASSERT(hProcess != NULL);
DWORD dwTemp = 0;
DWORD dwOldProtect;

VirtualProtectEx(hProcess, pf\_add, 5, PAGE\_READWRITE, &dwOldProtect);  
WriteProcessMemory(hProcess, pf\_add, OldCode, 5, 0);  
VirtualProtectEx(hProcess, pf\_add, 5, dwOldProtect, &dwTemp);  
bHook = FALSE;  

}
int Myadd(int a, int b)
{
//截获了对add()的调用,我们给a,b都加1
a = a + 1;
b = b + 1;
HookOff();//关掉Myadd()钩子防止死循环
int ret = m_add(a, b);
HookOn();//开启Myadd()钩子
return ret;
}

6、调用的方法

::LoadLibrary(_T("MFCMath.dll"));

此时会把Math.dll的入口替换Myadd的入口

假设在Myadd中使用了Math.dll中的Add函数,记住把入口再换回来,就是HookOff。调用完以后,再HookOn换回来。

::FreeLibrary()。能够释放掉在载入的dll

三、恶搞MessageBoxW函数

//不同Instance共享的该变量hinst
#pragma data_seg("SHARED")
static HINSTANCE hinst = NULL; //本dll的实例句柄 (MFCMath.dll)
#pragma data_seg()
#pragma comment(linker, "/section:SHARED,RWS")

HANDLE hProcess = NULL; //所处进程的句柄
BOOL bHook = FALSE; //是否Hook了函数
BOOL inject_status = FALSE; //是否对API进行了Hook
BYTE OldCode[5]; //老的系统API入口代码
BYTE NewCode[5]; //要跳转的API代码 (jmp xxxx)
typedef int (WINAPI *MyMsg)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType); //Math.dll中的Add函数定义

MyMsg m_msg; //Math.dll中的Add函数
FARPROC pf_add; //指向Add函数的远指针

void HookOn(); //开启钩子
void HookOff(); //关闭钩子
void Inject(); //详细进行注射,替换入口的函数
int WINAPI Myadd(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType); //我们定义的新的add()函数

BOOL CMFCMathApp::InitInstance()
{
hinst = AfxGetInstanceHandle(); //本dll句柄
hProcess = OpenProcess(PROCESS_ALL_ACCESS,NULL,::GetCurrentProcessId());
Inject();
return CWinApp::InitInstance();
}
int CMFCMathApp::ExitInstance()
{
if (bHook)
HookOff();
return CWinApp::ExitInstance();
}

void Inject()
{
if (inject_status == FALSE) {
inject_status = TRUE;
HMODULE hmod = ::LoadLibrary(_T("User32.dll"));//加载原Math.dll
m_msg = (MyMsg)::GetProcAddress(hmod, "MessageBoxW");
pf_add = (FARPROC)m_msg;
_asm
{
lea edi, OldCode
mov esi, pf_add
cld
movsd
movsb
}

    NewCode\[0\] = 0xe9;//第一个字节0xe9相当于jmp指令  
                      //获取Myadd()的相对地址  
    \_asm  
    {  
        lea eax, Myadd  
        mov ebx, pf\_add  
            sub eax, ebx  
            sub eax, 5  
            mov dword ptr\[NewCode + 1\], eax  
    }  
    HookOn();  
}  

}
void HookOn()
{
ASSERT(hProcess != NULL);
DWORD dwTemp = 0;
DWORD dwOldProtect;

//将内存保护模式改为可写,老模式保存入dwOldProtect  
VirtualProtectEx(hProcess, pf\_add, 5, PAGE\_READWRITE, &dwOldProtect);  
//将所属进程中add的前5个字节改为Jmp Myadd  
WriteProcessMemory(hProcess, pf\_add, NewCode, 5, 0);  
//将内存保护模式改回为dwOldProtect  
VirtualProtectEx(hProcess, pf\_add, 5, dwOldProtect, &dwTemp);

bHook = TRUE;  

}
//将所属进程中add()的入口代码恢复
void HookOff()
{
ASSERT(hProcess != NULL);
DWORD dwTemp = 0;
DWORD dwOldProtect;

VirtualProtectEx(hProcess, pf\_add, 5, PAGE\_READWRITE, &dwOldProtect);  
WriteProcessMemory(hProcess, pf\_add, OldCode, 5, 0);  
VirtualProtectEx(hProcess, pf\_add, 5, dwOldProtect, &dwTemp);  
bHook = FALSE;  

}
int WINAPI Myadd(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
lpText = _T("被掉包了,哈哈");
HookOff();//关掉Myadd()钩子防止死循环
int ret = m_msg(hWnd, lpText, lpCaption, uType);
HookOn();//开启Myadd()钩子
return ret;
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章