远程线程注入dll文件

利用远程线程注入dll文件,修改另一个进程内存值

  • 准备
  • 一. 编写一个能远程注入dll的进程
    • 1.界面设计
    • 2.事件代码
  • 二、编写一个修改进程内存的dll文件

准备

  1. Visual Studio编译器(以下代码是基于VS2008)
  2. 如果对于dll文件什么都不是很清楚的童鞋,可以观看 C++远程线程注入 视频

一. 编写一个能远程注入dll的进程

1.界面设计

本文通过VS建立了一个MFC 应用程序,建立完成,因如下图所示
远程线程注入dll文件_第1张图片

  1. 点击 视图-》资源视图,左侧弹出资源视图界面,点击红色划线的文件
    远程线程注入dll文件_第2张图片
  2. 类似VB编程,设计出下图所示界面。具体步骤可以参考上述提到的视频
    远程线程注入dll文件_第3张图片
    第一行填写DLL文件所在的路径。通过点击open按键,会弹出文件对话框,选择文件
    第二行填写需要注入的进程名字(可通过任务管理器查询)。输入完成后,点击inject就可完成注入。

2.事件代码

  1. 双击open按键,编译open点击事件,如下图
void CinjectDLLDlg::OnBnClickedOpen()
{
	//选择需要的DLL文件
	CFileDialog filedialog(TRUE, 0, 0, 6UL, _T("DLL Files | *.dll|"));
	if (filedialog.DoModal() == IDOK)
	{
		CString DLLpath;
		DLLpath = filedialog.GetPathName();
		SetDlgItemText(IDC_DLLPATH, DLLpath);
	}
}
  1. 同理,双击inject,编辑inject点击事件,如下图所示

void CinjectDLLDlg::OnBnClickedInject()
{
	CString DLLpath;
	CString Exename;
	GetDlgItemText(IDC_EXENAME, Exename);
	GetDlgItemText(IDC_DLLPATH, DLLpath);
	//如果进程名为空,报错
	if (Exename.GetLength() == 0)
	{
		MessageBox(_T("Please input exe name"));
		return ;
	}
    //调用ProcessFind函数寻找进程名
	DWORD ProcessID = ProcessFind(Exename);
	//如果遍历所有进程,没找到对应的PID,报错
	if (!ProcessID)
	{
         MessageBox(_T("Can't find the process"));
		 return ;
	}
	//调用Inject函数远程注入线程
	BOOL IsInjected = Inject(DLLpath, ProcessID);
	if (IsInjected)
		MessageBox(_T("Inject Success!"));
	else
		MessageBox(_T("Inject Fail!"));

}
  1. 补充自定义函数 ProcessFind 和 Inject
DWORD ProcessFind(LPCTSTR Exename)
{   

	//获取进程快照
	HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
	if (!hProcess)
	{
		return FALSE;
	}
	PROCESSENTRY32 info;
	info.dwSize = sizeof(PROCESSENTRY32);
	if (!Process32First(hProcess, &info))
	{
		return FALSE;
	}
	// 遍历所有进程,遇到相同名字的进程,返回对应的PID号
	// 否则,报错
	while (TRUE)
	{
		if (_tcscmp(info.szExeFile, Exename) == 0)
			return info.th32ProcessID;
		if (!Process32Next(hProcess, &info))
			return FALSE;
	}

}

BOOL Inject(LPCTSTR DLLPath, DWORD ProcessID)
{
	//获取要注入进程的读写权限
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessID);
	if (!hProcess)
		return FALSE;
    
	SIZE_T PathSize = (_tcslen(DLLPath) + 1) * sizeof(TCHAR);
    //在指定进程的虚拟空间提交内存区域
    LPVOID StartAddress = VirtualAllocEx(hProcess, NULL, PathSize, MEM_COMMIT, PAGE_READWRITE);
	
	if (!StartAddress)
		return FALSE;
	//写入对应dll文件的路径
	if (!WriteProcessMemory(hProcess, StartAddress, DLLPath, PathSize, NULL))
        return FALSE;
    //指定的动态链接库(DLL)中的输出库函数地址
	PTHREAD_START_ROUTINE pfnStartAddress = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "LoadLibraryW");
    if (!pfnStartAddress)
		return FALSE;
    //利用kernel32内核,打开dll文件,实现注入
	HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, pfnStartAddress, StartAddress, NULL, NULL);
    if (!hThread)
		return FALSE;
    
    //线程等待进程结束
	WaitForSingleObject(hThread, INFINITE);

	CloseHandle(hThread);
	CloseHandle(hProcess);

	return TRUE;
}

二、编写一个修改进程内存的dll文件

  1. 通过VS建立了一个dLL应用程序,建立完成,因如下图所示
    远程线程注入dll文件_第4张图片
  2. 点击dllmian.cpp
    远程线程注入dll文件_第5张图片
  3. 在DLLMain函数中添加自定义函数,如下图所示
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	int res = 0;
	case DLL_PROCESS_ATTACH:
		MessageBox(NULL, L"mydll inject", L"Welcome", NULL);
	    ChangeAddressValue((void *)0x75BC105C, 4, 12, res);
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}
/*
 * 修改指定内存区域的值
 * 
 * @param lpAddress:起始地址
 * @param dwSize: 修改的长度
 * @param data:修改的值
 * @param old_data:修改的值
 *
 * @return 无
 */
bool ChangeAddressValue(LPVOID lpAddress, DWORD dwSize, void* data, void* old_data)
{

	DWORD lpflOldProtect; // 保存老的保护方式

	if(VirtualProtect(lpAddress, dwSize, PAGE_READWRITE, &lpflOldProtect))
	{
		switch(dwSize)
		{
		case 1: 
			*((unsigned char*)old_data) = *((unsigned char*)lpAddress);
			*(unsigned char*)lpAddress = *((unsigned char *)data);
			break;
		case 2:
			*((unsigned short int*)old_data) =*((unsigned short int*)lpAddress);
			*((unsigned short int*)lpAddress) = *((unsigned short int*)data);
			break;
		case 4:
			*((unsigned int*) old_data) = *((unsigned int*)lpAddress);
			*((unsigned int*)lpAddress) = *((unsigned int*)data);
			break;
		default:
			break;
		}

		VirtualProtect(lpAddress, dwSize, lpflOldProtect, &lpflOldProtect);
		return TRUE;

	}
	else 
		return FALSE;
}

你可能感兴趣的:(WINDOWS编程,c++)