MFC:Win32-Dll及MFC-Dll编写调用
一、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;
}
MFC:Win32-Dll及MFC-Dll编写调用的更多相关文章
- Win32 DLL和MFC DLL 中封装对话框
现在最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是一个很普遍的关于如何在DLL中使用资源的问题.这里我们从Win32 DLL和MFC DLL两个方面来分析并解决这个问题. ...
- MFC:AfxLoadLibrary-将指定的 DLL 映射到调用进程的地址空间
Visual Studio 2012 - Visual C++ LoadLibrary 和 AfxLoadLibrary 进程调用 LoadLibrary (或 AfxLoadLibrary) 以显式 ...
- VS2010编写动态链接库DLL及单元测试用例,调用DLL测试正确性
转自:http://blog.csdn.net/testcs_dn/article/details/27237509 本文将创建一个简单的动态链接库,并编写一个控制台应用程序使用该动态链接库,该动态链 ...
- 四种DLL:NON-MFC DLL, Regular DLL Statically/Dynamically Linked to MFC, MFC Extension DLL
参考资料: https://msdn.microsoft.com/en-us/library/30c674tx.aspx http://www.cnblogs.com/qrlozte/p/484442 ...
- mfc extention dll 與 normal dll 的區別
extention dll 1.指從MFC中繼承過來的DLL,一般要求使用共享MFC DLL進行連接,也要求調用者也使用MFC且使用共享MFC,如此可保證DLL與調用者有相同的MFC庫. 2.在使用資 ...
- MFC的规则DLL与扩展DLL
一.MFC规则DLL MFC规则DLL可以在该dll内部使用MFC,但是与应用程序的接口不能是MFC的.能够被所有支持dll的编程语言所写的应用程序使用,当然也包括使用MFC创建的应用程序.在 ...
- [转]用多线程方法实现在MFC/WIN32中调用OpenGL函数并创建OpenGL窗口
原文链接: 1.用多线程方法实现在MFC/WIN32中调用OpenGL函数并创建OpenGL窗口 2.Windows MFC 两个OpenGL窗口显示与线程RC问题
- BCB如何编写,调用动态链接库DLL
一 编写动态链接库DLL DLL简称动态链接库,是Windows中程序的重要组成部分.想象一下,一个程序需要多人共同完成开发,怎么个共同法?这时我们就要考虑把程序分为好几个模块,团队每一个成员开发一个 ...
- 、Dll文件的编写 调用 说明
1>新建Dll文件TestLib.dll 新建Unit文件U_TestFunc U_TestFunc代码如下: unit U_TestFunc; interface uses //尽可能的少us ...
- Win32动态链接库和MFC 动态链接库
通过使用 DLL,程序可以实现模块化,由相对独立的组件组成.例如,一个计帐程序可以按模块来销售.可以在运行时将各个模块加载到主程序中(如果安装了相应模块).因为模块是彼此独立的,所以程序的加载速度 ...
随机推荐
- RabbitMQ调用
添加 gradle依赖complie("com.rabbitmq:amqp-client:5.0.0") Hello, World Working Queues Publish/S ...
- Lazarus 日志工具 MultiLog
MultiLog是一种同时以灵活性和低开销为目标的日志系统.顾名思义,它可用于将日志实例到多个目标,如文本文件.可视控件或其他应用程序.添加新的日志目标使用两个方法就可以实现了,其中一个方法是可选的. ...
- 【OpenCV】像素操作的数字图像处理
之前几天捣鼓matlab,用来处理数字图像,矩阵操作什么的,如果忘记线性代数就真的GG了. 在用了matlab被深深地吐槽之后,决定改用opencv,C++貌似也是处理数字图像的很好的工具 1. 在u ...
- CAD使用GetAllAppName读所有名称(网页版)
主要用到函数说明: MxDrawEntity::GetAllAppName 得到所有扩展数据名称,详细说明如下: 参数 说明 [out, retval] IMxDrawResbuf** ppRet 返 ...
- 02C++基本语法
基本语法 2.1.1单行注释 // 2.1.2多行注释 /* * */ 2.1.3标识符 C++ 标识符是用来标识变量.函数.类.模块,或任何其他用户自定义项目的名称.一个标识符以字母 A-Z 或 a ...
- 重启rsyncd
systemctl restart rsyncd.service
- Linux常用命令——目录处理命令
1.建立目录:mkdir mkdir -p [目录名] -p 递归创建 命令英文原意:make directories 实例: [root@localhost ~]# ls anaconda-ks.c ...
- 动态生成java、动态编译、动态加载
我曾经见过一个“规则引擎”,是在应用系统web界面直接编写java代码,然后保存后,规则即生效,我一直很是奇怪,这是如何实现的呢?实际这就好像jsp,被中间件动态的编译成java文件,有被动态的编译成 ...
- Python基础(十一) 异常处理
在程序运行过程中,总会遇到各种各样的错误,有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这样的错误我们通常称之为BUG,BUG是必须修复的.在Python中内置了一套异常处理机 ...
- 【Codeforces 923A】Primal Sport
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 考虑怎么得到数字x2=N,假设是质数p的倍数 那么x1肯定在x2-p+1~x2这个范围内才行 因为p的倍数要刚好大于等于x1, 所以x1肯定是 ...