一、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. 【sqli-labs】 less63 GET -Challenge -Blind -130 queries allowed -Variation2 (GET型 挑战 盲注 只允许130次查询 变化2)

    引号闭合 http://192.168.136.128/sqli-labs-master/Less-63/?id=1' or '1'='1 剩下的和Less62一样

  2. document.mozFullScreen

    非标准该特性是非标准的,请尽量不要在生产环境中使用它! 概述 返回一个布尔值,表明当前文档是否处于全屏模式. 语法 var isFullScreen = document.mozFullScreen ...

  3. vue-element-admin使用常见问题

    一.vue-element-admin添加快捷导航 这个组件是基于vue-i18n因此,首先在项目中安装i18n npm install --save vue-i18n 然后main.js中引入 im ...

  4. VC++代码转换为QT代码问题总结

    一边开发一边总结......  QQ937113547

  5. 梦想Android版CAD控件2019.01.23更新

    下载地址:http://www.mxdraw.com/ndetail_10121.html?tdsourcetag=s_pcqq_aiomsg1. 增加异步读取CAD,DWG文件函数,MxFuncti ...

  6. java_IO_3

    Reader和Writer针对字符文件  对图片类文件可能就显得无能为力了  会损坏文件 package ioStudy; import java.io.File; import java.io.Fi ...

  7. 13EL表达式语言

    EL表达式语言 EL表达式语言 JSP用于在页面上显示动态内容,通常需要在JSP页面中嵌入Java脚本以完成复杂功能.但大量的Java脚本使得JSP页面难以维护.一种类似JavaScript语言—EL ...

  8. Python 字符串常见的用法

    line = “ni hao wo jiao key” line.capotalize()#首字母大写 line.center(20)#居中显示固定的字符 line.count('n')#计数,计算该 ...

  9. 对于 前端请求Django 后端服务出现403 Forbidden (CSRF token missing or incorrect.) 问题的解析

    Django中使用ajax post向後臺傳送資料時403 Forbidden (CSRF token missing or incorrect.):的解決辦法 在Django中使用ajax post ...

  10. redis 指定端口 启动

    由于资源紧张 需要多创建一个redis实例 重新copy一份实例,然后修改redis.conf文件, 找到port 6379 处修改 端口号 6380 通过下面命令启动就好了 src/redis-se ...