摘要:木馬程序設計最主要的工作是將功能代碼實現隱藏,我們可以采用遠程線程技術,通過動態鏈接庫方法,借助遠程線程將木馬作為線程隱藏在其他進程中,從而達到隱藏的目的。
關鍵詞:進程; 木馬; 動態鏈接庫
中圖分類號:TP393文獻標識碼:A文章編號:1009-3044(2010)11-2612-02
1 概述
Windows系統平臺上提供了有效的編程和運行環境,可以將獨立的程序模塊創建為較小的DLL(Dynamic Linkable Library)文件,同時可對這些DLL文件功能模塊進行單獨編譯和測試。在運行時,只有當EXE程序確實要調用這些DLL模塊的情況下,系統才會將它們裝載到內存空間中。此方式不僅減少了EXE文件的大小和對內存空間的需求,而且使這些DLL模塊可以同時被多個應用程序使用。Microsoft Windows自己就將一些主要的系統功能以DLL模塊的形式實現。例如IE中的一些基本功能就是由DLL文件實現的,它可以被其它應用程序調用和集成。
在windows系統中,WS2_32.DLL是使用標準的動態鏈接庫來加載服務,然后通過加載的服務來實現系統功能,并調用WSPStartup來初始化。WSPStartup是Windows Socket 2的初始化函數,也就是入口函數,通過指定參數,來實現提供應用程序所期望的協議信息,然后我們可以獲得所保存的系統服務提供者的DLL名稱和路徑,加載系統服務后,可以查找到自己所要加載DLL的相關信息, 進而調用系統的各個服務提供者函數。在數據傳輸服務提供者的實現中,我們需要兩個程序,一個是可執行文件用來安裝傳輸服務提供者;另一個就是DLL形式的數據傳輸服務提供者。
2 基本原理
DLL木馬的實現原理是:程序員在DLL程序中包含木馬功能相關的代碼,隨后在目標主機系統中選擇特定進程,以某種方式強行執行進程,并且調用包含木馬功能的DLL,最終使木馬功能代碼得到執行,從而達到侵襲目標系統的目的。由于DLL程序自身的特點決定了以這種形式加載木馬不僅可行,而且具有良好的隱藏性:
1) DLL程序被映射到宿主進程的地址空間中,可以共享宿主進程的資源,在目標主機的級別進行非法訪問,獲取相應的系統資源;
2) DLL程序沒有獨立的進程地址空間,可以避免在目標主機中留下痕跡,從而達到隱蔽自身的目的。
在每個操作系統中都有系統網絡服務,它們是在系統啟動時自動加載,而且很多是基于IP協議的。若程序設計者編制一個IP協議的傳輸服務提供者,并安裝在服務提供者數據庫的最前端,系統網絡服務就會加載我們的服務提供者。如果將木馬功能代碼嵌入到服務提供者的DLL文件之中,在啟動系統網絡服務時我們的木馬程序也會被啟動。這種形式的DLL木馬只須被安裝一次,而后就會被自動加載到可執行文件的進程中,還有一個特點就是它會被多個網絡服務加載。通常在系統關閉時,系統網絡服務才會結束,所以我們的木馬程序同樣可以在系統運行時保持激活狀態。
我們可以將自已的木馬以線程方式注入遠程進程之中,遠程進程則是合法的用戶程序,這樣用戶管理者看到的只是合法進程,而無法發現木馬線程的存在.從而達到隱藏的目的。
3 動態鏈接庫木馬的實現
若DLL木馬實現了隱藏,我們在任務管理器中是看不到木馬“進程”,它完全溶進了系統的內核。DLL木馬可以注入其它進程的方法為遠程線程插入,遠程線程插入技術指的是通過在另一個進程中創建遠程線程的方法進入那個進程的內存地址空間。將木馬功能以DLL的形式實現后,需要使用插入到目標進程中的遠程線程將該木馬DLL插入到目標進程的地址空間,即利用該線程通過調用Windows API LoadLibrary函數來加載木馬DLL,從而實現木馬對系統的侵入。
DLL木馬功能代碼程序注入到系統中必須涉及到一個非常重要的Windows API函數 CreateRemoteThread。與之相比所習慣使用的CreateThrea函數只能在進程自身內部產生一個新的線程,而且被創建的新線程與主線程共享地址空間和其他資源;而CreateRemoteThread則不同,它可以在另外的進程中產生線程。CreateRemoteThread函數中的參數hProcess用于指定要創建線程的遠程進程,其函數原型為:
HANDLE CreateRemoteThread(
HANDLE hProcess, //遠程進程句柄
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
線程函數的代碼不能位于我們用來注入DLL木馬的進程所在的地址空間中,也就是說,我們不能想當然地自己寫一個函數,并把這個函數作為遠程線程的入口函數;不能把本進程的指針作為CreateRemoteThread的參數,因為本進程的內存空間與遠程進程的不一樣。
我們可以將已經編制好的木馬功能代碼編譯為DLL文件,然后將此DLL木馬注入程序,也就是將其注入到系統正在運行的系統進程中去,其實現步驟如下:
3.1 打開遠程進程
hRemoteProcess = OpenProcess(
PROCESS_CREATE_THREAD | //允許創建線程
PROCESS_VM_OPERATION | //允許VM操作
PROCESS_VM_WRITE, //允許VM寫
FALSE, dwRemoteProcessId );
3.2 計算DLL路徑名需要的內存空間
int cb = (1 + lstrlenW(pszLibFileName)) * sizeof(WCHAR);
pszLibFileRemote = (PWSTR) VirtualAllocEx( hRemoteProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
3.3將DLL的路徑名復制到遠程進程的內存空間
iReturnCode = WriteProcessMemory(hRemoteProcess, pszLibFileRemote, (PVOID) pszLibFileName, cb, NULL);
3.4 計算LoadLibraryW的入口地址
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT(\"Kernel32\")), \"LoadLibraryW\");
3.5 啟動遠程線程,通過遠程線程調用用戶的DLL文件
hRemoteThread = CreateRemoteThread( hRemoteProcess, NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL);
3.6 等待遠程線程退出
WaitForSingleObject(hRemoteThread, INFINITE);
4 總結
DLL木馬注入進程進行隱藏的技術和方法有很多,而且這一技術發展也相當快,本文僅從一個側面加以討論,希望通過這一探討讓我們對DLL木馬注入進程隱藏技術有一個更清楚的認識,同時也為我們防范他人利用進程手段非法入侵提供參考。