閱讀本文之前,你需要瞭解以下幾個API函數:
·OpenProcess - 用於打開要寄生的目標進程。
·VirtualAllocEx/VirtualFreeEx - 用於在目標進程中分配/釋放內存空間
·WriteProcessMemory - 用於在目標進程中寫入要加載的DLL名稱。
·CreateRemoteThread - 遠程加載DLL的核心內容,用於控制目標進程調用API函數。
·LoadLibrary - 目標進程通過調用此函數來加載病毒DLL。
在此我只給出了簡要的函數說明,關於函數的詳細功能和介紹請參閱MSDN
示例程序
我將在以下的篇幅中用一個簡單的示例Virus.exe來實現這一技術。這個示例的界面如下圖
首先運行Target.exe,這個文件是一個用Win32 Application嚮導生成的「Hello, World」程序,用來作為寄生的目標進程
然後在界面的編輯控件中輸入進程的名稱「Target.exe」,單擊「注入DLL」按鈕,這時候Virus.exe就會將當前目錄下的DLL.dll注入至Target.exe進程中
在注入DLL.dll之後,你也可以單擊「卸載DLL」來將已經注入的DLL卸載。
模擬的病毒體DLL.dll
這是一個簡單的Win32 DLL程序,它僅由一個入口函數DllMain組成:
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch ( fdwReason )
{
case DLL_PROCESS_ATTACH
{
MessageBox( NULL, _T("DLL已進入目標進程。"), _T("信息"), MB_ICONINformATION );
}
break;
case DLL_PROCESS_DETACH
{
MessageBox( NULL, _T("DLL已從目標進程卸載。"), _T("信息"), MB_ICONINformATION );
}
break;
}
return TRUE
}
如你所見,這裡我在DLL被加載和卸載的時候調用了MessageBox,這是用來顯示我的遠程注入/卸載工作是否成功完成。而對於一個真正的病毒體來說,它往往就是處理DLL_PROCESS_ATTACH事件,在其中加入了啟動病毒代碼的部分:
case DLL_PROCESS_ATTACH:
{
StartVirus();
}
break;
注入!
現在要開始我們的注入工作了。首先,我們需要找到目標進程:
DWORD FindTarget( LPCTSTR lpszProcess )
{
DWORD dwRet = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );G
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof( PROCESSENTRY32 );
Process32First( hSnapshot, &pe32 )
do
{
if ( lstrcmpi( pe32.szExeFile, lpszProcess ) == 0 )
{
dwRet = pe32.th32ProcessID;VM=S!
break;ulF
}
} while ( Process32Next( hSnapshot, &pe32 ) );
CloseHandle( hSnapshot );
return dwRet;
}
這裡我使用了Tool Help函數庫,當然如果你是NT系統的話,也可以選擇PSAPI函數庫。這段代碼的目的就是通過給定的進程名稱來在當前系統中查找相應的進程,並返回該進程的ID。得到進程ID後,就可以調用OpenProcess來打開目標進程了:
// 打開目標進程__#
HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwProcessID );
現在有必要說一下OpenProcess第一個參數所指定的三種權限。在Win32系統下,每個進程都擁有自己的4G虛擬地址空間,各個進程之間都相互獨立。如果一個進程需要完成跨進程的工作的話,那麼它必須擁有目標進程的相應操作權限。在這裡,PROCESS_CREATE_THREAD表示我可以通過返回的進程句柄在該進程中創建新的線程,也就是調用CreateRemoteThread的權限;同理,PROCESS_VM_OPERATION則表示在該進程中分配/釋放內存的權限,也就是調用VirtualAllocEx/VirtualFreeEx的權限;PROCESS_VM_WRITE表示可以向該進程的地址空間寫入數據,也就是調用WriteProcessMemory的權限。
至此目標進程已經打開,那麼我們該如何來將DLL注入其中呢?在這之前,我請你看一行代碼,是如何在本進程內顯式加載DLL的:pI
HMODULE hDll = LoadLibrary( "DLL.dll" ); @
那麼,如果能控制目標進程調用LoadLibrary,不就可以完成DLL的遠程注入了麼?
的確是這樣,我們可以通過CreateRemoteThread將LoadLibrary作為目標進程的一個線程來啟動,這樣就可以完成「控制目標進程調用LoadLibrary」的工作了。
到這裡,也許你會想當然地寫下類似這樣的代碼:
|