<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    原文地址:http://drops.wooyun.org/papers/7521

                    IX.1 ActiveX的歷史和簡單的介紹


                    說到ActiveX,則不得不提到COM(組件對象模型)。COM出現時要解決的問題是,“能否把軟件做到和硬件一樣”,硬件的理想情況是比如有人規定了USB的規范,(Server)提供一個USB接口之后,(Client)只要正確實現了USB就可以讓二者相聯系,擴展出更多的功能(USB鍵鼠,U盤,攝像頭,等等)。這之中Server(集線器)并不需要知道另一頭Client(鍵盤?鼠標?)具體做啥的,只是知道我(Server)提供給你(Client)一個符合USB規范的接口,你(Client)弄上個東西連接成功就能用,至于你(Client)如何實現就不是我(Server)的事情了。

                    最初COM的出現也是為了解決類似的問題,例如我在IE里面如何打開一個WORD文檔?針對它的解決方案稱為OLE(對象連接與嵌入)。1993年微軟發布了OLE2,在這(ole32.dll)中提供的API也被日后認為是COM API。有了這些支持之后,微軟用它創造了OLE控件,并最終發展成為了在IE中常見的ActiveX控件。如果你用過VB的話,在VB里就能發現大量此類控件的身影,如內嵌的Microsoft Viso等等。

                    enter image description here

                    每個ActiveX控件都由一個GUID(全局唯一標識符)來標識自己,GUID和UUID(全球唯一標識符)差不多,只不過后者是OSF(開源軟件基金會)維護,前者是微軟自己的實現。

                    GUID是一個128位的數字,理論上是極大概率時間空間唯一的(隨機數生成的空間有2122的大小,按照類似生日問題的算法,如果正確生成的話,和其他人生成的偶然重復概率為1/261)。

                    GUID算法包括1490年開始到現在的分鐘數(保證時間唯一性),一個偽隨機數,和MAC地址(保證空間唯一性,沒有網卡的話會使用另一個隨機常量),API CoCreateGuid可以生成GUID。GUID的一般形式類似于{AFEE063C-05BA-4248-A26E-168477F49734}這樣。

                    在IE里或者WSF或者HTA等支持OBJECT標簽的地方,可以通過它來加載ActiveX,OBJECT標簽的具體用法請見參考資料(1)。

                    enter image description here

                    圖:iDefense ComRaider ActiveX Fuzzer生成的WSF測試腳本使用了Object標簽來載入被測ActiveX控件

                    IX.2 IE中的ActiveX


                    默認情況下,要在IE瀏覽器中運行ActiveX插件,ActiveX插件必須同時擁有Safe For Scripting/Safe For Init標記才可以運行。在IE發現HTML網頁中有ActiveX控件時,IE會依次檢查如下動作來確定控件是否可以安全加載和運用于代碼中。

                    (1) IE會先檢查ActiveX控件是否設置了killbit,如果設置了Killbit,IE將不會加載這個控件;

                    (2)IE會確定這個控件是否派生了IObjectSafety,如果有的話,IE會通過這個接口檢查是否有設置Safe for Scripting/Safe For Init,如果沒有派生IObjectSafety,IE會在注冊表檢查{7DD95802-9882-11CF-9FA9-00AA006C42C4} (Safe for Initialization){7DD95801-9882-11CF-9FA9-00AA006C42C4}(Safe For Scripting).兩項。

                    這里的具體內容在之前的一篇文章http://drops.wooyun.org/papers/5673有介紹,所以不重復敘述了。為了后續實驗方便,我們可以使用環境自己先弄個ActiveX,這里以Microsoft Visual C++ 2010為例創建一個ActiveX控件。

                    首先,如圖創建一個新工程,簡單起見,在后一個窗口直接完成即可。

                    enter image description here

                    生成的對外接口定義文件(XXX.idl)文件是和該控件信息有關的一個重要文件,許多信息都可以在此看到。例如“類信息”中uuid就是ActiveX控件待會兒在IE中加載時所要用到的Classid。

                    enter image description here

                    由于我們只是演示,因此我們簡單的添加一個函數foo(): 在類視圖的接口處點擊右鍵,選擇添加->方法

                    enter image description here

                    然后,添加一個void foo(),填寫之后點擊完成:

                    enter image description here

                    這時VS會在多個地方添加這個函數的信息,不過簡單起見,回到剛才的idl文件中我們就可以看到添加了個新函數

                    enter image description here

                    在MSVC中直接F12過去:

                    enter image description here

                    這個位置就是新加函數的位置,為了方便演示,我們在里面隨便彈一個對話框好了:

                    ::MessageBox(0, L"hello wooyun", L"blast", MB_OK);
                    

                    然后,我們右鍵選擇工程,編譯一個Release版的ocx控件:

                    enter image description here

                    之后,使用regsvr32 testActivex.ocx。

                    enter image description here

                    此時,該ActiveX就已經被注冊了,我們創建一個測試用的htm文件吧,

                    <HTML>    
                    <OBJECT ID="test" WIDTH=300 HEIGHT=300 classid="CLSID:2D9835F7-9534-46C2-AE7A-C75098AA6105">  
                    </OBJECT>  
                    </HTML>  
                    

                    CLSID請換成你的idl里面的那個uuid。由于我們的ActiveX控件并未設置Safe For Scripting和Safe For Init,所以在本地域打開時IE做了這個提示,點擊是之后,就可以看到插件運行起來了。

                    enter image description here

                    enter image description here

                    此時,我們也可以測試調用我們加入的foo()函數,在SCRIPT標簽中調用test.foo(),即可調用成功,可見IE中彈出了一個對話框:

                    enter image description here

                    要實現Safe For Scripting、Init,請這么做: 頭文件(例如我的工程是testActivexCtrl.h)中加入#include <objsafe.h>,然后將 DECLARE_INTERFACE_MAP()

                    #!c++
                    BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)   
                    
                    
                        STDMETHOD_(HRESULT,   GetInterfaceSafetyOptions)   (     
                        /*   [in]   */   REFIID   riid,   
                        /*   [out]   */   DWORD   __RPC_FAR   *pdwSupportedOptions,   
                        /*   [out]   */   DWORD   __RPC_FAR   *pdwEnabledOptions   
                        );  
                    
                        STDMETHOD_(HRESULT,   SetInterfaceSafetyOptions)   (     
                            /*   [in]   */   REFIID   riid,   
                            /*   [in]   */   DWORD   dwOptionSetMask,   
                            /*   [in]   */   DWORD   dwEnabledOptions   
                            );  
                    
                    END_INTERFACE_PART(ObjSafe);
                    

                    加入class CtestActiveXCtrl : public COleControl塊中。

                    在對應CPP文件的最后加入下列代碼,記得將CtestActiveXCtrl換成你自己的類名。

                    #!c++
                    BEGIN_INTERFACE_MAP(CtestActiveXCtrl,COleControl) 
                      INTERFACE_PART(CtestActiveXCtrl,IID_IObjectSafety,ObjSafe) 
                    END_INTERFACE_MAP()  
                    
                    ULONG FAR EXPORT CtestActiveXCtrl::XObjSafe::AddRef() 
                    { 
                      METHOD_PROLOGUE(CtestActiveXCtrl,ObjSafe) 
                        return pThis->ExternalAddRef(); 
                    }  
                    
                    ULONG FAR EXPORT CtestActiveXCtrl::XObjSafe::Release() 
                    { 
                      METHOD_PROLOGUE(CtestActiveXCtrl,ObjSafe) 
                        return pThis->ExternalRelease(); 
                    }  
                    
                    HRESULT FAR EXPORT CtestActiveXCtrl::XObjSafe::QueryInterface(REFIID iid,void FAR* FAR* ppvObj) 
                    { 
                      METHOD_PROLOGUE(CtestActiveXCtrl,ObjSafe) 
                        return (HRESULT)pThis->ExternalQueryInterface(&iid,ppvObj); 
                    }  
                    
                    const DWORD dwSupportedBits = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA; 
                    const DWORD dwNotSupportedBits=~dwSupportedBits;  
                    
                    HRESULT STDMETHODCALLTYPE   
                      CtestActiveXCtrl::XObjSafe::GetInterfaceSafetyOptions(   
                      /*[in]*/ REFIID riid, 
                      /*[out]*/ DWORD __RPC_FAR *pdwSupportedOptions, 
                      /*[out]*/ DWORD __RPC_FAR *pdwEnabledOptions) 
                    { 
                      METHOD_PROLOGUE(CtestActiveXCtrl,ObjSafe) 
                        HRESULT retval = ResultFromScode(S_OK); 
                    
                      IUnknown FAR* punkInterface; 
                      retval = pThis->ExternalQueryInterface(&riid, (void **)&punkInterface); 
                      if(retval != E_NOINTERFACE) 
                      { 
                        punkInterface->Release(); 
                      } 
                    
                      *pdwSupportedOptions=*pdwEnabledOptions=dwSupportedBits; 
                      return retval; 
                    }  
                    
                    HRESULT STDMETHODCALLTYPE   
                      CtestActiveXCtrl::XObjSafe::SetInterfaceSafetyOptions(   
                      /*[in]*/ REFIID riid, 
                      /*[in]*/ DWORD dwOptionSetMask, 
                      /*[in]*/ DWORD dwEnabledOptions) 
                    { 
                      METHOD_PROLOGUE(CtestActiveXCtrl, ObjSafe) 
                    
                       IUnknown FAR* punkInterface; 
                      pThis->ExternalQueryInterface(&riid, (void **)&punkInterface); 
                      if(punkInterface)
                      { 
                        punkInterface->Release(); 
                      } 
                      else 
                      { 
                        return ResultFromScode(E_NOINTERFACE); 
                      }  
                    
                      if(dwOptionSetMask & dwNotSupportedBits)  
                      {   
                        return ResultFromScode(E_FAIL); 
                      }  
                    
                      dwEnabledOptions&=dwSupportedBits; 
                      if((dwOptionSetMask&dwEnabledOptions)!=dwOptionSetMask) 
                      { 
                        return ResultFromScode(E_FAIL); 
                      } 
                    
                      return ResultFromScode(S_OK); 
                    }
                    

                    重新編譯,再次打開IE時,這個控件就會直接加載起來而不會再彈出對話框了。

                    IX.3 Windows 10中ActiveX插件變成了什么樣


                    另一個大家比較關注的可能是Windows 10里面的ActiveX情況,有一個好消息是Microsoft Edge已經不支持ActiveX了,不過Windows 10同樣自帶的IE11則依然和Win7、Win8的IE11一樣,繼續支持ActiveX。

                    在Windows 10中讓我們做同樣的事情,

                    enter image description here

                    首先,Win10提供了IE和Edge瀏覽器,選擇使用Edge瀏覽器打開時,頁面中并未加載該ActiveX控件:

                    enter image description here

                    可以看到test對象事實上只是一個CObjectElement而已,它并沒有加載ActiveX控件。使用工具查看Edge的內存也可得出同樣結論——這個OCX并沒加載到內存。

                    enter image description here

                    enter image description here

                    再換用IE打開這個頁面,在Win10自帶的IE11中,我們看到插件正常運行了。

                    enter image description here

                    另外,在原先的IE中,Flash插件也是靠ActiveX的形式活著的。在Edge中應該也考慮到了這個問題,Edge自帶一套Flash,所以用戶不需要額外去網站上下載安裝,這套Flash的形式是什么呢?我們可以簡單看一下:

                    enter image description here

                    首先我們可以看到FLASH的加載代碼依然和之前一樣,采用Object的方式加載:

                    enter image description here

                    不過之前的經歷我們知道Object在Edge中是不能像之前一樣簡單加載ActiveX的,那這里是什么呢?參考進程列表可以發現,Edge在執行到包含有Flash的頁面時,會啟動一個FlashUtil_ActiveX.exe 進程,這個進程名字十分奇怪,在仔細查看Edge的進程模塊后,我們可以發現,Edge其實還是保留著加載ActiveX控件的能力的,只不過控制在一個比較小的范圍內而已:

                    enter image description here

                    enter image description here

                    本章節只是介紹了ActiveX的歷史和一個示例ActiveX的編譯方法,而并沒有介紹有關Activex安全的部分,關于Activex漏洞的挖掘等內容將在后續章節介紹。

                    參考資料


                    (1] http://www.w3school.com.cn/tags/tag_object.asp

                    (2] http://www.ffri.jp/assets/files/monthly_research/MR201503_Windows_10_Technical_Preview_Security_Overview_ENG.pdf

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频