(紀(jì)念國殤).Net Hosting:托管遠(yuǎn)程線程插入及非托管dll線程插入實(shí)現(xiàn)
線程插入,在托管平臺上面,是不能直接實(shí)現(xiàn)的。如果想通過托管平臺在一個(gè)非托管的Process里面插入執(zhí)行一段托管代碼,就需要在非托管Process里面啟動(dòng)CLR。我們可以以此為突破口,通過直接調(diào)用CLR提供的功能接口來執(zhí)行托管代碼。
最終效果,是實(shí)現(xiàn)了非托管平臺下托管代碼執(zhí)行的混合型線程插入。
在開發(fā)CLR的時(shí)候,MS將CLR作為一個(gè)COM服務(wù)器放到了一個(gè)DLL里面。MS為CLR定義了一個(gè)標(biāo)準(zhǔn)的COM接口,同時(shí)分配了全局的GUID。在安裝Framework的時(shí)候,就被安裝到了注冊表里面去。
基于上一篇文章里面講的DotNet CLR Hosting的原理,就可以很容易實(shí)現(xiàn)在非托管進(jìn)程里面啟動(dòng)CLR并且執(zhí)行托管代碼:
首先,在非托管宿主里面加載CLR并且啟動(dòng):
ICLRRuntimeHost *pCLRHost = NULL;
HRESULT hr = CorBindToRuntimeEx(
L"v2.0.40103", //需要加載的CLR版本,Null表示最新的
L"wks", //GC的風(fēng)格,Null表示默認(rèn)的工作站模式
STARTUP_CONCURRENT_GC,
CLSID_CLRRuntimeHost, //CLR的CLSID
IID_ICLRRuntimeHost, //ICLRRuntimeHost的IID
(PVOID*) &pCLRHost); //返回的COM接口
初始化并且啟動(dòng)CLR:
pCLRHost->Start();
然后執(zhí)行一段托管代碼:
hr = pCLRHost ->ExecuteInDefaultAppDomain(L"test.exe",
L" test.Program",
L"Start",
NULL,
&retVal);
可以把需要執(zhí)行的托管函數(shù)放到一個(gè)編譯好的本地代碼集或者是dll里面。然后把上面的代碼做成一個(gè)shellcode,這樣就可以實(shí)現(xiàn)托管代碼的線程插入了。
這種技術(shù),對于可以被插入的進(jìn)程也是有限制的,僅限所有有權(quán)限進(jìn)程WriteProcessMemory操作的本機(jī)進(jìn)程。
這里僅討論其實(shí)現(xiàn)的可能性和方法,個(gè)人感覺這種技術(shù)是雞肋..
下面介紹下非托管下的dll線程插入技術(shù)的實(shí)現(xiàn),首先介紹幾個(gè)dll線程插入的時(shí)候的主要的函數(shù):
OpenProcess - 用于打開要寄生的目標(biāo)進(jìn)程。
VirtualAllocEx/VirtualFreeEx - 用于在目標(biāo)進(jìn)程中分配/釋放內(nèi)存空間。
WriteProcessMemory - 用于在目標(biāo)進(jìn)程中寫入要加載的DLL名稱。
CreateRemoteThread - 遠(yuǎn)程加載DLL的核心內(nèi)容,用于控制目標(biāo)進(jìn)程調(diào)用API函數(shù)。
LoadLibrary - 目標(biāo)進(jìn)程通過調(diào)用此函數(shù)來加載病毒DLL。
單純的加載一個(gè)dll到一個(gè)具有WriteProcessMemory操作權(quán)限的Process并不是很困難,只要利用上面的幾個(gè)函數(shù),就可以讓目標(biāo)進(jìn)程執(zhí)行相應(yīng)的注入代碼:
//加載一個(gè)目標(biāo)Library到指定的Process ID里面,并且創(chuàng)建一個(gè)線程同時(shí)執(zhí)行注入的dll里面的代碼。
BOOL RemoteLoadLibrary( DWORD dwProcessID, LPCSTR lpszDll )
{
// 打開目標(biāo)進(jìn)程
HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD |
PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwProcessID );
// 向目標(biāo)進(jìn)程地址空間寫入DLL名稱
DWORD dwSize, dwWritten;
dwSize = lstrlenA( lpszDll ) + 1;
//在目標(biāo)進(jìn)程里面分配空間
LPVOID lpBuf = VirtualAllocEx( hProcess, NULL, dwSize, MEM_COMMIT,
PAGE_READWRITE );
if ( NULL == lpBuf )
{
CloseHandle( hProcess );
return FALSE;
}
//把需要插入的dll的內(nèi)容寫到分配好了的Process的內(nèi)存空間里面去。
if ( WriteProcessMemory( hProcess, lpBuf, (LPVOID)lpszDll, dwSize, &dwWritten ) )
{
// 要寫入字節(jié)數(shù)與實(shí)際寫入字節(jié)數(shù)不相等,仍屬失敗
if ( dwWritten != dwSize )
{
//釋放分配的空間。
VirtualFreeEx( hProcess, lpBuf, dwSize, MEM_DECOMMIT );
CloseHandle( hProcess );
return FALSE;
}
}
else
{
CloseHandle( hProcess );
return FALSE;
}
// 使目標(biāo)進(jìn)程調(diào)用LoadLibrary,加載DLL
DWORD dwID;
LPVOID pFunc = LoadLibraryA;
//創(chuàng)建一個(gè)遠(yuǎn)程需要執(zhí)行插入dll的thread,并且執(zhí)行代碼
HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)pFunc, lpBuf, 0, &dwID );
// 等待LoadLibrary加載完畢
WaitForSingleObject( hThread, INFINITE );
// 釋放目標(biāo)進(jìn)程中申請的空間
VirtualFreeEx( hProcess, lpBuf, dwSize, MEM_DECOMMIT );
CloseHandle( hThread );
CloseHandle( hProcess );
return TRUE;
}
上面把兩種技術(shù)都列舉出來了,基于托管平臺和非托管平臺實(shí)現(xiàn)dll插入的實(shí)現(xiàn)和對比。
紀(jì)念國殤。2008-5-19 2:02:58 PM 首發(fā)sscli.cnblogs.com.
posted on 2008-05-19 14:10 lbq1221119 閱讀(2788) 評論(8) 收藏 舉報(bào)
浙公網(wǎng)安備 33010602011771號