Skip to content

Instantly share code, notes, and snippets.

@jaredcatkinson
Last active February 24, 2024 15:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jaredcatkinson/f04cc846b79b42b97d081b6065962483 to your computer and use it in GitHub Desktop.
Save jaredcatkinson/f04cc846b79b42b97d081b6065962483 to your computer and use it in GitHub Desktop.
Script to derive a File Path from a Command Line string
function Resolve-CommandLineToFilePath
{
<#
.SYNOPSIS
The Resolve-CommandLineToFilePath function takes an arbitrary Command Line and resolves the called application/file's path.
.PARAMETER CommandLine
The CommandLine that you want to convert to a file path.
.NOTES
Author: Jared Atkinson (@jaredcatkinson)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
TODO: Throw error if no FilePath is found
.EXAMPLE
Resolve-CommandLineToFilePath -CommandLine '%windir%\system32\rundll32.exe'
CommandLine Path
----------- ----
%windir%\system32\rundll32.exe c:\windows\system32\rundll32.exe
.EXAMPLE
'cmd' | Resolve-CommandLineToFilePath
CommandLine Path
----------- ----
cmd c:\windows\system32\cmd.exe
.EXAMPLE
(Get-WmiObject -Class win32_service).PathName | Resolve-CommandLineToFilePath
CommandLine Path
----------- ----
C:\Windows\SysWOW64\Macromed\Flash\FlashPlayerUpdateService.exe C:\Windows\SysWOW64\Macromed\Flash\...
C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\System32\alg.exe C:\WINDOWS\System32\alg.exe
C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\svchost.exe -k netsvcs C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\svchost.exe -k netsvcs C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\System32\svchost.exe -k AppReadiness C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\system32\AppVClient.exe C:\WINDOWS\system32\AppVClient.exe
C:\WINDOWS\system32\svchost.exe -k wsappx C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\aspnet_state.exe C:\WINDOWS\Microsoft.NET\Framework6...
C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\system32\svchost.exe -k AxInstSVGroup C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\System32\svchost.exe -k netsvcs C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\system32\svchost.exe -k LocalServiceNoNetwork C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\System32\svchost.exe -k netsvcs C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\system32\svchost.exe -k DcomLaunch C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\System32\svchost.exe -k netsvcs C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\System32\svchost.exe -k LocalServiceAndNoImpersonation C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\system32\svchost.exe -k LocalService C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\svchost.exe -k LocalService C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\svchost.exe -k netsvcs C:\WINDOWS\system32\svchost.exe
"C:\Program Files\Common Files\Microsoft Shared\ClickToRun\OfficeClickToRun.exe" /service C:\Program Files\Common Files\Micro...
C:\WINDOWS\System32\svchost.exe -k wsappx C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\system32\dllhost.exe /Processid:{02D4B3F1-FD88-11D1-960D-00805FC79235} C:\WINDOWS\system32\dllhost.exe
C:\WINDOWS\system32\svchost.exe -k LocalServiceNoNetwork C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\svchost.exe -k NetworkService C:\WINDOWS\system32\svchost.exe
#>
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string[]]
$CommandLine
)
process
{
foreach($command in $CommandLine)
{
$props = @{
CommandLine = $command
}
# Expand Environment Variable
$command = [System.Environment]::ExpandEnvironmentVariables($command)
# Remove Quotes from the Path
$command = $command.Replace('"','')
# Current Working Directory
$workingdirectory = (Get-Location).Path.ToLower()
if(Test-Path -Path $command -PathType Leaf)
{
if($command -notmatch '\\')
{
$command = "$($workingdirectory)\$($command)"
}
$props.Add('Path',$command)
}
else
{
$sb = New-Object -TypeName System.Text.StringBuilder
# We are going to split the command line on spaces and test each iteration
:outer foreach($pathsegment in ($command -split ' ' | Where-Object { $_ }))
{
$sb.Append($pathsegment) | Out-Null
$finalpath = $sb.ToString()
Write-Verbose "Testing: $($finalpath)"
if(Test-Path -Path $finalpath -PathType Leaf)
{
if($finalpath.ToLower() -notmatch '\\')
{
$finalpath = "$($workingdirectory)\$($finalpath)"
}
$props.Add('Path',"$($finalpath)")
break outer
}
:inner foreach($pathext in ($env:PATHEXT -split ';' | Where-Object { $_ } ))
{
Write-Verbose "Testing: $($finalpath)$($pathext)"
if(Test-Path -Path "$($finalpath)$($pathext)" -PathType Leaf)
{
if($finalpath.ToLower() -notmatch '\\')
{
$finalpath = "$($workingdirectory)\$($finalpath)"
}
$props.Add('Path',"$($finalpath)$($pathext.ToLower())")
break outer
}
:innermost foreach($path in ($env:PATH -split ';' | Where-Object { $_ } ))
{
Write-Verbose "Testing: $($path)\$($finalpath)"
if(Test-Path -Path "$($path)\$($finalpath)" -PathType Leaf)
{
$props.Add('Path',"$($path)\$($finalpath)")
break outer
}
Write-Verbose "Testing: $($path)\$($finalpath)$($pathext)"
if(Test-Path -Path "$($path)\$($finalpath)$($pathext)" -PathType Leaf)
{
$props.Add('Path',"$($path)\$($finalpath)$($pathext.ToLower())")
break outer
}
}
}
$sb.Append(' ') | Out-Null
}
}
Write-Output (New-Object -TypeName psobject -Property $props)
}
}
}
Describe "Tests for the Resolve-CommandLineToFilePath function" {
It "works for full path" {
('C:\WINDOWS\System32\snmptrap.exe' | Resolve-CommandLineToFilePath).Path.ToLower() | Should be 'C:\windows\system32\snmptrap.exe'
}
It "works for full path, spaces, and quotes" {
('"C:\Program Files\Windows Defender Advanced Threat Protection\MsSense.exe"' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Program Files\Windows Defender Advanced Threat Protection\MsSense.exe'.ToLower()
}
It "works for full path, spaces, and no quotes" {
('C:\Program Files\OpenVPN\bin\openvpnserv.exe' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Program Files\OpenVPN\bin\openvpnserv.exe'.ToLower()
}
It "works with full path, no quotes, no spaces, and command line arguments" {
('C:\WINDOWS\system32\svchost.exe -k netsvcs' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\WINDOWS\system32\svchost.exe'.ToLower()
}
It "works with quotes, spaces, and arguments" {
('"C:\Program Files\Common Files\Microsoft Shared\ClickToRun\OfficeClickToRun.exe" /service' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Program Files\Common Files\Microsoft Shared\ClickToRun\OfficeClickToRun.exe'.ToLower()
}
It "works with no extension" {
('C:\Windows\system32\cmd' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Windows\system32\cmd.exe'.ToLower()
}
It "works with no path and no extension" {
Set-Location -Path \
('cmd' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Windows\system32\cmd.exe'.ToLower()
}
It "works with an extension, but no path" {
Set-Location -Path \
('cmd.exe' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Windows\system32\cmd.exe'.ToLower()
}
It "works with Environment Variables" {
('%windir%\system32\rundll32.exe' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Windows\system32\rundll32.exe'.ToLower()
}
It "works with file in Current Working Directory with no path and no file extension" {
Set-Location -Path \Windows\System32\
('cmd' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Windows\system32\cmd.exe'.ToLower()
}
It "works with file in Current Working Directory with no path file extension" {
Set-Location -Path \Windows\System32\
('cmd.exe' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Windows\system32\cmd.exe'.ToLower()
}
It "works with file in Current Working Directory with no path, no file extension, and arguments" {
Set-Location -Path \Windows\System32\
('cmd /c notepad.exe' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Windows\system32\cmd.exe'.ToLower()
}
It "works with file in Current Working Directory with no path, file extension, and arguments" {
Set-Location -Path \Windows\System32\
('cmd.exe /c notepad.exe' | Resolve-CommandLineToFilePath).Path.ToLower() | Should Be 'C:\Windows\system32\cmd.exe'.ToLower()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment