Last active
February 24, 2024 15:18
-
-
Save jaredcatkinson/f04cc846b79b42b97d081b6065962483 to your computer and use it in GitHub Desktop.
Script to derive a File Path from a Command Line string
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
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) | |
} | |
} | |
} |
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
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