mirror of
https://github.com/rapid7/metasploit-payloads
synced 2024-12-21 05:35:54 +01:00
cf6287e031
This commit actually changes the PS runner code so that it's base64-encoded before being sent to the interpreter. It's a bit of a hack but it means that all multiline commands are properly supported. IEX for the win!
363 lines
11 KiB
C#
Executable File
363 lines
11 KiB
C#
Executable File
using System;
|
|
using System.Collections.Generic;
|
|
using System.Management.Automation.Host;
|
|
using System.Management.Automation.Runspaces;
|
|
using System.Text;
|
|
|
|
namespace MSF.Powershell
|
|
{
|
|
public class Runner : IDisposable
|
|
{
|
|
// We use a dictionary of runners based on ID, this means that we can maintain
|
|
// separate sessions if we want to.
|
|
private static Dictionary<string, Runner> _runners;
|
|
private InitialSessionState _state;
|
|
private CustomPSHost _host = null;
|
|
private Runspace _runspace = null;
|
|
private string _id;
|
|
|
|
static Runner()
|
|
{
|
|
System.Diagnostics.Debug.Write("[PSH RUNNER] Static constructor called");
|
|
_runners = new Dictionary<string, Runner>();
|
|
}
|
|
|
|
public static string Execute(string id, string ps)
|
|
{
|
|
System.Diagnostics.Debug.Write(string.Format("[PSH RUNNER] Executing command on session {0}", id));
|
|
if (!_runners.ContainsKey(id))
|
|
{
|
|
_runners.Add(id, new Runner(id));
|
|
}
|
|
var runner = _runners[id];
|
|
return runner.Execute(ps);
|
|
}
|
|
|
|
public static Runner Get(string id)
|
|
{
|
|
if (!_runners.ContainsKey(id))
|
|
{
|
|
_runners.Add(id, new Runner(id));
|
|
}
|
|
return _runners[id];
|
|
}
|
|
|
|
public static void Remove(string id)
|
|
{
|
|
if (_runners.ContainsKey(id))
|
|
{
|
|
_runners[id].Dispose();
|
|
_runners.Remove(id);
|
|
}
|
|
}
|
|
|
|
public Runner(string id)
|
|
{
|
|
_id = id;
|
|
_state = InitialSessionState.CreateDefault();
|
|
_state.AuthorizationManager = null;
|
|
|
|
_host = new CustomPSHost();
|
|
|
|
_runspace = RunspaceFactory.CreateRunspace(_host, _state);
|
|
_runspace.Open();
|
|
}
|
|
|
|
public string Execute(string ps)
|
|
{
|
|
ps = "IEX ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(\"" + Convert.ToBase64String(Encoding.UTF8.GetBytes(ps), Base64FormattingOptions.None) + "\")))";
|
|
System.Diagnostics.Debug.Write(string.Format("[PSH RUNNER] Executing PS: {0}", ps));
|
|
using (Pipeline pipeline = _runspace.CreatePipeline())
|
|
{
|
|
pipeline.Commands.AddScript(ps);
|
|
pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
|
|
pipeline.Commands.Add("out-default");
|
|
pipeline.Invoke();
|
|
}
|
|
|
|
return _host.GetAndFlushOutput();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_runspace != null)
|
|
{
|
|
_runspace.Close();
|
|
_runspace.Dispose();
|
|
}
|
|
}
|
|
|
|
private class CustomPSHost : PSHost
|
|
{
|
|
private Guid _hostId;
|
|
private CustomPSHostUserInterface _ui = null;
|
|
|
|
public CustomPSHost()
|
|
{
|
|
_hostId = Guid.NewGuid();
|
|
_ui = new CustomPSHostUserInterface();
|
|
}
|
|
|
|
public string GetAndFlushOutput()
|
|
{
|
|
var output = _ui.ToString();
|
|
_ui.Clear();
|
|
return output;
|
|
}
|
|
|
|
public override System.Globalization.CultureInfo CurrentCulture
|
|
{
|
|
get { return System.Threading.Thread.CurrentThread.CurrentCulture; }
|
|
}
|
|
|
|
public override System.Globalization.CultureInfo CurrentUICulture
|
|
{
|
|
get { return System.Threading.Thread.CurrentThread.CurrentUICulture; }
|
|
}
|
|
|
|
public override void EnterNestedPrompt()
|
|
{
|
|
}
|
|
|
|
public override void ExitNestedPrompt()
|
|
{
|
|
}
|
|
|
|
public override Guid InstanceId
|
|
{
|
|
get { return _hostId; }
|
|
}
|
|
|
|
public override string Name
|
|
{
|
|
get { return "MSFConsole"; }
|
|
}
|
|
|
|
public override void NotifyBeginApplication()
|
|
{
|
|
}
|
|
|
|
public override void NotifyEndApplication()
|
|
{
|
|
}
|
|
|
|
public override void SetShouldExit(int exitCode)
|
|
{
|
|
}
|
|
|
|
public override PSHostUserInterface UI
|
|
{
|
|
get { return _ui; }
|
|
}
|
|
|
|
public override Version Version
|
|
{
|
|
get { return new Version(0, 1); }
|
|
}
|
|
}
|
|
|
|
private class CustomPSHostUserInterface : PSHostUserInterface
|
|
{
|
|
private StringBuilder _buffer;
|
|
private CustomPSHostRawUserInterface _rawUI;
|
|
|
|
public CustomPSHostUserInterface()
|
|
{
|
|
_buffer = new StringBuilder();
|
|
_rawUI = new CustomPSHostRawUserInterface();
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return _buffer.ToString();
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
_buffer.Remove(0, _buffer.Length);
|
|
}
|
|
|
|
public override Dictionary<string, System.Management.Automation.PSObject> Prompt(string caption, string message, System.Collections.ObjectModel.Collection<FieldDescription> descriptions)
|
|
{
|
|
return new Dictionary<string, System.Management.Automation.PSObject>();
|
|
}
|
|
|
|
public override int PromptForChoice(string caption, string message, System.Collections.ObjectModel.Collection<ChoiceDescription> choices, int defaultChoice)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
public override System.Management.Automation.PSCredential PromptForCredential(string caption, string message, string userName, string targetName, System.Management.Automation.PSCredentialTypes allowedCredentialTypes, System.Management.Automation.PSCredentialUIOptions options)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public override System.Management.Automation.PSCredential PromptForCredential(string caption, string message, string userName, string targetName)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public override PSHostRawUserInterface RawUI
|
|
{
|
|
get { return _rawUI; }
|
|
}
|
|
|
|
public override string ReadLine()
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
public override System.Security.SecureString ReadLineAsSecureString()
|
|
{
|
|
return new System.Security.SecureString();
|
|
}
|
|
|
|
public override void Write(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value)
|
|
{
|
|
_buffer.Append(value.TrimEnd());
|
|
}
|
|
|
|
public override void Write(string value)
|
|
{
|
|
_buffer.Append(value.TrimEnd());
|
|
}
|
|
|
|
public override void WriteDebugLine(string message)
|
|
{
|
|
_buffer.Append("DEBUG: ");
|
|
_buffer.AppendLine(message.TrimEnd());
|
|
}
|
|
|
|
public override void WriteErrorLine(string value)
|
|
{
|
|
_buffer.Append("ERROR: ");
|
|
_buffer.AppendLine(value.TrimEnd());
|
|
}
|
|
|
|
public override void WriteLine(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value)
|
|
{
|
|
_buffer.AppendLine(value.TrimEnd());
|
|
}
|
|
|
|
public override void WriteLine(string value)
|
|
{
|
|
_buffer.AppendLine(value.TrimEnd());
|
|
}
|
|
|
|
public override void WriteLine()
|
|
{
|
|
_buffer.AppendLine();
|
|
}
|
|
|
|
public override void WriteProgress(long sourceId, System.Management.Automation.ProgressRecord record)
|
|
{
|
|
}
|
|
|
|
public override void WriteVerboseLine(string message)
|
|
{
|
|
_buffer.Append("VERBOSE: ");
|
|
_buffer.AppendLine(message.TrimEnd());
|
|
}
|
|
|
|
public override void WriteWarningLine(string message)
|
|
{
|
|
_buffer.Append("WARNING: ");
|
|
_buffer.AppendLine(message.TrimEnd());
|
|
}
|
|
}
|
|
|
|
private class CustomPSHostRawUserInterface : PSHostRawUserInterface
|
|
{
|
|
|
|
public override ConsoleColor BackgroundColor
|
|
{
|
|
get { return ConsoleColor.Black; }
|
|
set { }
|
|
}
|
|
|
|
public override Size BufferSize
|
|
{
|
|
get { return new Size(120, 100); }
|
|
set { }
|
|
}
|
|
|
|
public override Coordinates CursorPosition
|
|
{
|
|
get { return new Coordinates(0, 0); }
|
|
set { }
|
|
}
|
|
|
|
public override int CursorSize
|
|
{
|
|
get { return 1; }
|
|
set { }
|
|
}
|
|
|
|
public override void FlushInputBuffer()
|
|
{
|
|
}
|
|
|
|
public override ConsoleColor ForegroundColor
|
|
{
|
|
get { return ConsoleColor.White; }
|
|
set { }
|
|
}
|
|
|
|
public override BufferCell[,] GetBufferContents(Rectangle rectangle)
|
|
{
|
|
return new BufferCell[0,0];
|
|
}
|
|
|
|
public override bool KeyAvailable
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
public override Size MaxPhysicalWindowSize
|
|
{
|
|
get { return new Size(int.MaxValue, int.MaxValue); }
|
|
}
|
|
|
|
public override Size MaxWindowSize
|
|
{
|
|
get { return new Size(120, 100); }
|
|
}
|
|
|
|
public override KeyInfo ReadKey(ReadKeyOptions options)
|
|
{
|
|
return new KeyInfo();
|
|
}
|
|
|
|
public override void ScrollBufferContents(Rectangle source, Coordinates destination, Rectangle clip, BufferCell fill)
|
|
{
|
|
}
|
|
|
|
public override void SetBufferContents(Rectangle rectangle, BufferCell fill)
|
|
{
|
|
}
|
|
|
|
public override void SetBufferContents(Coordinates origin, BufferCell[,] contents)
|
|
{
|
|
}
|
|
|
|
public override Coordinates WindowPosition
|
|
{
|
|
get { return new Coordinates(-200, -200); }
|
|
set { }
|
|
}
|
|
|
|
public override Size WindowSize
|
|
{
|
|
get { return new Size(120, 100); }
|
|
set { }
|
|
}
|
|
|
|
public override string WindowTitle
|
|
{
|
|
get { return string.Empty; }
|
|
set { }
|
|
}
|
|
}
|
|
}
|
|
}
|