*本文原創(chuàng)作者:nickchang,本文屬FreeBuf原創(chuàng)獎(jiǎng)勵(lì)計(jì)劃,未經(jīng)許可禁止轉(zhuǎn)載
背景
二十多年來,操作系統(tǒng)的發(fā)展突飛猛進(jìn),windows也走過了各種版本。微軟每次都在新版本中加入很多的改進(jìn),比如完善某些API,引入新的安全機(jī)制(UAC,ASLR,…),調(diào)整系統(tǒng)目錄結(jié)構(gòu)(Application Data目錄 從win98的%windir%Application Data變成winXp的%USERPROFILE%Application Data,后又變成Vista的%APPDATA%),這些改動(dòng)會(huì)影響windows的向后兼容性(backward compatibility)。
對于一個(gè)開發(fā)windows程序的程序員來說,他無法預(yù)見未來的windows會(huì)作出哪些調(diào)整,那么如何保證現(xiàn)在發(fā)布的程序也能在未來新版本的windows下運(yùn)行呢?對于第三方軟件商來說,這基本上就是不可能完成的任務(wù)。一個(gè)在Vista運(yùn)行得好好的程序很可能在win7下無法運(yùn)行。因?yàn)橐粋€(gè)極小的API改動(dòng)都可能讓該程序崩潰。
比如下圖,在SDK6.0(Vista)和SDK7.1(win7)下,clusapi.dll 里的CreateCluster() 的參數(shù)不一致:新版本的CreateCluster()沒有tAcceptPartialFailure這個(gè)參數(shù)。(如果感興趣的話,這個(gè)鏈接 http://abi-laboratory.pro/compatibility/提供了更全面的各個(gè)版本windows API兼容性的比較。)
假設(shè)一個(gè)在SDK6.0下編譯的程序調(diào)用了這個(gè)API,代碼編譯后如下:
Push pvCallbackArg
Push pfnProgressCallback
Push tAcceptPartialFailure
Push pConfig
Call CreateCluster
然而win7下,新版clusapi.dll的CreateCluster()并沒有tAcceptPartialFailure這個(gè)參數(shù),導(dǎo)致該程序多push進(jìn)一個(gè)參數(shù),這會(huì)使該函數(shù)在運(yùn)行時(shí)發(fā)生不可預(yù)見的問題。因此,微軟每推出一款新版本的windows,開發(fā)者原則上理應(yīng)檢查自己的程序是否在新版本windows上存在問題。如果有問題,則進(jìn)行兼容性修復(fù),比如重寫API調(diào)用并且重新編譯。但是事實(shí)上,大多數(shù)軟件公司并沒有興趣長期維護(hù)舊產(chǎn)品,而且有的軟件公司已經(jīng)倒閉,開發(fā)團(tuán)隊(duì)都散了。這就造成了很多舊軟件無法在新windows下運(yùn)行。
這種情況下用戶會(huì)責(zé)備誰呢?當(dāng)然是微軟,因?yàn)檫@個(gè)程序在win7下運(yùn)行得好好的,為什么win10下就跑不起來了呢?程序不會(huì)有問題,一定是win10的問題!這樣一來,微軟不得不為第三方軟件商擦屁股。傳說微軟在研發(fā)win95的時(shí)候特意派人去軟件專賣店買了一卡車win3.1下的軟件,拿回去逐一測試能否在win95下正常運(yùn)行。如果發(fā)現(xiàn)不能正常運(yùn)行,如何修復(fù)呢?
這就要用到本文的主角:Shim。Shim的本意是墊圈或墊片。理論上說,任何的計(jì)算機(jī)問題都可以新增一層邏輯來解決。Shim也是這么一個(gè)墊在應(yīng)用程序和windowsAPI之間的邏輯層。
Freebuf上有一篇很好的關(guān)于shim的簡介( http://www.freebuf.com/news/48878.html)。簡而言之,當(dāng)一個(gè)應(yīng)用程序開始運(yùn)行的時(shí)候,Shim把導(dǎo)入地址表(IAT)里的系統(tǒng)DLL庫函數(shù)地址用ShimDLL里的函數(shù)地址來替換,從而可以透明的攔截其API調(diào)用,修改其傳遞的參數(shù)等等。這個(gè)過程相當(dāng)于windows自己做了一個(gè)IAThooking。
如圖所示,一個(gè)應(yīng)用程序在調(diào)用Windows API之前,修改了IAT從而被重定向到Shim。
如果你對Shim的細(xì)節(jié)感興趣,請參考這兩篇對Shim逆向的研究http://blog.csdn.net/celestialwy/article/details/707148
http://bbs.pediy.com/showthread.php?t=175483
當(dāng)然,并不是所有的程序都會(huì)被Shim。Windows自己維護(hù)著一個(gè)Shim數(shù)據(jù)庫(sdb文件,位于%windir%AppPatchsysmain.sdb)。當(dāng)一個(gè)應(yīng)用程序創(chuàng)建進(jìn)程的時(shí)候,WindowsLoader會(huì)檢查sysmain.sdb,并判斷時(shí)否該程序需要被修復(fù),以及如何被修復(fù)。比如下圖,當(dāng)我運(yùn)行test.exe的時(shí)候,用processmonitor可以看見系統(tǒng)讀取了sysmain.sdb這個(gè)文件。
Shim 數(shù)據(jù)庫包含了大約5000多條記錄。每個(gè)記錄對應(yīng)一個(gè)需要被Shim的應(yīng)用程序。記錄的內(nèi)容分兩部分:
1.定義如何識別該應(yīng)用程序。比如通過文件名識別,或者通過某些文件屬性值(版本號,文件大小,等等)來匹配。例如識別大航海時(shí)代4就利用了其文件名(dk4.exe,dk4pk.exe,dk4.ico)并且dk4.exe的”product_name”屬性必須包含字符串”大航海時(shí)代”.
2.定義如何修復(fù)該應(yīng)用程序。比如修改操作系統(tǒng)的版本號,修改API參數(shù),禁用某些功能等等。
做一個(gè)小實(shí)驗(yàn),在win7下隨便找一個(gè)帶窗口的可執(zhí)行文件,把文件名改為”3D Frog Frenzy.exe”。然后運(yùn)行這個(gè)文件,你會(huì)發(fā)現(xiàn)AltTab沒反應(yīng)了。這是因?yàn)镾him起了作用,如下圖所示,Shim只要識別了應(yīng)用程序文件名為”3DFrog Frenzy.exe”,便啟動(dòng)了對應(yīng)的修復(fù)機(jī)制,包括忽略AltTab。因此,只要文件名為”3D Frog Frenzy.exe”,AltTab就失效了。
這里推介一款微軟的Shim工具: Application Compatibility Toolkit(ACT) (https://www.microsoft.com/en-us/download/details.aspx?id=7352)這個(gè)工具可以查看Shim數(shù)據(jù)庫。打開瀏覽一下,看到一大堆十幾年前的經(jīng)典軟件,比如豪杰超級解霸,東方快車。。。
利用Shim的攻擊
除了微軟自帶的Shim數(shù)據(jù)庫以外,用戶還可以給任意程序自定義Shim修復(fù)方式。這在提高兼容性的同時(shí)也引入了一些安全隱患。特別是ACT工具內(nèi)嵌了800多種修復(fù)方式,ACT工具允許用戶很容易的給任意程序添加”特殊的”修復(fù)方法(大概30秒就可以搞定)。這些”特殊的”修復(fù)方法可能被攻擊者用來做一些猥瑣的事情。用ACT工具自定義Shim的方法如下:
1.先選擇一個(gè)應(yīng)用程序
2.然后可以選擇修復(fù)方式,大概有300多種可供選擇,如果啟動(dòng)ACT的時(shí)候用了“/x”參數(shù),修復(fù)方式會(huì)增加到800多種。
Sean Pierce在blackhat 2015總結(jié)過一些可以被惡意利用的Shim修復(fù)方法:
1.強(qiáng)制關(guān)閉進(jìn)程:”TerminateExe”可以用來強(qiáng)制關(guān)閉某些安全程序(還有那些sysinternal的檢測工具),相似的還有”IgnoreLoadLibrary”。
2.禁用防御機(jī)制:選擇”DisableASLR”, ”DisableSeh”等可以禁用掉某些程序的防御機(jī)制,從而進(jìn)一步溢出攻擊。
3.系統(tǒng)駐留:用”InjectDLL”, ”LoadLibraryRedirect”等可以把惡意代碼注入到一些常用程序,比如WORD.exe。那么每次啟動(dòng)Word.exe,惡意代碼會(huì)先運(yùn)行。這種駐留方法比傳統(tǒng)的方法(注冊表)更不容易被發(fā)現(xiàn)。安全檢測工具例如Autorun.exe也發(fā)現(xiàn)不了。
4.繞過分析:病毒可以把一部分重要代碼(比如脫殼解密)放在DLL里,然后設(shè)置自定義Shim用”InjectDLL”調(diào)入。在這種情況下,簡單的把病毒和DLL拷貝到沙盒里運(yùn)行進(jìn)行動(dòng)態(tài)分析往往不會(huì)成功。因?yàn)?ldquo;InjectDLL”是自定義的Shim,而沙盒上沒有設(shè)置同樣的Shim。
比如我們?nèi)绻幌胱?60正常工作,那么可以給360安全中心設(shè)置一個(gè)自定義的Shim修復(fù),選擇QHSafeMain.exe。
選擇”RedirectEXE”并且設(shè)置命令行參數(shù), 這里我想設(shè)置重定向到IE,并打開騰迅的主頁。所以命令行參數(shù)我填上 ”c:program files (x86)Internet Exploreriexplore.exe www.qq.com”。
保存,并且安裝以后,雙擊右下角托盤里的360圖標(biāo),360安全中心沒有打開,取而代之的是彈出了騰迅的網(wǎng)站。
當(dāng)然,這種攻擊方法也有2個(gè)弱點(diǎn)
1.攻擊者需要目標(biāo)主機(jī)的管理員權(quán)限來安裝自定義Shim。
2.Shim只工作于用戶模式,因此只能用于設(shè)置用戶模式的程序。該攻擊方式對內(nèi)核模塊無效。
利用shim 緩存進(jìn)行取證
每次執(zhí)行應(yīng)用程序,系統(tǒng)都要根據(jù)Shim數(shù)據(jù)庫來檢查該應(yīng)用程序是否需要被Shim。而Shim數(shù)據(jù)庫里有5000+記錄,每次都比對會(huì)使效率變得很低。所以實(shí)際上windows使用了Shim緩存來提高效率。Shim緩存使用了LRU(Leastfrequently used 最近最少使用)淘汰算法,因此最近執(zhí)行過的程序會(huì)出現(xiàn)在Shim緩存里, 下一次運(yùn)行該程序的時(shí)候就不需要比對Shim數(shù)據(jù)庫。避免了頻繁比對從而提高了效率。Win7的Shim緩存可以跟蹤應(yīng)用程序的最近修改時(shí)間,文件完整路徑和執(zhí)行標(biāo)志(后面會(huì)介紹什么是執(zhí)行標(biāo)志)。該緩存放在內(nèi)存中,所以我們可以用 Volatility的shimcachemem插件來取出信息。
如下圖所示。
安全分析人員在病毒取證的時(shí)候往往需要知道最近在該系統(tǒng)上執(zhí)行過哪些程序。這個(gè)時(shí)候用volatity查看Shim 緩存就可以給我們足夠的信息:Shim緩存里的那些程序就是最近執(zhí)行過的。不過這里還有一個(gè)坑。在某些情況下,預(yù)覽文件夾的時(shí)候explore會(huì)把該文件夾里沒有運(yùn)行過的程序也加到Shim緩存里。不過在這種情況下,該緩存記錄的執(zhí)行標(biāo)志是False,而那些實(shí)際運(yùn)行過的程序執(zhí)行標(biāo)志為True。比如上圖的例子里,Svchost.exe是運(yùn)行過的,而audiodg.exe并沒有真正運(yùn)行過。
由于內(nèi)存信息是易失數(shù)據(jù),很多時(shí)候安全分析人員可能無法得到完整的內(nèi)存dump。在這個(gè)時(shí)候我們可以查看注冊表里的Shim緩存影像。Win7在關(guān)閉或重啟的時(shí)候會(huì)把Shim緩存序列化到注冊表的以下位置。
SYSTEMCurrentControlSetControlSessionManagerAppCompatCacheAppCompatCache
該注冊表鍵的記錄長度是固定的,為1024。我們可以用ShimCacheParser.py 來讀取該信息。值得注意的是由于windows只有在關(guān)閉或重啟的時(shí)候才會(huì)序列化Shim緩存,所以此處是上一次windows運(yùn)行時(shí)的Shim緩存。
這里我模擬一個(gè)被感染用戶,該用戶從郵箱下載并運(yùn)行了一段惡意javascript腳本。 這個(gè)腳本會(huì)下載一個(gè)PE文件,存于臨時(shí)目錄下,然后運(yùn)行之。重啟后,用ShimCacheParser.py ,結(jié)果如下圖。
根據(jù)LFU算法,最近運(yùn)行的記錄排在前面。可以看到Wscript.exe先運(yùn)行,Wscript.exe是用來解釋執(zhí)行javascript的。然后看到臨時(shí)目錄下的te0Iogn3cxZHWOM.exe運(yùn)行了。注意到該程序的最近修改時(shí)間(Last modified time)為16年8月11日09點(diǎn)35分48秒,就是我點(diǎn)擊惡意javascript的時(shí)間,說明這個(gè)exe文件是我點(diǎn)擊javascript的時(shí)候新創(chuàng)建的。結(jié)合文件路徑信息,取證人員可以很容易的發(fā)現(xiàn)問題的源頭。
參考文獻(xiàn)
[1]. windows 的 shim engine分析 http://blog.csdn.net/celestialwy/article/details/707148
[2]. Windows 8的用戶模式Shim Engine小探及利用 http://bbs.pediy.com/showthread.php?t=175483
[3]. Fireeye: Shim Shady, https://www.fireeye.com/blog/threat-research/2015/10/shim_shady_live_inv/shim-shady-part-2.html
[4]. Malicious Application Compatibility Shims, Blackhat 2015
*本文原創(chuàng)作者:nickchang,本文屬FreeBuf原創(chuàng)獎(jiǎng)勵(lì)計(jì)劃,未經(jīng)許可禁止轉(zhuǎn)載