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
#include
#include
#include
// 提升進程訪問權限
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 );