IE安全系列之——RES Protocol
RES是IE支援的特殊Protocol。它用於從二進位制檔案中讀取資源資訊並展示在網頁中。由於現在RES已經被微軟大老爺削弱成狗,所以本來準備拆兩篇的文章乾脆就合在一篇寫了。文中除非有特殊提示,否則都以IE11為準。
0x00 Res Protocol ABC
res Protocol用於從一個檔案裡面提取指定資源。語法為:res://sFile[/sType]/sID
各Token含義:
- sfile:百分號編碼。包含資源的檔案路徑。
- sType:可選的,字串或者數字,表明資源型別。可以是任意億一個FindResource可以識別的預定義型別。如果指定了數字型別的值,則需要跟隨一個#字元。未指定時預設RT_HTML或RT_FILE。
- sID:字元或數字型別。資源識別符號。如果指定了數字值,需要跟隨一個#。
具體的可見參考資料1,不翻譯了……
0x01 新視窗中Res Protocol的載入
在新視窗開啟res protocol的時候,res Protocol的dll會被載入記憶體。Res protocol載入的dll使用LoadLibraryExW讀入,一些常見的res protocol,例如res://ieframe.dll/
的讀入時並沒有使用完整的路徑。雖然可以考慮DLL劫持問題,但program files和system32均為administrator許可權,所以還是不要想了……
在新視窗載入res protocol URL時,最終解析、載入資源並繫結的工作由CResProtocol類的CResProtocol::DoParseAndBind完成。
#!bash
0:009> kvn 1
# ChildEBP RetAddr Args to Child
00 072fa464 664b2ad5 0f806814 00000000 00000060 KERNEL32!LoadLibraryExWStub (FPO: [Non-Fpo])
0:009> dds esp
072fa468 664b2ad5 MSHTML!CResProtocol::DoParseAndBind+0x103
072fa46c 0f806814
0:009> du 0f806814
0f806814 "ieframe.dll"
程式碼1:CResProtocol::DoParseAndBind正在使用LoadLibraryEx載入ieframe.dll
DoParseAndBind處理ResProtocol時的具體做法:
a、Crack Res URL。
Res URL格式如我們之前所述。另外,res protocol的第一個path部分不允許有“/”。因為微軟在crack URL時hardcode直接wcschr搜尋的L'/'。解析字串時遇到的第一個“/”(除了res://的//)後面只能是restype,或者id。
b、傳入的res protocol 路徑長度大於MAX_PATH時,返回E_FAIL,所以Fuzz這裡意義也不是多大了。Win95+IE4.0時候這裡有漏洞,這個判斷也是自那個漏洞之後補上的。
c、LoadLibraryEx載入資源DLL,Flag為DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE。所以也不要考慮重複利用載入的DLL了,因為DLL被對映到了只讀記憶體中。並不會被執行。
#!bash
0:009> !address 67370000
Usage: Image
Base Address: 67370000
End Address: 67371000
Region Size: 00001000
State: 00001000 MEM_COMMIT
Protect: 00000002 PAGE_READONLY
Type: 01000000 MEM_IMAGE
Allocation Base: 67370000
Allocation Protect: 00000080 PAGE_EXECUTE_WRITECOPY
Image Path: F:\WINDOWS\SYSTEM32\IEFRAME.dll
Module Name: IEFRAME
Loaded Image Name: F:\WINDOWS\SYSTEM32\IEFRAME.dll
Mapped Image Name:
More info: lmv m IEFRAME
More info: !lmi IEFRAME
More info: ln 0x67370000
More info: !dh 0x67370000
程式碼2:分配在只讀頁上的ieframe.dll
0x02 曾經的可行方法:new Image判斷res
確實遲了一些,不過為了彌補,我接下來會分析為什麼用不了了
曾經在Angler Exploit Kit中,攻擊者用Res Protocol玩出了一堆花樣。使用如下程式碼,可以判斷本地檔案是否存在。
#!js
function my_onError(){alert("file not exists!!");}
function Check(s) {
x = new Image();
x.onerror=my_onError;
x.src = s;
document.body.appendChild(x);
return 0;
}
Check("res://f:\\node\\asoehook2.dll/#2/#102")
程式碼3:使用Res Protocol檢查本地檔案
(不過在最新的IE11中,這個判斷並不能在http/https/ftp下進行,也不能在任何網路相關的protocol開啟的about:blank或者iframe 的about:blank中進行。下節說)
為啥Image可以做到這個呢?讓我們仔細看一下。猜也能猜得到,new Image事實上建立了一個CImgElement。
#!bash
Breakpoint 10 hit
eax=11fe3bc0 ebx=662016f0 ecx=11fe3bc0 edx=000001bc esi=65eb2270 edi=072fa3c8
eip=66201739 esp=072fa3a4 ebp=072fa3b4 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200206
MSHTML!CImgElement::CImgElement:
66201739 8bff mov edi,edi
0:009> kvn
# ChildEBP RetAddr Args to Child
00 072fa3a0 66201718 0000003d 06a08000 662016f0 MSHTML!CImgElement::CImgElement (FPO: [Non-Fpo])
01 072fa3b4 6625110b 072fa440 06a08000 072fa3ec MSHTML!CImgElement::CreateElement+0x28 (FPO: [Non-Fpo])
02 072fa3f0 663aa61a 06a08000 11fe8a00 00000000 MSHTML!CreateElement+0xab (FPO: [Non-Fpo])
03 072fa500 664c4bb9 0000003d 072fa524 00000000 MSHTML!CMarkup::CreateElement+0xee (FPO: [Non-Fpo])
04 072fa548 664c49a0 06a7ee10 06920000 0bb24420 MSHTML!CImageElementFactory::create+0x49 (FPO: [Non-Fpo])
05 072fa5b8 664c48e4 00000001 11fe8a00 072fa5d8 MSHTML!CImgElement::Var_create+0x89 (FPO: [Non-Fpo])
06 072fa5e0 552f3b7e 189114e0 01000001 163c3d20 MSHTML!CFastDOM::CHTMLImageElement::DefaultEntryPoint+0x44 (FPO: [Non-Fpo])
07 072fa648 552f8f53 189114e0 01000001 163c3d20 jscript9!Js::JavascriptExternalFunction::ExternalFunctionThunk+0x18e (FPO: [Non-Fpo])
程式碼4: CImgElement的建立
然後,為Image指定src後,整個流程如下:
#!bash
CImgElement::OnPropertyChange ---> CImgHelper::SetImgSrc ---> CImgHelper::FetchAndSetImgCtx
在早期的IE中,這一套流程下來並沒有認為res是不讓載入的,所以能夠觸發onerror事件。但是,使用file:///的src不可判斷本地檔案是否存在。這就使得res判斷成為比較獨特的存在。
就像http下並不能透過file protocol或者UNC訪問本地檔案(例如上述程式碼Check("file:///f:/yy.jpg")不會丟擲onerror事件),而如果在非http/https/ftp網站開啟的about:blank中還是可以使用的。
上述描述在不過在最新的IE中無效了,那是因為微軟的LMZL策略。
0x03 Local Machine Zone Lockdown
我也就不貼到最後的參考連線裡面了,直接貼這兒好了:
https://technet.microsoft.com/en-us/library/cc782928(v=ws.10).aspx
LMZL是微軟搞出來的一個安全策略,簡單的說就是阻止網際網路內容訪問本地內容,照理來說,在Windows XP SP2的時候就已經有這個功能了,但是直到多年以後,我在IE8上實驗,還是能用RES訪問本地資源。
微軟的行蹤一向很謎。這個舉動也相當的謎。RES Protocol的當作本地檔案處理的邏輯為什麼沒加?觀察IE8和IE11處理相同本地資料的程式碼可以得出一個基礎結論——應該是忘了。
0x04 IE11下的RES Protocol(IMG src中)為什麼失效了?
首先,在IE中我輸入了下面的程式碼。不出意外地,document.body.appendChild(iii)之後,元素新增成功,但是圖片沒顯示出來,同時,onerror也沒有觸發。我開始以為是因為f:\asoehook2.dll存在的緣故。結果換了個隨便打的地址加上Res Protocol,還是沒有觸發onerror。
同比在IE8下的Res Protocol,則既能顯示圖片,又能觸發onerror。
於在IE11下,Img SRC指定為RES Protocol時,Img顯示的是一個透明的方塊,所以先懷疑這些點:下載是否出問題了?在跟蹤下載棧之後,發現下載和IE8的幾乎一模一樣。
#!bash
ChildEBP RetAddr
039e85a4 764c14a2 urlmon!CBSCHolder::OnProgress(
unsigned long ulProgress = 0x338,
unsigned long ulProgressMax = 0x338,
unsigned long ulStatusCode = 4,
wchar_t * szStatusText = 0x0bbc2ce8 "res://f:\asoehook2.dll/#2/#102")+0x50 [d:\blue\inetcore\urlmon\mon\mpxbsc.cxx @ 807]
039e85dc 764c46e1 urlmon!CBinding::OnTransNotification(
tagBINDSTATUS NotMsg = <Value unavailable error>,
unsigned long dwCurrentSize = 0x338,
unsigned long dwTotalSize = 0x338,
wchar_t * pwzStr = 0x00000000 "",
HRESULT hrINet = 0x00000000)+0x35b [d:\blue\inetcore\urlmon\trans\cbinding.cxx @ 2676]
039e8610 764c4458 urlmon!CBinding::ReportData(
unsigned long grfBSCF = 0xd,
unsigned long ulProgress = 0x338,
unsigned long ulProgressMax = 0x338)+0xa1 [d:\blue\inetcore\urlmon\trans\cbinding.cxx @ 5451]
039e8638 764c43ec urlmon!COInetProt::ReportData(
unsigned long grfBSCF = 0xd,
unsigned long ulProgress = 0x338,
unsigned long ulProgressMax = 0x338)+0x54 [d:\blue\inetcore\urlmon\trans\prothndl.cxx @ 1863]
039e8674 764c4303 urlmon!CTransaction::DispatchReport(
tagBINDSTATUS NotMsg = BINDSTATUS_ENDDOWNLOADDATA (0n6),
unsigned long grfBSCF = 0xd,
unsigned long dwCurrentSize = 0x338,
unsigned long dwTotalSize = 0x338,
wchar_t * pwzStr = 0x00000000 "",
HRESULT hresult = 0x00000000)+0x19e [d:\blue\inetcore\urlmon\trans\transact.cxx @ 3153]
(Inline) -------- urlmon!CTransaction::DispatchPacket+0x23 [d:\blue\inetcore\urlmon\trans\transact.cxx @ 3278]
(Inline) -------- urlmon!CTransaction::OnINetCallback+0x116 [d:\blue\inetcore\urlmon\trans\transact.cxx @ 3356]
二者都成功地獲取到了所需的資源,看來這裡可以先排除。
然後,讓我們再追蹤一下事件。給MSHTML!CImgHelper::Fire_onerror
下斷點,為了確認下我下的對不對,我修改了iii.src=“aa”
,這時,Fire_onerror成功觸發。
圖:給iii的src傳入非res Protocol時,onerror事件就能成功觸發。
而在IE11下指定Res Protocol時,Fire_onerror卻始終無法斷到。這可以證明一個猜想:如果IE禁止RES Protocol用在IMG中,那麼這個禁止邏輯可能不是在事件裡面去處理的。
對比在IE8下,即使使用Res Protocol,Fire_onerror仍然可以斷到:
目標放在Fire_onerror的前後兩層。上一層OnDwnChan看起來並不是多相關,再向上一層,CImgHelper::SetImgCtx裡首先有了一些不一樣的地方。
#!bash
0:008>
eax=00000000 ebx=071b2930 ecx=039e9cb0 edx=00000000 esi=00000000 edi=00000000
eip=639c17ce esp=039e9c9c ebp=039e9cd0 iopl=0 nv up ei pl nz ac pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000216
MSHTML!CImgHelper::SetImgCtx+0x11:
639c17ce e868feffff call MSHTML!CImgHelper::CScriptCalloutProtection::CScriptCalloutProtection (639c163b)
0:008>
eax=039e9cb0 ebx=071b2930 ecx=071b2934 edx=071b2930 esi=00000000 edi=00000000
eip=639c17d3 esp=039e9ca0 ebp=039e9cd0 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
MSHTML!CImgHelper::SetImgCtx+0x16:
639c17d3 33f6 xor esi,esi
0:008>
eax=039e9cb0 ebx=071b2930 ecx=071b2934 edx=071b2930 esi=00000000 edi=00000000
eip=639c17d5 esp=039e9ca0 ebp=039e9cd0 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
MSHTML!CImgHelper::SetImgCtx+0x18:
639c17d5 397314 cmp dword ptr [ebx+14h],esi ds:002b:071b2944=031a8e00
0:008>
eax=039e9cb0 ebx=071b2930 ecx=071b2934 edx=071b2930 esi=00000000 edi=00000000
eip=639c17d8 esp=039e9ca0 ebp=039e9cd0 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
MSHTML!CImgHelper::SetImgCtx+0x1b:
639c17d8 0f857b090000 jne MSHTML!CImgHelper::SetImgCtx+0x217 (639c2159) [br=1]
0:008>
eax=039e9cb0 ebx=071b2930 ecx=071b2934 edx=071b2930 esi=00000000 edi=00000000
eip=639c2159 esp=039e9ca0 ebp=039e9cd0 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
MSHTML!CImgHelper::SetImgCtx+0x217:
639c2159 397344 cmp dword ptr [ebx+44h],esi ds:002b:071b2974=00000000
CImgHelper::CScriptCalloutProtection::CScriptCalloutProtection在IE8中並不存在,不過很不幸,CImgHelper::CScriptCalloutProtection::CScriptCalloutProtection 並不是我們要找的目標。
但是目標也不遙遠了,繼續往下看一點程式碼,就可以發現IE11在設定IMG元素的上下文時,做了一個CMarkup::CheckForLMZLLoad(v8, 1);的判斷。
LMZL還有印象不?就是上一節說的Local Machine Zone Lockdown,名字看起來有點中二病,微軟具體讓這個東西覆蓋了多少程式碼量也是個謎。
記住第二個引數1。
跟入CheckForLMZLLoad之後,我們看到了if(a4 == 1){v8 = &FCK::FEATURE_BLOCK_LMZ_IMG;}
看起來很明顯了,微軟在IMG設定上下文的時候,限制了Local Machine Zone的圖片資源載入。
設定上下文?差點忘了,獲取圖片和設定上下文的函式就是這個:CImgHelper::FetchandSetImgCtx。
既然上下文設定失敗,那麼事件繫結和觸發也必然沒著落,更慘的是圖片也不讓顯示,RES Protocol判斷本地檔案是否存在的功能自此宣告滅亡。
0x05 網路診斷
也許你最近一年根本就沒有用過IE,不要緊,IE裡面有個無法顯示此頁還是一直在那裡的。當訪問一個無法處理的網站時,IE會展示res://ieframe.dll/dnserror.htm#http://xxx
,在這個頁面上有一個“修復連線問題”。
點選一下這個東西,就會蹦出來一個網路修復程式,比較神奇。那麼這裡會不會也有安全問題呢,這個修復程式IE是怎麼定位到的?
跟蹤一下,可以發現發現IE實際呼叫了ndfapi的LaunchMSDT函式,該函式啟動system32下的msdt.exe。呼叫時使用的是完整路徑,所以無需考慮exe劫持之類的問題。
#!bash
0:009> kvn
# ChildEBP RetAddr Args to Child
00 072fa2cc 54f3c7ec 08085978 004bdf80 00000000 KERNEL32!CreateProcessWStub (FPO: [Non-Fpo])
01 072fa5b0 54f3cb1c 07fff5a8 fedbc665 54f32b80 ndfapi!LaunchMSDT+0x201 (FPO: [Non-Fpo])
02 072fa688 54f3c5d8 00000001 54f30000 072fa6bc ndfapi!CNetDiagClient::LaunchScriptedDiagnostics+0x143 (FPO: [Non-Fpo])
03 072fa6a0 54f377a2 00000001 072fa6dc 67654b7d ndfapi!NdfExecuteDiagnosisEx+0x53 (FPO: [Non-Fpo])
04 072fa6ac 67654b7d 069d37e0 00040c94 00000000 ndfapi!NdfExecuteDiagnosis+0x12 (FPO: [Non-Fpo])
05 072fa6dc 675ee143 072fa72c 07b3f7cc 07ffec54 IEFRAME!DiagnoseConnectionProblems+0xa9 (FPO: [Non-Fpo])
06 072fa9bc 7732b0ff 07ff4ff8 072faa0c 07ffec54 IEFRAME!CShellUIHelper::DiagnoseConnection+0x2d3 (FPO: [Non-Fpo])
07 072fa9d4 7730c807 07ff4ff8 00000070 00000004 OLEAUT32!DispCallFunc+0x16f
看起來一切都是那麼嚴謹,不過誰知道呢,IE總是在最意想不到的地方出各種小問題。
0x06 參考資料
相關文章
- IE安全系列之——RES Protocol與列印預覽(II)2020-08-19Protocol
- IE安全系列之——IE中的ActiveX(II)2020-08-19
- IE安全系列之——昨日黃花:IE中的ActiveX(I)2020-08-19
- IE安全系列:IE的自我介紹 (I)2020-08-19
- IE安全系列:IE的自我介紹 (II)2020-08-19
- netty系列之:在netty中使用proxy protocol2022-11-23NettyProtocol
- IE安全系列之:中流砥柱(I)—Jscript 5處理淺析2020-08-19JS
- IE安全系列之:中流砥柱(II)—Jscript 9處理淺析2020-08-19JS
- IE安全系列:指令碼先鋒(II)2020-08-19指令碼
- IE安全系列:指令碼先鋒(I)2020-08-19指令碼
- top命令之RES,DATA2018-07-28
- Protocol Buffers 系列 (1) - 什麼是Protocol Buffers?2022-05-09Protocol
- IE安全系列:指令碼先鋒(III)--網馬中的Shellcode2020-08-19指令碼
- IE安全系列:指令碼先鋒(IV)—網馬中的Shellcode2020-08-19指令碼
- return isPlainObject(res) || Array.isArray(res) ? observer(res, cb) : res; 這個的執行順序是什麼2024-07-06AIObjectServer
- 認識 Express 的 res.send() 和 res.end()2022-01-21Express
- IE沙箱拖拽安全策略解析2020-08-19
- 理解 virt、res、shr 之間的關係(linux 系統篇)2022-09-23Linux
- 理解virt、res、shr之間的關係(linux系統篇)2022-09-14Linux
- dart系列之:安全看我,dart中的安全特性null safety2021-12-22DartNull
- tryhackme-Res(資源)2024-03-08
- Magicodes.IE之花式匯出2020-09-28
- Swift - 使用 Protocol 避免框架之間迴圈引用2019-04-19SwiftProtocol框架
- 網路協議之:memcached text protocol詳解2022-06-03協議Protocol
- 網路協議之:memcached binary protocol詳解2022-06-13協議Protocol
- 多執行緒系列之 執行緒安全2019-01-09執行緒
- 安全系列之:跨域資源共享CORS2021-09-13跨域CORS
- protocol buffer2024-05-10Protocol
- No appropriate protocol2021-09-09APPProtocol
- Android資源res之向量圖完全指南(加SVG-path命令分析)2018-12-08AndroidSVG
- VuePress 部落格之 SEO 優化(四) Open Graph protocol2022-03-12Vue優化Protocol
- Elasticsearch和亞馬遜之間的衝突 - protocol2021-01-22Elasticsearch亞馬遜Protocol
- createContext(req, res)幹了什麼?2019-03-23Context
- location.protocol2018-10-26Protocol
- Jaeger TChannel ——protocol2018-07-16Protocol
- 聊聊SWIM Protocol2019-05-02SWIMProtocol
- 網路協議之:haproxy的Proxy Protocol代理協議2022-06-01協議Protocol
- GaussDB技術解讀系列:高安全之密態等值2024-10-28