Vynae.psm1

# %{$_.Days * 24 + $_.Hours":"$_.Minutes}
<#
ISSUES
 
* Track time to completion
*
 
 
PARAM DEF
 
Name Description Done?
----------------------------------------------------------------------------------
Name Name of the processes Y
Strict Force exact match for string options Y
Network Return network information Y
ID Process ID Y
PPID Parent Process ID Y
ParentName Parent Process Name Y
ExecutablePath Process Executable Path Y
CommandLine Search command line options Y
Visualize Create a visualization of the data Y
Trace Trace the process back to it's origin Y
Time Specify a time Days/Hours/Minutes N
Hash Search via hash Y
Algorithm Algorithm for hashing Y
NetOnly Only Show processes with network connections Y
NetState Search by network state Y
Outfile Save a transcript Y
ManualQuery User entered query (CQL) Y
#>



<#GLOBALS#>
$global:ErrorActionPreference="SilentlyContinue"




<#Network Retrieval#>
function NetworkGather($Process){
    $x = Get-NetTCPConnection -OwningProcess $Process
    $NetworkInfo = [ordered]@{      
        State           = $x.State
        LocalAddress    = $x.LocalAddress
        LocalPort       = $x.LocalPort
        RemoteAddress   = $x.RemoteAddress
        RemotePort      = $x.RemotePort
    }
    return $NetworkInfo
}

<#BUILD CIM QUERY#>
function CIMQUERY{
    <#MANUAL USER QUERY#>
    if($ManualQuery){
        $global:QueryList += "`n`tGet-CimInstance -Query `"$ManualQuery`""
        return "Get-CimInstance -Query `"$ManualQuery`""
    }

    <# BUILD QUERY
 
    String properties must be enclosed in escaped single quotes `'string`'
 
    #>

    $expression = "Get-CimInstance -Query `"Select * from WIN32_Process"
    if($Name -or $ID -or $PPID -or $ExecutablePath -or $CommandLine){$expression += " where "}
    <#BUILD STANDARD QUERY#>
    if($Trace -eq $False){
        if($Name){
            # Test if other properties have been added
            if($expression.length -ne 58){
                $expression += " AND "
            }
            if($Strict){
                $expression += "name=`'$name`'"
            }else{
                $expression += "name like `'$name%`'"
            }
        }
        if($ID){
            if($expression.length -ne 58){
                $expression += " AND "
            }
            $expression += "ProcessId=$ID"
        }
        if($PPID){
            if($expression.length -ne 58){
                $expression += " AND "
            }
            $expression += "ParentProcessId=$PPID"
        }
        if($ExecutablePath){
            if($expression.length -ne 58){
                $expression += " AND "
            }
            if($Strict){
                $expression += "ExecutablePath=`'$ExecutablePath`'"
            }else{
                $expression += "ExecutablePath like `'%$ExecutablePath%`'"
            }
        }
        if($CommandLine){
            if($expression.length -ne 58){
                $expression += " AND "
            }
            if($Strict){
                $expression += "CommandLine=`'$CommandLine`'"
            }else{
                $expression += "CommandLine like `'%$CommandLine%`'"
            }
        }
        # End Query
        $expression += "`""

        <# START OPTIONS#>
        if($ParentName){
            $expression += " | % {if ((Get-Process -ID `$_.ParentProcessId).Name -match `$ParentName){`$_}}"
        }
        if($NetOnly){
            $expression += " | % {if ((Get-NetTCPConnection -OwningProcess `$_.ProcessId)){`$_}}"
        }
        if($NetState){
            $expression += " | % {if ((Get-NetTCPConnection -OwningProcess `$_.ProcessId) -and ((Get-NetTCPConnection -OwningProcess `$_.ProcessId).state -eq `$NetState)){`$_}}"
        }
        if($Hash){
            $expression += " | % {if ((Get-FileHash `$_.ExecutablePath -Algorithm `$Algorithm).hash -eq `"`$Hash`"){`$_}}"
        }
        $global:QueryList += "`n`t$expression"
        return $expression
    }
    <#BUILD TRACE QUERY#>
    if($Trace){
        $expression += "ProcessId=$ID"
        $expression += "`""
        $global:QueryList += "`n`t$expression"
        return $expression
    }
}


<#OUTPUT FILTERING#>
function ProcessOutput($Process){
    $Process
    if($Visualize){
        $global:ProcessArray += $Process
    }
    if($Network){
        Get-NetTCPConnection -OwningProcess $Process.ID | ft State,LocalAddress,LocalPort,RemoteAddress,RemotePort
    }
    if($Trace){
        $Parent = $Process.ParentId
        if((Get-CimInstance -Query "SELECT * FROM WIN32_Process WHERE ProcessId=$Parent") -And $Parent -ne 0 -And $Parent -ne $NULL){
            Get-ProcessInfo -Trace -ID $Process.ParentId
        }
    }
}


<#
.Synopsis
  Process examination and analysis tool.
 
.Description
  Vynae 2.0 is a module focused version of Vynae and is designed for process exmaination and analysis.
  Using custom PSObjects, Vynae 2.0 can be integrated into any script and can be used with built-in tools like select-object, where-object, and foreach-object.
  This is an upgrade from the original Vynae tool, which did not take advantage of custom objects.
 
  Vynae has many applications and uses, and further information can be found on https://blog.bajiri.com.
 
.Parameter Name
    Name of the processes
.Parameter Strict
    Force exact match for string options
.Parameter Network
    Return network information
.Parameter ID
    Process ID
.Parameter PPID
    Parent Process ID
.Parameter ParentName
    Parent Process Name
.Parameter ExecutablePath
    Process Executable Path
.Parameter CommandLine
    Search command line options
.Parameter Visualize
    Create a visualization of the data (GridView)
.Parameter Trace
    Trace the process back to its origin
.Parameter Hash
    Search via hash
.Parameter Algorithm
    Algorithm for hashing
.Parameter NetOnly
    Only Show processes with network connections
.Parameter NetState
    Search by network state
.Parameter Outfile
    Save a transcript
.Parameter ManualQuery
    User entered query (CQL)
 
.Example
   # List all processes
   Get-ProcessInfo
 
.Example
   # List all processes and associated network connections.
   Get-ProcessInfo -Network
 
.Link
    http://blog.bajiri.com
    
#>

function Get-ProcessInfo{
    param([switch]$Network, [string]$Name, [switch]$Strict, [int]$ID, [int]$PPID, [string]$ParentName, [string]$ExecutablePath, [string]$CommandLine, [Switch]$Trace, [DateTime]$Time, [string]$Hash, [string]$Algorithm="SHA256", [Switch]$NetOnly, [string]$NetState, [string]$Outfile, [switch]$Visualize, [string]$ManualQuery)
    Begin {
        $Stopwatch = [System.Diagnostics.Stopwatch]::startNew()
        $global:QueryList=@()
        if($Visualize){
            $global:ProcessArray =@()
        }
        if($Outfile){
            Start-Transcript $Outfile
        }
    }
    process {
        foreach($x in (iex (CIMQUERY) )){
            $Parent = Get-CimInstance CIM_Process | ? ProcessID -eq $x.ParentProcessID
            $ProcessInfo = New-Object PSObject -Property $([ordered]@{
                Name            = $x.ProcessName
                ID              = $x.ProcessId
                CommandLine     = $x.CommandLine
                ExecutablePath  = if ($x.ExecutablePath) {$x.ExecutablePath} else {""}
                ExecutableHash  = if ($x.ExecutablePath) { (Get-FileHash $x.ExecutablePath -Algorithm $Algorithm).Hash } else {""}
                ParentName      = $Parent.ProcessName
                ParentID        = $Parent.ProcessId
                ParentPath      = if ($Parent.ExecutablePath) {$Parent.ExecutablePath} else {""}
                ParentHash      = if ($Parent.ExecutablePath) {(Get-FileHash $Parent.ExecutablePath -Algorithm $Algorithm).Hash} else {""}
                CreationDate    = $x.CreationDate
                ActiveTime      = (New-TimeSpan -Start $x.CreationDate -End $(Get-Date) | Select Days, Hours, Minutes)
                })
            <#SET DEFAULT PROPERTIES (HIDE NETWORK PROPERTIES)#>
            $ProcessInfo.PSObject.TypeNames.Insert(0,'ProcessInfo')
            $DefaultDisplaySet = "Name, ID, CommandLine, ExecutablePath, ExecutableHash, ParentName, ParentID, ParentPath, ParentHash, CreationDate, ActiveTime"
            $DefaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$DefaultDisplaySet)
            Update-TypeData -TypeName ProcessInfo -DefaultDisplayPropertySet Name, ID, CommandLine, ExecutablePath, ExecutableHash, ParentName, ParentID, ParentPath, ParentHash, CreationDate, ActiveTime
            if ($Network) {if (Get-NetTCPConnection -OwningProcess $x.ProcessId) {$Network_HT = NetworkGather($x.ProcessId); Add-Member -InputObject $ProcessInfo -NotePropertyMembers $Network_HT}}
            ProcessOutput($ProcessInfo)
        }
    }
    end {
        $Stopwatch.Stop() 
        Write-Host "Time Elapsed(seconds):"$Stopwatch.Elapsed.TotalSeconds
        write-Host "Queries used: "$QueryList
        Stop-Transcript
        if($Visualize){
            $global:ProcessArray | sort -property ActiveTime -Descending| ogv -Title "ProcessInfo"
        }
    }

}

Export-ModuleMember -Function Get-ProcessInfo