本文通过VS建立了一个MFC 应用程序,建立完成,因如下图所示
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);
}
}
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!"));
}
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;
}
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;
}