MFC動態調用dll到指定的進程中(win7系統vs2013環境下)

在這裏將寫一個簡單的MFC程序,此MFC將把一個dll插入到一個目標進程(也叫靶子)中

原理很簡單,就是通過目標(靶子)窗口的類名,找到這個目標的進程,再動態地將dll插入其中。

要實現此效果也並不複雜,就算是剛接觸vc的也可以完成此程序。(比較複雜的是插入代碼的原理

一、主程序

1、新建一個MFC項目,類型選擇基於對話框


2、寫一個簡單的窗體


點擊啓動事件

MessageBox(L"調用Dll到程序中成功。");


二、要調用的Dll

1、新建一個win32dll

這個wiin32就是要被插入(注入)的dll。



選擇dll、勾選導出符號


1、生成Dll項目


此時會在主程序Maindebug文件夾中生成了Dll.dllDll.lib文件


三、配置主程序Main的屬性

1、選擇鏈接器——輸入——附加依賴項:Dll.lib


1、選擇連接器——輸入——常規——附加庫目錄:..\Debug


1、包含頭文件。

選擇屬性——C/C++——附加包含目錄:..\..\Dll


然後在主程序的MainDlg.cpp類中加入包含Dll的頭文件#include "Dll.h"

再在啓動按鈕點擊時調用一下Dll中的一個函數fnDll

fnDll();

啓動程序點擊啓動



使用PCHunter64.exe查看進程


看到Dll.dll已經在此程序中被調用了。


PCHunterFree下載地址:http://download.csdn.net/detail/u014175572/9500637


以上所做的一切只是爲了示範如何用MFC調用dll(高手請無視上面的內容)。

接下來纔是重點。下面將“找到目標進程”、“插入dll到目標進程中”在MFC程序啓動按鈕的點擊事件中完成。


 

四、動態調用dll

1、先將屬性的鏈接器——輸入——附加依賴項刪除


把項目中剛調用的引用頭文件以及函數都屏蔽



1、引入注入的工具代碼Injection.h到主程序的頭文件文件夾中以及Injection.cpp到源文件夾中。

Injection.h內容如下:

#pragma once

HANDLE InjectProcess(DWORD dwProcessId, const WCHAR* szModuleName);

void UpdataToken();

Injection.cpp內容如下:

#include "stdafx.h"
#include "Injection.h"


HANDLE hAimProcess=NULL;
DWORD dAimProcessId=0;
HMODULE hKernel32=NULL;
HANDLE hInjectionThread=NULL;
PTHREAD_START_ROUTINE lpLoadLibraryAddress=NULL;
LPVOID lpParameter=NULL;
WCHAR wFilePath[MAX_PATH]={0};
size_t nPathLength=0;
HMODULE hInst=NULL;

HMODULE StartInjectionThread()
{
	hInjectionThread=::CreateRemoteThread(hAimProcess,NULL,0,lpLoadLibraryAddress,lpParameter,0,NULL);
	DWORD h = 0;
	if(hInjectionThread){
		::WaitForSingleObject(hInjectionThread,INFINITE);
		::GetExitCodeThread(hInjectionThread,&h);
	}
	return (HMODULE)h;
}

void FreeSpace()
{
	if(hInjectionThread!=NULL){
		DWORD h=0;
		::TerminateThread(hInjectionThread,h);
		::CloseHandle(hInjectionThread);
		::VirtualFreeEx(hAimProcess,lpParameter,nPathLength,MEM_DECOMMIT);
		::CloseHandle(hAimProcess);
		hInjectionThread=NULL;
	}	
}

void InitInjectionAddress()
{
	nPathLength = (1 + wcslen(wFilePath)) * sizeof(WCHAR);
	hKernel32 = GetModuleHandle(L"Kernel32.dll");
	lpLoadLibraryAddress=(PTHREAD_START_ROUTINE)GetProcAddress(hKernel32,"LoadLibraryW");
}

BOOL AllocateMemToAimProcess()
{
	lpParameter = VirtualAllocEx(hAimProcess,0,nPathLength,MEM_COMMIT,PAGE_READWRITE);
	return WriteProcessMemory(hAimProcess,lpParameter,wFilePath,nPathLength,NULL);
}

void InitInjectionModulePath(const WCHAR* szModuleName)
{
	GetModuleFileName(hInst,wFilePath,MAX_PATH);
	int nLen = wcslen(wFilePath);
	for(int i=nLen-1;i>-1;i--)
	{
		if(wFilePath[i]==L'\\')
		{
			for(int j=i+1;j<nLen;j++)
			{
				wFilePath[j]=0;
			}
			wcscat(wFilePath,szModuleName);
			break;
		}
	}
}

HANDLE InjectProcess(DWORD dwProcessId, const WCHAR* szModuleName)
{
	dAimProcessId = dwProcessId;
	hAimProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId);
	InitInjectionModulePath(szModuleName);
	InitInjectionAddress();
	if(!AllocateMemToAimProcess())
	{
		return FALSE;
	}
	StartInjectionThread();
	FreeSpace();
	return hAimProcess;
}


void UpdataToken()
{
	HANDLE hToken;
	LUID DebugNameValue;
	TOKEN_PRIVILEGES Privileges;
	DWORD dwRet;
	OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
	LookupPrivilegeValue(NULL, L"SeDebugPrivilege", &DebugNameValue);
	Privileges.PrivilegeCount=1;
	Privileges.Privileges[0].Luid=DebugNameValue;
	Privileges.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
	AdjustTokenPrivileges(hToken, FALSE,&Privileges, sizeof(Privileges), NULL, &dwRet);
	CloseHandle(hToken);
}



此時編譯會出現一個錯誤警告

error C4996: 'wcscat': This function or variable may be unsafe. Consider using wcscat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

只需要在在項目->屬性->C/C++->預處理器->預處理器定中添加_CRT_SECURE_NO_WARNINGS這個預定義。


1、加入調用Injection的函數

#include "Injection.h"

WCHAR czClassName[] = L"TXGuiFoundation";
WCHAR czWinName[] = L"陸周泉";
void CMainDlg::OnBnClickedOk()
{
	// TODO:  在此添加控件通知處理程序代碼
	//CDialogEx::OnOK();
	//fnDll();
	MessageBox(L"程序啓動成功。");
	DWORD procid = 0;
	CWnd *pWnd = FindWindow(czClassName, NULL);
	if (pWnd){
		MessageBox(L"找到窗口");
		GetWindowThreadProcessId(pWnd->m_hWnd, &procid);
		if (procid){
			//MessageBox(L"找到進程id");
			UpdataToken();
			if (InjectProcess(procid, L"Dll.dll"))
			{
				MessageBox(L"注入成功");
			}
		}
	}
	//MessageBox(L"調用Dll成功。");
}

void CMainDlg::OnBnClickedOk()就是MFC窗體中啓動按鈕的點擊事件。


其中WCHAR czClassName[] = L"TXGuiFoundation";爲類名,可以使用Spy4Win.exe軟件獲取


WCHAR czClassName[] 的值就是要插入的那個進程的類名,這個類名必須要知道。爲何不用內存地址指針呢?內存地址是會改變,但窗口的類名很少變動。

這個類名你們可以根據需求自己獲取(獲取類名的工具有很多,這裏用的是spy),這裏我用QQ作爲靶子程序,即把Dll插入到QQ的進程中。


spy下載地址:http://download.csdn.net/detail/qq_34771394/9500751

1、根據路徑再調節一下C/C++包含目錄,路徑是一個很麻煩的問題,我這裏的開發環境需要改一下路徑,不同的環境配置的路徑都可能會有所不同,這裏需要酌情調整。


再啓動程序查看靶子進程,Dll.dll已經加入到了目標的進程中


這樣,自定義的dll就成功地插入到了靶子(QQ)中。


此Demo代碼下載地址:http://download.csdn.net/detail/u014175572/9507309

發佈了40 篇原創文章 · 獲贊 554 · 訪問量 133萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章