作者:
路人甲
·
2016/01/12 10:41
0x00 背景
[email protected]JavaScript BackDoor中提到了利用rundll32.exe執行一段JavaScript程式碼即可反彈一個Http Shell,這裡將之前看到的對其原理進行分析的文章翻譯和大家分享。
links: http://thisissecurity.net/2014/08/20/poweliks-command-line-confusion/
最近,hFireF0X在逆向工程論壇kernelmode.info上發表了對Win32/Poweeliks惡意軟體詳細調查的文章。這個惡意軟體的特別之處就是它存在於window登錄檔中並且使用rundll32.exe來執行JavaScript程式碼。
我發現很有趣的是我顯然不是唯一一個發現可以透過rundll32來執行一些JavaScript程式碼的人。
當我們第一次發現命令列執行JavaScript,我們很好奇它是如何工作的。
在接下來的文章中,我們會分析JavaScript程式碼時如何執以及為什麼會在呼叫這樣簡單的命令列程式碼時執行:
#!bash
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";alert(‘foo’);
0x01 Rundll32介紹
關於rundll32.dll的使用在MSDN上有專門的文件;它往往被用來呼叫一個DLL檔案的輸出函式,可以透過以下的命令來實現:
#!bash
RUNDLL32.EXE <dllname>,<entrypoint> <optional arguments>
entrypoint就是輸出函式;它的函式原型應該是如下所示:
#!cpp
void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
引數lpszCmdLine是由rundll32.exe命令語句中的<optional arguments>
值確定的。
我們會嘗試指出rundll32.exe是如何能夠呼叫被mshtml.dll輸出的函式RunHTMLApplication,以及“Javascript”字首是如何被用來執行實際的JavaScript程式碼的。
0x02 Rundll32.exe分析
a.引數
rundll32.exe做的第一件事就是使用內建的ParseCommand命令來對命令進行解析。這個函式會查詢一個逗號(‘,’,0x2c)來定位dll的名稱和一個空格(‘ ’,0x20)來定位入口點名稱
當使用我們的樣本命令時,ParseCommand會返回javascript:"\..\mshtml
作為DLL名稱,返回RunHTMLApplication
作為入口點。
0x03 Dll loader
rundll32.exe會嘗試幾種方法來從最初的“JavaScript:"\..\mshtml
”載入實際的DLL。
第一次測試使用了函式GetFileAttributes("javascript:"\..\mshtml")
。這個函式最終會接近C:\Windows\system32\mshtml
。如果這個檔案沒有被發現,那麼這個函式就會返回-1。
接下來SearchPath
會被呼叫來確定DLL的名稱。這個函式會讀取登錄檔鍵值HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SafeProcessSearchMode
。微軟對於這個鍵值的定義是:
當這個REG_DWORD型別的登錄檔鍵值被設為1,SearchPath會首先搜尋系統路徑中指定的資料夾,然後會搜尋當前工作的資料夾。當這個登錄檔鍵值被設為0時,電腦首先會搜尋當前工作的資料夾,然後再去搜尋系統路徑中指定的資料夾。系統對於這個登錄檔鍵的預設值是0。
在預設情況下,這個登錄檔鍵值是不存在的(在win xp、7、8下),所以SearchPath
會優先嚐試在rundll32.dll的當前目錄中載入檔案mshtml,其次才會嘗試在系統路徑中進行定位。
如果所有的嘗試都失敗了,那麼rundll32.exe就會進行下一步。GetFileAttribute
將再次被呼叫來給模組查詢manifest檔案:javascript:"\..\mshtml.manifest
。
若所有的之前的步驟都失敗了,rundll32.exe最終會呼叫Loadlibrary("javascript:"\..\mshtml")
。
LoadLibrary
只是位於ntdll.dll中的一個對LdrLoadDLL的簡單封裝。在內部,LdrLoadDll會新增預設的擴充套件dll並且把結果字串(javascript:”\..\mshtml.dll
)作為路徑來解析。“..
”代表再向上一層資料夾:它就解析成了mshtml.dll
。
當mshtml.dll
已經被確定了,LdrLoadDll就可以載入系統目錄中的lib庫了。
rundll32.exe接下來會使用之前提取的入口點名稱RunHTMLApplication
呼叫GetProcAddress
。
這個時候我們可以發現,javascript:
字首看起來毫無用處:LoadLibrary("foobar:\"\..\mshtml")
工作的很好。所以,為什麼要加這麼一個字首呢?
0x04 協議處理
一旦入口地址已經被解析出來,rundll32.dll會呼叫函式mshtml.dll!RunHTMLApplication
。
即使沒有被記錄,實際的RunHTMLApplication也能從c:\windows\system32\mshta.exe
的呼叫中推斷出來(這個應用專門來啟動一個.hta檔案)。
#!cpp
HRESULT RunHTMLApplication(
HINSTANCE hinst,
HINSTANCE hPrevInst,
LPSTR szCmdLine,
int nCmdShow
);
這和期望的rundll32.exe的入口點地址很相似:
#!cpp
void CALLBACK EntryPoint(
HWND hwnd,
HINSTANCE hinst,
LPSTR lpszCmdLine,
int nCmdShow
);
RunHTMLApplication接受一個視窗的控制程式碼而不是一個模組的控制程式碼作為第一個引數。這個引數會在mshml登記一個視窗類或者為一個類建立視窗時被使用。傳遞一個同實際的例項並不相一致的值並不會給user32帶來很大影響。
第二個引數完全沒有被使用,所以這個不匹配並不重要。
最後一個引數,nCmdShow
,被RunHTMLApplication
函式用來展示代管這個HTML應用的主機視窗。rundll32經常使用值SW_SHOWDEFAULT
來呼叫入口點函式來指示任何可能開啟的視窗使用視窗預設配置。
在我們的例子中,可能更讓人感興趣的引數是 lpszCmdLine (";alert('foo'))
。
這顯然會導致問題,因為這並不是一個有效的JavaScript語句(注意在語句末尾丟掉的雙引號)。但是它仍然有效,因為RunHTMLApplication
忽略給定的引數,並且更傾向於從windows API GetCommandLine
中重新請求原始的命令(封裝在GetCmdKLine
函式的一個呼叫中)。
完整的命令包含了可執行檔案和引數的名稱:GetCmdLine
透過整理可執行規範來提取引數。
在這之後,RunHTMLApplication
會呼叫CreateURLMonitor
:
這也是需要字串“javascript”的地方。
CreateURLMonitor
解析命令列來提取char":"(0x3A)之前的字串:“javascript”。
CreateUrlMoniker
會爬取登錄檔鍵值HKCR\SOFTWARE\Classes\PROTOCOLS\Handler\
。這些鍵值和一個協議集以及它們的CLSID有關。
CreateUrlMoniker
會發現一個合適的協議處理器來對Javascript的協議進行處理(HKCR\SOFTWARE\Classes\PROTOCOLS\Handler\javascript
):
CLSID{3050F3B2-98B5-11CF-BB82-00AA00BDCE0B}
符合微軟“Microsoft HTML Javascript Pluggable Protocol”規範。
這也是為什麼字串“javascript”必須在引數的開始部分的原因。
相同的機制在人們在IE的導航欄輸入javascript:alert('alert')時也會起作用。
位於“:”分隔符之後的字串會被JavaScript URL moniker解釋成JavaScript指令:
#!js
"\..\mshtml,RunHTMLApplication ";alert(‘foo’);
這是一個帶有字串"\..\mshtml,RunHTMLApplication "
和函式(alert)
的無效JavaScript語句(因為雙引號會跳過所有之前的步驟!)。
最終RunHTMLApplication會呼叫CHTMLApp::Run
,這條JavaScript語句也會被執行:
0x05 安全影響
從安全的角度來看,透過rundll32來執行JavaScript就像執行一個HTML應用。
換句話說,我們可以使用IE的全部權利。當區域安全被關閉,允許跨域指令碼訪問,我們就可以擁有讀寫客戶端機器檔案和登錄檔的權力。
透過這個技巧,JavaScript可以在IE外部被執行,並且指令碼沒有任何安全概念的約束,比如保護模式\沙盒。
0x06 結論
按照我們的理解,這個技術語序繞過一些信任內建的rundll32的行為的安全產品。
0x07 本文相關
- https://twitter.com/hFireF0X
- http://www.kernelmode.info/forum/viewtopic.php?f=16&t=3377
- http://support.microsoft.com/kb/164787/en
- http://msdn.microsoft.com/enus/library/windows/desktop/aa365527%28v=vs.85%29.aspx
- https://thisiscybersec.files.wordpress.com/2014/08/capture-d_c3a9cran-2014-08-20-c3a0-16-16-36.png
- https://thisiscybersec.files.wordpress.com/2014/08/capture-d_c3a9cran-2014-08-20-c3a0-16-16-36.png
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!