一、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编写调用的更多相关文章

  1. Win32 DLL和MFC DLL 中封装对话框

    现在最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是一个很普遍的关于如何在DLL中使用资源的问题.这里我们从Win32   DLL和MFC   DLL两个方面来分析并解决这个问题.     ...

  2. MFC:AfxLoadLibrary-将指定的 DLL 映射到调用进程的地址空间

    Visual Studio 2012 - Visual C++ LoadLibrary 和 AfxLoadLibrary 进程调用 LoadLibrary (或 AfxLoadLibrary) 以显式 ...

  3. VS2010编写动态链接库DLL及单元测试用例,调用DLL测试正确性

    转自:http://blog.csdn.net/testcs_dn/article/details/27237509 本文将创建一个简单的动态链接库,并编写一个控制台应用程序使用该动态链接库,该动态链 ...

  4. 四种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 ...

  5. mfc extention dll 與 normal dll 的區別

    extention dll 1.指從MFC中繼承過來的DLL,一般要求使用共享MFC DLL進行連接,也要求調用者也使用MFC且使用共享MFC,如此可保證DLL與調用者有相同的MFC庫. 2.在使用資 ...

  6. MFC的规则DLL与扩展DLL

    一.MFC规则DLL     MFC规则DLL可以在该dll内部使用MFC,但是与应用程序的接口不能是MFC的.能够被所有支持dll的编程语言所写的应用程序使用,当然也包括使用MFC创建的应用程序.在 ...

  7. [转]用多线程方法实现在MFC/WIN32中调用OpenGL函数并创建OpenGL窗口

    原文链接: 1.用多线程方法实现在MFC/WIN32中调用OpenGL函数并创建OpenGL窗口 2.Windows MFC 两个OpenGL窗口显示与线程RC问题

  8. BCB如何编写,调用动态链接库DLL

    一 编写动态链接库DLL DLL简称动态链接库,是Windows中程序的重要组成部分.想象一下,一个程序需要多人共同完成开发,怎么个共同法?这时我们就要考虑把程序分为好几个模块,团队每一个成员开发一个 ...

  9. 、Dll文件的编写 调用 说明

    1>新建Dll文件TestLib.dll 新建Unit文件U_TestFunc U_TestFunc代码如下: unit U_TestFunc; interface uses //尽可能的少us ...

  10. Win32动态链接库和MFC 动态链接库

      通过使用 DLL,程序可以实现模块化,由相对独立的组件组成.例如,一个计帐程序可以按模块来销售.可以在运行时将各个模块加载到主程序中(如果安装了相应模块).因为模块是彼此独立的,所以程序的加载速度 ...

随机推荐

  1. binlog_format不同模式下,对mysqlbinlog恢复的影响

      binlog_format='mixed' (root)[(none)]>use test; Reading table information for completion of tabl ...

  2. 【windows】自动化测试持续集成(CI)环境部署

    1. 环境准备 1.1 我的环境 1.Win10 64位 2.JDK 1.8.0_121 3.Tomcat 7.0.92 4. Jenkins 2.24 5.SVN-Server 3.8.1 1.2 ...

  3. Jmeter之重定向请求

    一.自动重定向和跟随重定向的区别 自动重定向:状态码一般是200.20X.当重定向自动跳转时,只针对GET和Head请求,自动重定向自动跳转到最终目标页面,当HTTP请求为自动重定向时,JMeter不 ...

  4. CAD得到当前选择的实体(网页版)

    主要用到函数说明: IMxDrawSelectionSet::CurrentSelect 得到当前已经选择的实体.详细说明如下: 参数 说明 filterData 过滤条件 js中使用如下: 1 2 ...

  5. JS中的let和var的区别

    最近很多前端的朋友去面试被问到let和var的区别,其实阮一峰老师的ES6中已经很详细介绍了let的用法和var的区别.我简单总结一下,以便各位以后面试中使用. ES6 新增了let命令,用来声明局部 ...

  6. spring用来干什么,解决的问题

    // 1. 实体类 class User{ } //2. dao class  UserDao{ .. 访问db } //3. service class  UserService{ UserDao ...

  7. 参考整理papers(一)

    https://blog.csdn.net/qq_14845119/article/details/82219246 整理了OCR的论文,可以参考一下.还有一些相关论文 论文(poster):Scen ...

  8. react 导航切换

    <ul class="nav"> <li onClick={() => this.changeFontColor(0)} className={`${0 = ...

  9. UVA 674 Coin Change (完全背包)

    解法 dp表示目前的种数,要全部装满所以f[0]=1其余为0的初始化是必不可少的 代码 #include <bits/stdc++.h> using namespace std; int ...

  10. [ural1057][Amount of Degrees] (数位dp+进制模型)

    Discription Create a code to determine the amount of integers, lying in the set [X; Y] and being a s ...