<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

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

            (本文純屬虛構,如有雷同,實屬巧合)

            大名鼎鼎的AspxSpy,罹患間歇性木馬病而被白道追殺。大權在握的系統管理員,冷笑著把這位老兄打入了十八層地獄。拒絕訪問,組件錯誤……連最寶貴的命令執行都要封殺。是可忍孰不可忍!拿上小饅頭,我閉關數月。

            國慶悄然而至,滿街地小姐們穿著爆乳裝,齊P小短裙(學名硬得快)擠來擠去,中國首位本土科學家獲得了諾貝爾獎,我靜靜地呆在家中,把這漫長的歷練一一道來,以饗讀者。

            0x00 詞匯約定


            非專業術語,僅供娛樂:

            Shell:這里指類似于命令提示符的,一個用于運行可執行文件的C#頁面。

            本機代碼:與托管代碼對應。

            0x01 *外殺馬


            和* 外真是有緣,這不,最近又偶遇* 外的服務器,規模約莫二十上下。向來服務器的安全檢測,也有不少無法獲得最高權限的情形,但這次最令人困惑的,是無論如何也無法在Shell中執行命令。管理員,你在挑逗我么?不想讓我知道其中的奧妙,為何又留下了一個漏洞?給管理員戴好可愛的綠帽后,我搜遍系統,終于發現裝神弄鬼的,是一個小小驅動——*外殺馬。

            圖1 *外殺馬

            圖2 IDA中的*外殺馬

            一個名為NotifyRoutine的函數引起了我的興趣。這是一個回調函數,它的偽代碼如下:

            void __stdcall NotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
            {
            // …
              ProcessHandle = ProcessId;
              v66 = ProcessId;
              if ( Create && PsLookupProcessByProcessId(ParentId, &Object) >= 0 )
              {
                v3 = (const char *)PsGetProcessImageFileName(Object);
                if ( !stricmp(v3, "w3wp.exe") || (v4 = (const char *)PsGetProcessImageFileName(Object), !stricmp(v4, "php-cgi.exe")) )
                {
                  v5 = 1;
                  PsLookupProcessByProcessId(ProcessId, &TokenHandle);
            // …
            

            圖3 NotifyRoutine

            DriverEntry注冊NotifyRoutine的偽代碼如下:

            int __stdcall sub_407000(int a1, int a2)
            {
            // …
              DbgPrint("加載*外驅動.\n");
              PsSetCreateProcessNotifyRoutine(NotifyRoutine, 0);
            // …
              return dword_405248(dword_4056BC, a1, a2, &v3, &v7, 0); 
            }
            

            圖4 PsSetCreateProcessNotifyRoutine

            NotifyRoutine的流程很簡單,最重要的分支如下:

            (1) 判斷是否創建了進程

            (2) 是,則判斷是否由w3wp.exe所創建

            (3) 是,則與白名單比較。

            (4) 中止所有不在白名單上的進程

            (5) 給用戶返回“拒絕訪問”的提示

            白名單為硬編碼,主要放行了.Net編譯器的命令,否則源代碼就無法在線編譯執行了。它允許的命令:

            C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe
            C:\\WINDOWS\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe”
            ……
            

            它還允許System用戶(SID為S-1-5-18)執行C:\WINDOWS\system32\cmd.exe等命令。

            所有命令都帶有完整路徑,如果擁有足夠的權限(如提權成功后),可將存在于白名單且系統中一般不存在的命令替換為你的工具,如:

            C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\csc.exe
            C:\\WINDOWS\\Microsoft.NET\\Framework\\v3.5\\csc.ex
            …
            

            替換后的命令在Shell中可正常執行,僅會在C盤根目錄下的日志中留下一條NotKill記錄。

            判斷系統中是否存在*外殺馬,一看C盤根目錄是否存在 7i24_com_FreeHostKill_vxxx.txt的日志文件,二看system32\drivers下是否存在FreeHostKill.sys,三看注冊表。

            總之,*外殺馬不僅僅殺馬,它是什么人都殺。它只是一個極其原始的防火墻,通過監控所有進程的創建,在白名單的控制之下,哪怕位高權重的Administrators組用戶也無法在Shell中執行命令。

            0x02 光明而曲折的破解之路


            道高一尺,魔高一丈,既然明白了原理,就來嘗試如何破解吧。

            我不知道是否有人在低權限的腳本環境中有辦法躲過驅動的監控,如果有,那真要頂禮膜拜了。

            我不是圣人,還是按照通常的思路來完成我的Shell:

            (1) 不創建進程

            (2) 不創建線程

            (3) 直接使用Shell代碼將用戶提升至最高權限

            前途是光明的,道路是曲折的。只要有人嘗試了這條路,很快就會出現更多的探索者,期待更多的奇思妙想的出現。

            許多漏洞Exploit都采用了vc++編寫,因此最初的做法是弄清漏洞的原理后,使用C#語法逐行重寫這些源代碼。十多天磨練下來,唯一的感受就是——痛苦,九九八十一重的煉獄也不過如此。

            重寫內容 對人的摧殘度 說明
            API DllImport API、結構、常數,PInvoke站點提供查詢
            C++指針 IntPtr
            托管內存與非托管內存的數據交換 Marshal類支持
            內嵌匯編 ShellCode,召喚請叫我雷鋒的人

            好想開個遵義會議,讓人指出一條明路。日夜google中,終于一個家伙說,使用dll封裝你的代碼吧。神啊,如此有創意的點子,為何不是我想出來的呢?

            醍醐灌頂之后,本人的血壓暫時飆升到160,刷刷刷地把main函數改名導出,兩分鐘內dll封裝完畢,真是無本生意的典范。看導演的安排,接下的劇情無非就是千里狙敵,褲襠藏雷,開著21世紀的R2概念車去欺負剛擺脫叢林文化的小膏藥旗了。

            可惜天亮了,美夢成空,為了讓大伙不再走我的老路,我把那些令人欲仙欲死的問題總結如下:

            (1) Wow64麻煩

            省略幾千字,我把它放到了本系列篇(三)中加以詳述。

            (2) LoadLibrary加載DLL提示無法找到模塊

            在本機上正常加載的DLL,天殺的虛擬機卻提示無法找到模塊。這是因為操作系統缺少DLL所依賴的運行庫文件。若不想把自己的寶貝工具弄得像超生游擊隊,只有想辦法把庫代碼直接封裝進DLL中。我使用兩種方式來解決:

            (1)右鍵打開項目的屬性,C/C++ - 代碼生成 – 運行庫 – 將/MD選項改為/MT(或/MTd)選項。再次編譯,立刻發現生成的dll臃腫了不少,問題解決。

            (2)把源代碼放到vc6下編譯。我首先嘗試利用vs2015環境來輔助vc6的編譯。不曾想捅了一個危險的馬蜂窩,彈出了一大串與頭文件有關的警告和錯誤,想來微軟也懶得保持那代價高昂的兼容性了。前后折騰了半小時,乖乖放棄。接著切換到vs2010環境,無須任何的修改,vc6順利完成編譯,問題解決。

            在vc6中如何編譯64位程序?山寨某前輩的經驗給懶漢們參考一下:(以vs2010為例)

            分為3個步驟:

            創建64位環境

            在開始菜單下點擊“Visual Studio 2010 – Visual Studio Tools – Visual Studio x64 兼容工具命令提示(2010)”,然后在此命令提示符中運行VC6:

            D:\vc\vc6common\MSDev98\Bin\MSDEV.EXE /useenv

            圖5 x64 兼容工具命令提示

            修改配置

            復制Release或Debug的配置,起名xx64,激活該配置。(1、Build – Configurations – Add…;2、Build – Set Active Configuration…)

            圖6 新建Win32 Debug64配置

            修改項目配置

            1、在“Project Settings”對話框中, 點擊“General”標簽. 在“Output directories”, 在“Intermediate files” 和“Output files”輸入框中, 鍵入“Debug64”(無引號)

            圖7 設置輸出路徑

            2、在“C/C++”標簽上, “Debug info”下拉列表中, 選擇“Program database”(參數選項對應是 /Zi)

            圖8 設置調試信息

            3、在“Link”標簽上, “Project options”的輸入框中, 將“/machine:I386”改為“/machine:AMD64”(命令中將出現兩個不同的/machine)

            圖9 設置編譯指令

            編譯后成功得到大腹便便的64位dll。

            (3) w3wp.exe遇到無法處理的異常,網站崩潰

            我的破壞力還蠻大的。把本機調試通過的程序放到服務器上運行,瞬間弄崩了網站,重啟IIS后再執行幾次,服務器藍屏死機。

            代碼基本未變,我只是把它封裝在DLL中,由w3wp.exe加載運行,怎么就崩潰了呢。長夜漫漫,無心睡眠,在迷糊中把IIS 7應用程序池從集成模式調整為經典模式后,異常莫明地消失了。比爾,你想玩死人么 ?集成與經典模式到底是怎么一回事?

            圖10 集成模式處理管道

            八股文常常引用上圖說明IIS7的集成模式。IIS 7集成了ASP.NET運行庫,使用統一的管道來處理請求。經典模式兼容了IIS 6,如下圖所示,處理ASP.NET動態請求的只是IIS的一個插件——ISAPI模塊。同理,PHP插件只處理PHP請求,它們各司其職,互不干涉。兩種模式的差別涇渭分明。

            圖11 經典模式處理流程

            還有一些值得閱讀的入門文檔,如《ASP.NET Application Life Cycle Overview for IIS 7.0》,概述了ASP.NET應用程序在生命周期里發生了什么事情。《IIS Modules Overview》主要說明模式及其配置方式。從IIS 7的模塊界面可以看到,集成模式使用托管代碼模塊來處理.aspx頁面的請求,而經典模式使用本機代碼模塊。

            圖12 請求處理模塊

            書讀了不少,按流行俚語,“然而這并沒有什么ruan用”,還缺少某種催化劑,看來我只能再次求助于Windbg了。

            使用kp命令查看異常發生時的調用棧,前后幾十個調用,秘密就隱藏在它們中間。仔細觀察兩種模式,為了運行我的代碼,最后都從托管環境轉入了非托管環境,非托管環境下的調用完全相同。完蛋了,究竟要從哪里下手哇。咬咬牙,開始跟吧,十多天下來,人比黃花瘦。

            今天是個好日子,我升級了。我察覺自己又犯了老毛病,沒有認真檢查關鍵語句的運行結果。

            if (x)
            {
                // y
            }
            

            經典模式下x為真,這符合預期,然而在操蛋的集成模式下為假,稍不留神就忽略了。再追溯x的來源,終于發現集成模式似乎由于緩存的影響,對本機DLL的變化不能做出實時的更新。

            解決起來簡單而粗暴,加個else直接返回錯誤提示。我并不介意多運行三兩次,誰讓它們不是我的機子呢,等集成模式睡醒了,更新了它的緩存,權限也到手了。

            (4) w3wp.exe已提升為System權限,但Shell權限不變。

            經過第三階段的苦戰,我的代碼終于可以穩定地運行了,但又出現了一個奇怪的現象。

            在提升權限之前,查詢應用程序池的用戶:

            圖13 提權前用戶

            此時,75804號進程,即w3wp.exe擁有IIS_IUSRS用戶權限。緊接著提升權限,頁面顯示了執行結果:

            圖14 Shell代碼提權

            請忽略若干無用的調試信息,我們需要關注的是最后三行。w3wp.exe的進程號仍為75804(也可能會創建新的w3wp.exe),用戶權限已提升為SYSTEM。

            讓我們再次查看此時應用程序池的用戶:

            圖15 提權成功后用戶未變

            怪哉?應用程序池的用戶為何沒有改變呢?

            晚飯時間到了,補充足夠的能量后,我已經想到了一種可能。IIS啟用了模擬功能后,即使w3wp.exe以SYSTEM權限運行,應用程序池用戶仍保持不變。

            為了驗證這種可能性,讓我們亮劍,它就是用來中斷模擬的API——RevertToSelf。美女現身,Beautiful!

            圖16 強制中斷IIS模擬恢復用戶身份

            0x03 勝利的號角

            西元201x年,001號大殺器研制成功,為紀念cctv,我把它命名為cv51。

            圖17 未能進入內核無權讀寫致出錯

            首次執行出錯,不必理會,再次嘗試執行。

            圖18 提權成功

            cv51的兄弟cvbb此時運行在SYSTEM權限下,順利添加用戶tingting。

            圖19 其他工具共享同一個w3wp.exe的權限

            登錄服務器。任務管理器中,w3wp.exe(PID:22324)在提升權限后的身份可能顯示為SYSTEM,也可能保持不變。

            圖20 模擬使任務管理器不能真實顯示Shell的權限

            查看管理員的密碼,統計是否有使用強密碼的習慣,獲得的密碼僅用于學習與研究,將在24小時內刪除。上傳mimikatz,在命令提示符下執行如下命令,所有登錄用戶盡在日志中:(mimikatz是開源工具,請到官方站點下載,不吃毒蘋果)

            mimikatz log privilege::debug sekurlsa::logonpasswords

            圖21 mimikatz破解曾經登錄的用戶信息

            以上測試在Windows 2003、2008及R2版本中通過。

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线