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


  • 相关阅读:
    Linux初学
    Linux初学
    EntityFramework IEnumerable,IQueryable ,Include
    EntityFramework 4/5/6 中执行自定义SQL语句
    ServiceStack Web Service 创建与调用简单示列
    ServiceStack 概念
    Couchbase 环境搭建与使用(C#)
    Redis 环境搭建与使用(C#)
    分享几段JavaScript
    Activemq 平台搭建与C#示列
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7105903.html
Copyright © 2020-2023  润新知