DLL注入其他进程技术 阅读本篇文章,需要有《线程注入其他进程技术》基础。 DLL注入技术才具有强大的功能和使用性,同时简单易用,因为DLL中可以实现复杂的功能和很多的技术。 技术要点: 1、宿主进程调用LoadLibrary,可以完成DLL的远程注入。可以通过CreateRemoteThread将LoadLibrary作为宿主进程的一个线程来启动,可以完成“控制目标进程调用LoadLibrary”的工作。 2、标准DLL中DllMain,是DLL执行的入口;使用MFC的DLL中InitInstance,是DLL执行的入口,但是没有消息循环。 注意: a、如果是需要多线程,只能使用有DLLMain的标准DLL。因为使用MFC的DLL,在InitInstance中启动新的线程,会在启动线程的地方阻塞不继续执行。即说,使用带MFC的DLL只能单线程作业。 b、如果需要使用多线程和MFC。可以在标准DLL中先启动线程,再调用使用MFC的DLL。 实现步骤 1、将DLL的地址拷贝到宿主进程地址空间中 2、通过CreateRemoteThread将LoadLibrary作为宿主进程的一个线程来启动 可以正确运行的示例代码(拷贝后直接可以使用): 应用程序文件内容: // #pragma once #include <windows.h> #include <TlHelp32.h> #include <iostream> #include <time.h> // 提升进程访问权限 bool enableDebugPriv() { HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tkp; if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { return false; } if( !LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue) ) { CloseHandle(hToken); return false; } tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = sedebugnameValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if( !AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL) ) { CloseHandle(hToken); return false; } return true; }
// 根据进程名称得到进程ID,如果有多个运行实例的话,返回第一个枚举到的进程的ID DWORD processNameToId(LPCTSTR lpszProcessName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe; pe.dwSize = sizeof(PROCESSENTRY32); if( !Process32First(hSnapshot, &pe) ) { MessageBox( NULL, "The frist entry of the process list has not been copyied to the buffer", "Notice", MB_ICONINFORMATION | MB_OK ); return 0; } while( Process32Next(hSnapshot, &pe) ) { if( !strcmp(lpszProcessName, pe.szExeFile) ) { return pe.th32ProcessID; } } return 0; } int main(int argc, char* argv[]) { // 定义线程体的大小 const DWORD dwThreadSize = 5 * 1024; DWORD dwWriteBytes; // 提升进程访问权限 enableDebugPriv(); // 等待输入进程名称,注意大小写匹配 std::cout << "Please input the name of target process !" << std::endl; char szExeName[MAX_PATH] = { 0 }; std::cin >> szExeName; DWORD dwProcessId = processNameToId(szExeName); if( dwProcessId == 0 ) { MessageBox( NULL, "The target process have not been found !", "Notice", MB_ICONINFORMATION | MB_OK ); return -1; } // 根据进程ID得到进程句柄 HANDLE hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if( !hTargetProcess ) { MessageBox( NULL, "Open target process failed !", "Notice", MB_ICONINFORMATION | MB_OK ); return 0; } // 在宿主进程中为线程体开辟一块存储区域 // 在这里需要注意MEM_COMMIT内存非配类型以及PAGE_EXECUTE_READWRITE内存保护类型 // 其具体含义请参考MSDN中关于VirtualAllocEx函数的说明。 void* pRemoteThread = VirtualAllocEx( hTargetProcess, 0, dwThreadSize, MEM_COMMIT , PAGE_EXECUTE_READWRITE); if( !pRemoteThread ) { MessageBox( NULL, "Alloc memory in target process failed !", "notice", MB_ICONINFORMATION | MB_OK ); return 0; } // 设置需要注入的DLL名称 char szDll[256]; memset(szDll, 0, 256); strcpy(szDll, "E:\mydll.dll"); // 拷贝注入DLL内容到宿主空间 if( !WriteProcessMemory( hTargetProcess, pRemoteThread, (LPVOID)szDll, dwThreadSize, 0) ) { MessageBox( NULL, "Write data to target process failed !", "Notice", MB_ICONINFORMATION | MB_OK ); return 0; } LPVOID pFunc = LoadLibraryA; //在宿主进程中创建线程 HANDLE hRemoteThread = CreateRemoteThread( hTargetProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, pRemoteThread, 0, &dwWriteBytes); if( !hRemoteThread ) { MessageBox( NULL, "Create remote thread failed !", "Notice", MB_ICONINFORMATION | MB_OK ); return 0; } // 等待LoadLibraryA加载完毕 WaitForSingleObject(hRemoteThread, INFINITE ); VirtualFreeEx(hTargetProcess, pRemoteThread, dwThreadSize, MEM_COMMIT); CloseHandle( hRemoteThread ); CloseHandle( hTargetProcess ); return 0; }
实验的标准DLL文件: // mydll.cpp : Defines the entry point for the DLL application. // #include "stdafx.h" DWORD WINAPI MyThreadProc1( LPVOID pParam ); DWORD WINAPI MyThreadProc2( LPVOID pParam ); BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch ( ul_reason_for_call ) { case DLL_PROCESS_ATTACH: { MessageBox( NULL, "DLL已进入目标进程。", "信息", MB_ICONINFORMATION ); DWORD dwThreadId; HANDLE myThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MyThreadProc1, NULL, 0, &dwThreadId); HANDLE myThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MyThreadProc2, NULL, 0, &dwThreadId); break; } case DLL_PROCESS_DETACH: { MessageBox( NULL, "DLL已从目标进程卸载。", "信息", MB_ICONINFORMATION ); break; } } return TRUE; } DWORD WINAPI MyThreadProc1( LPVOID pParam ) { MessageBox( NULL, "DLL已进入线程1。", "信息", MB_ICONINFORMATION ); return 0; } DWORD WINAPI MyThreadProc2( LPVOID pParam ) { MessageBox( NULL, "DLL已进入线程2。", "信息", MB_ICONINFORMATION );