進(jìn)行DLL注入的一種方法
- 發(fā)布于:2020-12-29
- 共 258 人圍觀
這種方法只能在WIN2000中使用(XP,和最新的2003不知道)。具體步驟如下:
?。保?、取得遠(yuǎn)程進(jìn)程的進(jìn)程ID;
?。玻?、在遠(yuǎn)程進(jìn)程空間中分配一段內(nèi)存用來(lái)存放要注入的DLL完整路徑;
?。常?、將要注入的DLL的路徑寫(xiě)到剛才分配的遠(yuǎn)程進(jìn)程空間;
?。矗?、從Kernel32.dll中取得LoadLibray的地址;
?。担?、調(diào)用CreateRemoteThread函數(shù)以從Kernel32.dll中取得的LoadLibrary函數(shù)的地址為線(xiàn)程函數(shù)的地址,以我們要注入的DLL文件名為參數(shù),創(chuàng)建遠(yuǎn)程線(xiàn)程;
在第二三步中,為什么要把我們要注入的DLL的文件名寫(xiě)到遠(yuǎn)程進(jìn)程的地址空間進(jìn)行*作,《WINDOWS核心編程》中是這樣描述的:
“(要注入的DLL文件名)字符串是在調(diào)用進(jìn)程的地址空間中。該字符串的地址已經(jīng)被賦予新創(chuàng)建的遠(yuǎn)程線(xiàn)程,該線(xiàn)程將它傳遞給L o a d L i b r a r y A。但是,當(dāng)L o a d L i b r a r y A取消對(duì)內(nèi)存地址的引用時(shí), D L L路徑名字符串將不再存在,遠(yuǎn)程進(jìn)程的線(xiàn)程就可能引發(fā)訪(fǎng)問(wèn)違規(guī)”;
至于第四步中為什么不直接對(duì)LoadLibrary進(jìn)行調(diào)用,《WINDOWS核心編程》中是這樣描述的:
“如果在對(duì)C r e a t e R e m o t e T h r e a d的調(diào)用中使用一個(gè)對(duì)L o a d L i b r a r y A的直接引用,這將在你的模塊的輸入節(jié)中轉(zhuǎn)換成L o a d L i b r a r y A的形實(shí)替換程序的地址。將形實(shí)替換程序的地址作為遠(yuǎn)程線(xiàn)程的起始地址來(lái)傳遞,會(huì)導(dǎo)致遠(yuǎn)程線(xiàn)程開(kāi)始執(zhí)行一些令人莫名其妙的東西。其結(jié)果很可能造成訪(fǎng)問(wèn)違規(guī)?!?
好了,下面開(kāi)始我們的例子。
?。薄⑼厦鎽?yīng)用HOOK來(lái)進(jìn)行DLL注入一樣,我們先創(chuàng)建一個(gè)DLL工程,這個(gè)DLL完全可以不編寫(xiě)任何代碼,因?yàn)槲覀冎幌雽LL注入到指定進(jìn)程就達(dá)到目的了,但為了好看,我還是隨便在其中寫(xiě)一個(gè)API函數(shù)。代碼如下:
extern "C" __declspec(dllexport) __stdcall void About();
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------
void __declspec(dllexport) __stdcall About()
{
MessageBox(NULL,"這個(gè)DLL模塊演示了DLL的注入技術(shù)。\n"
"通過(guò)程序的調(diào)用LoadLibrary將本模塊注入到指定的"
"進(jìn)程的地址空間中。", "DLL注入技術(shù)",
MB_ICONINFORMATION + MB_OK);
}
編譯它,就得到我們用來(lái)注入的DLL文件了。接下來(lái)是測(cè)試工程。
?。病⒕帉?xiě)測(cè)試工程。用BCB建立一個(gè)應(yīng)用程序工程,在窗體中放入兩個(gè)按鈕,一個(gè)用來(lái)注入,一個(gè)用來(lái)撤消,另外還有一個(gè)文本框控件,用來(lái)等待用戶(hù)輸入進(jìn)程ID號(hào)。代碼如下:
//---------------------------------------------------------------------------
// DLL注入函數(shù)
BOOL WINAPI LoadLib(DWORD dwProcessId, LPWSTR lpszLibName)
{
HANDLE hProcess = NULL,
hThread = NULL;
LPWSTR lpszRemoteFile = NULL;
// 打開(kāi)遠(yuǎn)程進(jìn)程
hProcess = OpenProcess(PROCESS_CREATE_THREAD
| PROCESS_VM_OPERATION
| PROCESS_VM_WRITE,
FALSE,
dwProcessId);
if (hProcess == NULL)
{
MessageBox(NULL, ("OpenProcess failed with error "
+ IntToStr(GetLastError())).c_str(), "Error",
MB_ICONINFORMATION + MB_OK);
return FALSE;
}
// 在遠(yuǎn)程進(jìn)程中分配存貯DLL文件名的空間
lpszRemoteFile = (LPWSTR)VirtualAllocEx(hProcess, NULL,
sizeof(WCHAR) * lstrlenW(lpszLibName) + 1,
MEM_COMMIT, PAGE_READWRITE);
if (lpszRemoteFile == NULL)
{
MessageBox(NULL, ("VirtualAllocEx failed with error "
+ IntToStr(GetLastError())).c_str(), "Error",
MB_ICONINFORMATION + MB_OK);
return FALSE;
}
// 復(fù)制DLL文件名到遠(yuǎn)程剛分配的進(jìn)程空間
if (!WriteProcessMemory(hProcess, lpszRemoteFile,
(PVOID)lpszLibName, sizeof(WCHAR) * lstrlenW(lpszLibName) + 1,
NULL))
{
MessageBox(NULL, ("WriteProcessMemory failed with error "
+ IntToStr(GetLastError())).c_str(), "Error",
MB_ICONINFORMATION + MB_OK);
return FALSE;
}
// 取得LoadLibrary函數(shù)在Kennel32.dll中的地址
PTHREAD_START_ROUTINE pfnThreadRtn =
(PTHREAD_START_ROUTINE)GetProcAddress(
GetModuleHandle("Kernel32.dll"),"LoadLibraryW");
if (pfnThreadRtn == NULL)
{
MessageBox(NULL, ("GetProcAddress failed with error "
+ IntToStr(GetLastError())).c_str(), "Error",
MB_ICONINFORMATION + MB_OK);
return FALSE;
}
// 創(chuàng)建遠(yuǎn)程線(xiàn)程
hThread = CreateRemoteThread(hProcess,
NULL,
0,
pfnThreadRtn, // LoadLibrary地址
lpszRemoteFile, // 要加載的DLL名
0,
NULL);
if (hThread == NULL)
{
MessageBox(NULL, ("CreateRemoteThread failed with error "
+ IntToStr(GetLastError())).c_str(), "Error",
MB_ICONINFORMATION + MB_OK);
return FALSE;
}
// 等待線(xiàn)程返回
WaitForSingleObject(hThread, INFINITE);
// 釋放進(jìn)程空間中的內(nèi)存
VirtualFreeEx(hProcess, lpszRemoteFile, 0, MEM_RELEASE);
// 關(guān)閉句柄
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
// 在進(jìn)程空間釋放注入的DLL
BOOL WINAPI FreeLib(DWORD dwProcessId, LPTSTR lpszLibName)
{
HANDLE hProcess = NULL,
hThread = NULL,
hthSnapshot = NULL;
MODULEENTRY32 hMod = {sizeof(hMod)};
BOOL bFound;
// 取得指定進(jìn)程的所有模塊映象
hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
dwProcessId);
if (hthSnapshot == NULL)
{
MessageBox(NULL, ("CreateRemoteThread failed with error "
+ IntToStr(GetLastError())).c_str(), "Error",
MB_ICONINFORMATION + MB_OK);
return FALSE;
}
// 取得所有模塊列表中的指定的模塊
BOOL bMoreMods = Module32First(hthSnapshot, &hMod);
if (bMoreMods == FALSE)
{
MessageBox(NULL, ("Module32First failed with error "
+ IntToStr(GetLastError())).c_str(), "Error",
MB_ICONINFORMATION + MB_OK);
return FALSE;
}
// 循環(huán)取得想要的模塊
for (;bMoreMods; bMoreMods = Module32Next(hthSnapshot, &hMod))
{
//ShowMessage(String(hMod.szExePath) + " | " + String(lpszLibName));
if ((strcmp(hMod.szExePath, lpszLibName) == 0) ||
(strcmp(hMod.szModule, lpszLibName) == 0))
break;
}
// 打開(kāi)進(jìn)程
hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION,
FALSE, dwProcessId);
if (hProcess == NULL)
{
MessageBox(NULL, ("OpenProcess failed with error "
+ IntToStr(GetLastError())).c_str(), "Error",
MB_ICONINFORMATION + MB_OK);
return FALSE;
}
// 取得FreeLibrary函數(shù)在Kernel32.dll中的地址
PTHREAD_START_ROUTINE pfnThreadRtn =
(PTHREAD_START_ROUTINE)GetProcAddress(
GetModuleHandle("Kernel32.dll"), "FreeLibrary");
if (pfnThreadRtn == NULL)
{
MessageBox(NULL, ("GetProcAddress failed with error "
+ IntToStr(GetLastError())).c_str(), "Error",
MB_ICONINFORMATION + MB_OK);
return FALSE;
}
// 創(chuàng)建遠(yuǎn)程線(xiàn)程來(lái)執(zhí)行FreeLibrary函數(shù)
hThread = CreateRemoteThread(hProcess,
NULL,
0,
pfnThreadRtn,
hMod.modBaseAddr,
0,
NULL);
if (hThread == NULL)
{
MessageBox(NULL, ("CreateRemoteThread failed with error "
+ IntToStr(GetLastError())).c_str(), "Error",
MB_ICONINFORMATION + MB_OK);
return FALSE;
}
// 等待線(xiàn)程返回
WaitForSingleObject(hThread, INFINITE);
// 關(guān)閉句柄
CloseHandle(hThread);
CloseHandle(hthSnapshot);
CloseHandle(hProcess);
return TRUE;
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btLoadClick(TObject *Sender)
{
m_szDllFile = Application->ExeName;
m_szDllFile = m_szDllFile.SubString(0, m_szDllFile.Length()
- String(StrRScan(m_szDllFile.c_str(),'\\')).Length());
m_szDllFile = m_szDllFile + "\\DllLib.dll";
m_dwProcessId = StrToInt(Edit->Text);
LoadLib(m_dwProcessId, WideString(m_szDllFile).c_bstr());
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btUnloadClick(TObject *Sender)
{
FreeLib(m_dwProcessId, m_szDllFile.c_str());
}
//---------------------------------------------------------------------------
好了,把上面的工程編譯成生EXE文件,接下來(lái)我們就可以進(jìn)行DLL的注入測(cè)試了。先打開(kāi)記事本(當(dāng)然你也可以打開(kāi)其它的進(jìn)程,或直接在已經(jīng)加載的進(jìn)程測(cè)試),通過(guò)WINDOWS的任務(wù)管理器,找到它的進(jìn)程ID。然后運(yùn)行我們的測(cè)試工程,在文本框中輸入進(jìn)程ID,點(diǎn)擊注入。這時(shí)我們就可以通過(guò)我們最先寫(xiě)的小工具來(lái)查看它的進(jìn)程空間中所包含的模塊了,你會(huì)發(fā)現(xiàn),我們的DLL已經(jīng)成功加載到了它的進(jìn)程空間中。點(diǎn)擊卸載,取消DLL的注入。
轉(zhuǎn)載請(qǐng)說(shuō)明出處:六百號(hào)技術(shù) - SEO優(yōu)化,網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)絡(luò)編程,軟件技巧,網(wǎng)絡(luò)知識(shí),系統(tǒng)技術(shù) ? 進(jìn)行DLL注入的一種方法
標(biāo)簽: