果洛皆料电子有限公司

進(jìn)行DLL注入的一種方法

  • 發(fā)布于:2020-12-29
  • 258 人圍觀
利用遠(yuǎn)程線(xiàn)程來(lái)進(jìn)行DLL注入

這種方法只能在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的注入。
萬(wàn)企互聯(lián)
標(biāo)簽: