一、引言
隨著信息技術(shù)的快速發(fā)展,人們會(huì)越來(lái)越重視信息的安全性,信息數(shù)據(jù)的安全保密已經(jīng)成為研究計(jì)算機(jī)發(fā)展的一個(gè)重要課題。在其它
識(shí)別技術(shù)尚不能普及情況下,密碼常常被用戶用作保護(hù)他們寶貴數(shù)據(jù)的最后一道屏障,然而有了密碼,用戶也不能高枕無(wú)憂,因?yàn)楝F(xiàn)在有很多的工具可以窮舉和竊取
用戶密碼,下面通過(guò)Detours簡(jiǎn)單介紹一下截取密碼的基本原理,以此提醒用戶密碼要定期更換,而且其它相關(guān)的安全保衛(wèi)措施同樣不可忽視。
二、基本原理
在Windows
編程中,人們普遍使用密碼編輯框,來(lái)提示用戶使用密碼,密碼編輯框除了回顯字符之外,與一般的編輯框框控件并沒(méi)有任何區(qū)別。通過(guò)調(diào)用
GetWindowText和GetDlgItemText函數(shù),或者向該密碼編輯框窗口發(fā)送WM_GETTEXT消息,用戶很容易獲得這些輸入的密碼字
符,這可以通過(guò)Visual
Studio提供的SPY++工具來(lái)驗(yàn)證。如果用戶為了圖省事,讓系統(tǒng)記住這些密碼,免去每次登錄時(shí)密碼輸入,這將會(huì)使他們陷入更加危險(xiǎn)的境地,因?yàn)楝F(xiàn)在
有許多類(lèi)似于Reveal的小程序,可以獲得鼠標(biāo)所指之處的密碼,它們基本上都是通過(guò)向密碼編輯框發(fā)送WM_GETTEXT消息實(shí)現(xiàn)的。即便不讓系統(tǒng)保存
密碼,用戶也不能大意,因?yàn)榫驮谀爿斎氤绦虻谋澈螅赡茈[藏著
這么一個(gè)惡意的程序,它會(huì)記錄你輸入的任何字符,并神不知鬼不覺(jué)地把它記錄到一個(gè)文件中。
這樣的程序一般都是通過(guò)鉤子函數(shù)或者
API
HOOK實(shí)現(xiàn)的。因?yàn)橛脩糨斎胪昝艽a之后,還要提交給應(yīng)用程序來(lái)驗(yàn)證,并以此確定他們是否為合法用戶。這時(shí)候,應(yīng)用程序往往會(huì)調(diào)用上述函數(shù)或者發(fā)送
WM_GETTEXT消息,獲得用戶輸入的密碼文本。如果有這么一個(gè)程序,能夠截獲這些API函數(shù)調(diào)用或者截獲這些窗口消息,那么它就會(huì)在密碼到達(dá)應(yīng)用程
序之前先期截獲這些密碼。
這些程序一般都會(huì)在系統(tǒng)啟動(dòng)時(shí),自動(dòng)運(yùn)行,然后安裝系統(tǒng)鉤子,截獲GetWindowText或
GetDlgItemText函數(shù),或者截獲Windows消息(如WM_DESTROY),并向密碼及其兄弟窗口發(fā)送WM_GETTEXT消息,即可獲
得包括用戶名在內(nèi)的全部文本,保存到文件之后,然后把控制權(quán)交給系統(tǒng)。這樣的程序一般都有
局限性,因?yàn)樗仨氶_(kāi)機(jī)自動(dòng)運(yùn)行后,才會(huì)起作用,因此通過(guò)修改注冊(cè)編輯表,很容易發(fā)現(xiàn)它們的蹤跡,并把它們清除到系統(tǒng)之外。而且在安全模式下,這些程序除
非你主動(dòng)運(yùn)行它,否則它永遠(yuǎn)不會(huì)被激活。
注意這里的運(yùn)行并非一定要你用鼠標(biāo)去雙擊一個(gè)應(yīng)用程序,如果你雙擊的文件是一個(gè)TXT文本文件(或者BMP、HTML等文件),而這些文件默認(rèn)打開(kāi)程序已
被修改為黑客程序,這種情況下數(shù)據(jù)文件成了導(dǎo)火索,它們同樣也會(huì)激活黑客程序。
還有一種程序是以DLL形式寄生在可執(zhí)行文件之上
(譬如記事本Notepad、畫(huà)筆Mspaint)_),這往往需要一個(gè)安裝程序,負(fù)責(zé)修改可執(zhí)行文件,使得可執(zhí)行文件運(yùn)行時(shí)能夠自動(dòng)加載這些(木馬程
序)動(dòng)態(tài)鏈接庫(kù),刪除這些動(dòng)態(tài)鏈接庫(kù),則會(huì)導(dǎo)致可執(zhí)行文件無(wú)法運(yùn)行。這種情況下,除非你重新安裝應(yīng)用程序, 否則你無(wú)法甩掉跟在你程序背后的鬼影。
三、具體實(shí)現(xiàn)
1.動(dòng)態(tài)鏈接庫(kù)的注入
動(dòng)
態(tài)鏈接庫(kù)是WIN32系統(tǒng)的一個(gè)重要組成部分,它能夠動(dòng)態(tài)地裝入到進(jìn)程的地址空間,
動(dòng)態(tài)鏈接庫(kù)一旦注入到應(yīng)用程序的進(jìn)程空間,就會(huì)成為應(yīng)用程序的運(yùn)行中的一部分,和應(yīng)用程序代碼一起運(yùn)行。由于有些進(jìn)程壓根就沒(méi)有用到某些動(dòng)態(tài)鏈接庫(kù),包括
它的輸出數(shù)據(jù)和輸出函數(shù)。可以說(shuō)這些應(yīng)用程序和動(dòng)態(tài)鏈接庫(kù)之間沒(méi)有任何“血緣關(guān)系”,應(yīng)用程序也從來(lái)不會(huì)去主動(dòng)地加載這些動(dòng)態(tài)鏈接庫(kù),因此,我們必須編寫(xiě)
代碼實(shí)現(xiàn)DLL庫(kù)的注入。把動(dòng)態(tài)鏈接庫(kù)注入到另外一個(gè)進(jìn)程。最經(jīng)典的做法是,在DLL中安裝一個(gè)鉤子函數(shù),這樣系統(tǒng)會(huì)幫我們把它注入到每一個(gè)受該鉤子函數(shù)
影響的進(jìn)程之中。
鉤子函數(shù)的安裝往往需要一個(gè)安裝程序,負(fù)責(zé)調(diào)用SetWindowsHookEx函數(shù),然而如果我們每次使用鉤子
函數(shù)時(shí)都運(yùn)行安裝程序,那將是非常麻煩,對(duì)于一個(gè)木馬程序來(lái)說(shuō),很容易暴露自己,因此我們希望我們的動(dòng)態(tài)連接庫(kù)能夠寄生在一個(gè)可執(zhí)行文件之上,一旦這個(gè)應(yīng)
用程序執(zhí)行時(shí),它就會(huì)在進(jìn)程初始化階段(DLL_PROCESS_ATTACH),安裝鉤子函數(shù),這樣應(yīng)用程序甚至系統(tǒng)的窗口消息都會(huì)處于鉤子函數(shù)的監(jiān)控
之下,鉤子函數(shù)的鉤子過(guò)程會(huì)負(fù)責(zé)截獲有用的消息,并作相應(yīng)的處理。 微軟公司提供的Detours工具包(
http://www.research.microsoft.com/sn/detours),
剛好能夠滿足我們這個(gè)要求。Detours除了提供了一組API攔截的函數(shù)之外,還提供了一組函數(shù)能夠很容易地實(shí)現(xiàn)DLL的注入,利用這組函數(shù),我們既可
以創(chuàng)建一個(gè)注入了DLL的新進(jìn)程,也可以把DLL注入到一個(gè)已經(jīng)運(yùn)行的進(jìn)程,更重要的是,它還能夠修改應(yīng)用程序的文件頭,在文件頭中加入DLL的信息,這
樣應(yīng)用程序修改后不用任何干預(yù),它自身就能負(fù)責(zé)完成動(dòng)態(tài)鏈接庫(kù)的加載。
2.Detours注入動(dòng)態(tài)鏈接庫(kù)
我
們知道win32應(yīng)用程序都采用win 32二進(jìn)制PE格式存儲(chǔ),PE是一個(gè)COFF擴(kuò)展(Common Object File
Format)。一個(gè)win32二進(jìn)制文件是由下面幾部分組成的,一個(gè)DOS 兼容頭、一個(gè)PE頭、
一個(gè)包含程序代碼的文本段、一個(gè)包含初始化數(shù)據(jù)的數(shù)據(jù)段、一個(gè)列舉引用DLL
和函數(shù)名的引入表、一個(gè)列舉代碼和輸出符號(hào)的輸出表,除了兩個(gè)頭結(jié)構(gòu)之外,其余部分都是可選的,在某些win32文件中可能某些部分不存在。
為
了修改win 32 二進(jìn)制代碼,Detours
又在輸出表和調(diào)試符號(hào)部分中間創(chuàng)建了一個(gè)新的.Detours段(如上圖所示)(注:調(diào)試符號(hào)部分必須位于win32
二進(jìn)值文件的最后),這個(gè)新的.Detours段包含了一個(gè)Detours頭記錄和一個(gè)原來(lái)PE頭的副本。如果要修改輸入表的話,Detours就會(huì)創(chuàng)建
一個(gè)新的輸入表,并把它添加到復(fù)制的PE
頭中,然后修改原始的PE頭結(jié)構(gòu),使其指向新的輸入表。最后,Detours把用戶的Payloads(負(fù)載)追加到.
Detours段的尾部,然后在文件尾部添加調(diào)試符號(hào)信息。由于Detours備份了原始的PE頭,所以這個(gè)過(guò)程完全可逆,以便能夠去除.Detours
段,恢復(fù)exe文件到未注入前的樣子。
創(chuàng)建一個(gè)新的輸入表有兩個(gè)目的,一個(gè)目的是它能夠保存原來(lái)的輸入表,以便需要時(shí)恢復(fù)對(duì)原來(lái)文件的修改;另一個(gè)目的是,新的輸入表可以包含重命名的動(dòng)態(tài)連接庫(kù)和函數(shù),還可以包含新的動(dòng)態(tài)連接庫(kù)和函數(shù).
Detours
既提供了一組編輯輸入表,添加、枚舉、去除Payloads(負(fù)載),再綁定二進(jìn)制的函數(shù),也提供了一組枚舉映射地址空間的二進(jìn)制文件、定位映射文件
Payloads(負(fù)載)的函數(shù)。每一個(gè)Payload(負(fù)載)均由一個(gè)GUID (a 128- bit globally unque
identifier全球唯一標(biāo)識(shí)符)標(biāo)識(shí)。
這些函數(shù)的使用讀者可以參考Detours提供的例子程序SetDll.cpp文件。
3.消息攔截
一
旦動(dòng)態(tài)鏈接庫(kù)注入到應(yīng)用程序后,它就會(huì)在進(jìn)程初始化階段完成鉤子函數(shù)的安裝,這里我們安裝了兩種鉤子類(lèi)型,WH_GETMESSAGE和
WH_CALLWNDPROC,鉤子函數(shù)的處理過(guò)程主要對(duì)WM_SETFOCUS和WM_DESTROY消息進(jìn)行攔截,對(duì)前一個(gè)消息,先通過(guò)獲得其類(lèi)名
(GetClassName函數(shù))和窗口風(fēng)格(GetWindowLong函數(shù)),判斷它是否是一個(gè)密碼編輯框(注意VisualC++、Delphi、
Visual
Basic編輯框的類(lèi)名都不一樣)。如果是,則把它本身窗口及其兄弟窗口、父窗口的窗口句柄保存到一個(gè)數(shù)組中,一旦系統(tǒng)向窗口WM_DESTROY消息
時(shí),消息被鉤子函數(shù)截獲,鉤子處理過(guò)程會(huì)向保存到數(shù)組中的每一個(gè)窗口句柄發(fā)送WM_GETTEXT,獲得對(duì)話框標(biāo)題或各個(gè)編輯框的文本。
四、程序的使用
本
程序是在Windows 2000環(huán)境下用Visual C++
6.0調(diào)試通過(guò)的,在Windows98環(huán)境下也可以運(yùn)行。使用時(shí),先運(yùn)行DllPatch.Exe程序,然后瀏覽到有密碼的應(yīng)用程序,確認(rèn)后,
DllPath程序會(huì)給目標(biāo)應(yīng)用程序創(chuàng)建一個(gè)備份文件,然后修改應(yīng)用程序,并把InetPub.Dll文件拷貝到目標(biāo)應(yīng)用程序目錄和Windows系統(tǒng)目
錄。這時(shí)你可以利用View Dependency
工具打開(kāi)應(yīng)用程序文件,你會(huì)發(fā)現(xiàn)它里面又多引用了一個(gè)名叫InetPub.Dll的動(dòng)態(tài)鏈接庫(kù).密碼截獲后,木馬程序會(huì)把密碼文件存放在臨時(shí)文件目錄下的
一個(gè)擴(kuò)展名為tmp的文件中,為了便于說(shuō)明,該文件的內(nèi)容沒(méi)有加密,同時(shí)Windows系統(tǒng)目錄的Kernel32.ini文件也保存了有關(guān)密碼的一些信
息。真正的黑客程序可能就不會(huì)這么做,因?yàn)檫@很容易暴露自己,而且它還會(huì)修改InetPub.dll文件的日期與應(yīng)用程序一致。也許你會(huì)說(shuō),我馬上更改密
碼,你截獲的密碼照樣進(jìn)不去,殊不知就在你更改密碼的同時(shí),更改后的新密碼也被記錄下來(lái)。
通過(guò)這個(gè)程序,我們可以看到僅僅依靠密碼來(lái)保證系統(tǒng)的安全是遠(yuǎn)遠(yuǎn)不夠的。
點(diǎn)擊這里下載
源程序和
演示程序。
DETOURS 下載地址:
http://www.research.microsoft.com/sn/detours http://research.microsoft.com/sn/detours