en-US/PSDetour.dll-Help.xml

<?xml version="1.0" encoding="utf-8"?>
<helpItems schema="maml" xmlns="http://msh">
  <command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
    <command:details>
      <command:name>New-PSDetourHook</command:name>
      <command:verb>New</command:verb>
      <command:noun>PSDetourHook</command:noun>
      <maml:description>
        <maml:para>Create a PSDetour hook from a scriptblock.</maml:para>
      </maml:description>
    </command:details>
    <maml:description>
      <maml:para>Creates a hook object from a PowerShell scriptblock to be used as a hook for a native C function. The scriptblock should contain an `[OutputType([...])]` attribute to denote what the return value is of the C function. It should also contain a `param()` block with parameters for each C function argument and their types. When the hook is run, the `$this` variable contains information about the hook itself and can be used to invoke the actual API through the `Invoke` method.</maml:para>
      <maml:para>Take care when typing the return and parameter types as a misconfiguration can cause the whole process to crash. A parameter can be marked with the `MarshalAs` attribute to denote the marshalling type behaviour to use. Currently only the `UnmanagedType`, `In`, and `Out` attributes can be set.</maml:para>
      <maml:para>See about_PSDetourMarshalling (./about_PSDetourMarshalling.md)for more information around how to define a hook and its input/output types.</maml:para>
    </maml:description>
    <command:syntax>
      <command:syntaxItem>
        <maml:name>New-PSDetourHook</maml:name>
        <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="1" aliases="none">
          <maml:name>DllName</maml:name>
          <maml:description>
            <maml:para>The DLL name or path where the C function to hook is defined.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">String</command:parameterValue>
          <dev:type>
            <maml:name>String</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
          <maml:name>MethodName</maml:name>
          <maml:description>
            <maml:para>The C function name/symbol to hook.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">String</command:parameterValue>
          <dev:type>
            <maml:name>String</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="3" aliases="ScriptBlock">
          <maml:name>Action</maml:name>
          <maml:description>
            <maml:para>The scriptblock to run when the C function is called. The `[OutputType([type])]` should be defined as the return value type of the C function. Parameters should also be defined in the `param()` block for each argument of the C function and their respective types. Any variables that reference variables outside of the `-Action` should be prefixed with `$using:VariableName`.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">ScriptBlock</command:parameterValue>
          <dev:type>
            <maml:name>ScriptBlock</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
          <maml:name>Address</maml:name>
          <maml:description>
            <maml:para>Hook the method at the address specified. This can be used to hook methods that are not publicly exported by name. The `-DllName` and `-MethodName` must still be set to provide enough metadata for the reflected method to be generated. By default the `Address` is the offset in the current process but `-AddressIsOffset` can be used to specify the address is an offset from the loaded `DllName` address of the process.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">IntPtr</command:parameterValue>
          <dev:type>
            <maml:name>IntPtr</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
          <maml:name>AddressIsOffset</maml:name>
          <maml:description>
            <maml:para>Will automatically calculated the actual method address from the loaded Dll module specified by `-DllName` based on the `-Address` value. For example if `Kernel32.dll` is loaded at the address `0x0000F000` and the specified address is `-Address 0x0001`, the final method address will be `0x0000F001`.</maml:para>
          </maml:description>
          <dev:type>
            <maml:name>SwitchParameter</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>False</dev:defaultValue>
        </command:parameter>
      </command:syntaxItem>
    </command:syntax>
    <command:parameters>
      <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="3" aliases="ScriptBlock">
        <maml:name>Action</maml:name>
        <maml:description>
          <maml:para>The scriptblock to run when the C function is called. The `[OutputType([type])]` should be defined as the return value type of the C function. Parameters should also be defined in the `param()` block for each argument of the C function and their respective types. Any variables that reference variables outside of the `-Action` should be prefixed with `$using:VariableName`.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">ScriptBlock</command:parameterValue>
        <dev:type>
          <maml:name>ScriptBlock</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
        <maml:name>Address</maml:name>
        <maml:description>
          <maml:para>Hook the method at the address specified. This can be used to hook methods that are not publicly exported by name. The `-DllName` and `-MethodName` must still be set to provide enough metadata for the reflected method to be generated. By default the `Address` is the offset in the current process but `-AddressIsOffset` can be used to specify the address is an offset from the loaded `DllName` address of the process.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">IntPtr</command:parameterValue>
        <dev:type>
          <maml:name>IntPtr</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
        <maml:name>AddressIsOffset</maml:name>
        <maml:description>
          <maml:para>Will automatically calculated the actual method address from the loaded Dll module specified by `-DllName` based on the `-Address` value. For example if `Kernel32.dll` is loaded at the address `0x0000F000` and the specified address is `-Address 0x0001`, the final method address will be `0x0000F001`.</maml:para>
        </maml:description>
        <command:parameterValue required="false" variableLength="false">SwitchParameter</command:parameterValue>
        <dev:type>
          <maml:name>SwitchParameter</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>False</dev:defaultValue>
      </command:parameter>
      <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="1" aliases="none">
        <maml:name>DllName</maml:name>
        <maml:description>
          <maml:para>The DLL name or path where the C function to hook is defined.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">String</command:parameterValue>
        <dev:type>
          <maml:name>String</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
        <maml:name>MethodName</maml:name>
        <maml:description>
          <maml:para>The C function name/symbol to hook.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">String</command:parameterValue>
        <dev:type>
          <maml:name>String</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
    </command:parameters>
    <command:inputTypes>
      <command:inputType>
        <dev:type>
          <maml:name>None</maml:name>
        </dev:type>
        <maml:description>
          <maml:para></maml:para>
        </maml:description>
      </command:inputType>
    </command:inputTypes>
    <command:returnValues>
      <command:returnValue>
        <dev:type>
          <maml:name>PSDetour.Commands.ScriptBlockHook</maml:name>
        </dev:type>
        <maml:description>
          <maml:para>An object that contains the necessary information for `Start-PSDetour` to setup the required hooks.</maml:para>
        </maml:description>
      </command:returnValue>
    </command:returnValues>
    <maml:alertSet>
      <maml:alert>
        <maml:para></maml:para>
      </maml:alert>
    </maml:alertSet>
    <command:examples>
      <command:example>
        <maml:title>-- Example 1 - Hook CreateDirectoryW with string marshalling --</maml:title>
        <dev:code>PS C:\&gt; New-PSDetourHook -DllName Kernel32 -MethodName CreateDirectoryW -Action {
... [OutputType([bool])]
... param (
... [System.Runtime.InteropServices.MarshalAs([System.Runtime.InteropServices.UnmanagedType]::LPWStr)]
... [string]$PathName,
... [IntPtr]$SecurityAttributes
... )
...
... # Calling $this.Invoke will invoke the actual function and return the value
... $this.Invoke($PathName, $SecurityAttributes)
... }</dev:code>
        <dev:remarks>
          <maml:para>This example will hook the CreateDirectoryW (https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createdirectoryw). The `OutputType` is denoted as `bool` to reflect the `BOOL` return value of the function. The `$PathName` parameter is documented as a `string` and is also marked as an `UnmanagedType.LPWStr` to help dotnet know it's a Unicode string. Without this attribute the string will be an `ANSI` string giving the wrong value. The `$this.Invoke` method is called to invoke the real `CreateDirectoryW` and the output is implicitly returned back to the caller. Only the last output from the scriptblock action is going to be returned, in this case there is only the output from `$this.Invoke`.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>--- Example 2 - Hook CreateDirectoryW with raw IntPtr paths ---</maml:title>
        <dev:code>PS C:\&gt; New-PSDetourHook -DllName Kernel32 -MethodName CreateDirectoryW -Action {
... [OutputType([bool])]
... param (
... [IntPtr]$PathName,
... [IntPtr]$SecurityAttributes
... )
...
... # Calling $this.Invoke will invoke the actual function and return the value
... $res = $this.Invoke($PathName, $SecurityAttributes)
...
... if (-not $res) {
... $path = "\\?\" + [System.Runtime.InteropServices.Marshal]::PtrToStringUni($PathName)
... $newPath = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($path)
... $res = $this.Invoke($newPath, $SecurityAttributes)
... [System.Runtime.InteropServices.Marshal]::FreeHGlobal($newPath)
... }
...
... $res
... }</dev:code>
        <dev:remarks>
          <maml:para>This is like the first example but the `$Pathname` is coming in as a raw `IntPtr`. This `IntPtr` can be passed along directly but it can also be converted back to a string using normal dotnet methods. In this example it will try to invoke the C function and have a fallback to prefix the path with `\?` if that fails.</maml:para>
        </dev:remarks>
      </command:example>
    </command:examples>
    <command:relatedLinks>
      <maml:navigationLink>
        <maml:linkText>Online Version:</maml:linkText>
        <maml:uri>https://github.com/jborean93/PSDetour/blob/main/docs/en-US/New-PSDetourHook.md</maml:uri>
      </maml:navigationLink>
    </command:relatedLinks>
  </command:command>
  <command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
    <command:details>
      <command:name>New-PSDetourSession</command:name>
      <command:verb>New</command:verb>
      <command:noun>PSDetourSession</command:noun>
      <maml:description>
        <maml:para>Creates a PSRemoting session to another process.</maml:para>
      </maml:description>
    </command:details>
    <maml:description>
      <maml:para>Creates a PSRemoting session to another process by injecting a running version of PowerShell into a new thread. This can be used to run commands remotely in any process and not just PowerShell.</maml:para>
      <maml:para>Due to the nature of how PSDetour hooks into the remote process, this is something that cannot be undone. Once a process has been tainted it will continue to run the PowerShell listener until the target process ends. See about_PSDetourSessions (./about_PSDetourSessions.md)for more information.</maml:para>
    </maml:description>
    <command:syntax>
      <command:syntaxItem>
        <maml:name>New-PSDetourSession</maml:name>
        <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="0" aliases="none">
          <maml:name>ProcessId</maml:name>
          <maml:description>
            <maml:para>The process to create the remote session to. This can either be the process id, name, or `Process` object. If specifying by string/name, only one process of that name must exist. If there is none or multiple then the cmdlet will output an error.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">ProcessIntString[]</command:parameterValue>
          <dev:type>
            <maml:name>ProcessIntString[]</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
          <maml:name>ApplicationArguments</maml:name>
          <maml:description>
            <maml:para>Any custom arguments to set in the remote session under `$PSSenderInfo.ApplicationArguments`. The keys must be a string and the values can only be primitive types like integers, strings, etc.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">PSPrimitiveDictionary</command:parameterValue>
          <dev:type>
            <maml:name>PSPrimitiveDictionary</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
          <maml:name>Name</maml:name>
          <maml:description>
            <maml:para>Custom name to call the remote runspace.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">String</command:parameterValue>
          <dev:type>
            <maml:name>String</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
          <maml:name>OpenTimeoutMS</maml:name>
          <maml:description>
            <maml:para>The timeout in milliseconds to wait until the session has been opened.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">Int32</command:parameterValue>
          <dev:type>
            <maml:name>Int32</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
      </command:syntaxItem>
    </command:syntax>
    <command:parameters>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
        <maml:name>ApplicationArguments</maml:name>
        <maml:description>
          <maml:para>Any custom arguments to set in the remote session under `$PSSenderInfo.ApplicationArguments`. The keys must be a string and the values can only be primitive types like integers, strings, etc.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">PSPrimitiveDictionary</command:parameterValue>
        <dev:type>
          <maml:name>PSPrimitiveDictionary</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
        <maml:name>Name</maml:name>
        <maml:description>
          <maml:para>Custom name to call the remote runspace.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">String</command:parameterValue>
        <dev:type>
          <maml:name>String</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
        <maml:name>OpenTimeoutMS</maml:name>
        <maml:description>
          <maml:para>The timeout in milliseconds to wait until the session has been opened.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">Int32</command:parameterValue>
        <dev:type>
          <maml:name>Int32</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="0" aliases="none">
        <maml:name>ProcessId</maml:name>
        <maml:description>
          <maml:para>The process to create the remote session to. This can either be the process id, name, or `Process` object. If specifying by string/name, only one process of that name must exist. If there is none or multiple then the cmdlet will output an error.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">ProcessIntString[]</command:parameterValue>
        <dev:type>
          <maml:name>ProcessIntString[]</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
    </command:parameters>
    <command:inputTypes>
      <command:inputType>
        <dev:type>
          <maml:name>PSDetour.ProcessIntString[]</maml:name>
        </dev:type>
        <maml:description>
          <maml:para>The process can be passed in by input.</maml:para>
        </maml:description>
      </command:inputType>
    </command:inputTypes>
    <command:returnValues>
      <command:returnValue>
        <dev:type>
          <maml:name>System.Management.Automation.Runspaces.PSSession</maml:name>
        </dev:type>
        <maml:description>
          <maml:para>The PSSession object that can be used with `Invoke-Command`, `Enter-PSSession`, or other PSRemoting cmdlets. Make sure to use `Remove-PSSession` to shut down the session when it's no longer needed.</maml:para>
        </maml:description>
      </command:returnValue>
    </command:returnValues>
    <maml:alertSet>
      <maml:alert>
        <maml:para>Currently only x64 process targets are supported. ARM or x86 based processes will most likely fail and crash the target process. See Host Error Codes (https://github.com/dotnet/runtime/blob/main/docs/design/features/host-error-codes.md)for a list of return codes that may be used to debug hosting errors.</maml:para>
      </maml:alert>
    </maml:alertSet>
    <command:examples>
      <command:example>
        <maml:title>-------- Example 1 - Create a remote session to notepad --------</maml:title>
        <dev:code>PS C:\&gt; $session = New-PSDetourSsession -ProcessId notepad
PS C:\&gt; Enter-PSSession -Session $session</dev:code>
        <dev:remarks>
          <maml:para>Creates a PSSession to the process called `notepad` and create an interactive prompt for that session. Note: This will only work if there is only one process called `notepad`.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>---- Example 2 - Create a remote session to a process by id ----</maml:title>
        <dev:code>PS C:\&gt; $session = New-PSDetourSsession -ProcessId 1234
PS C:\&gt; Invoke-Command -Session $session -ScriptBlock { $pid }
PS C:\&gt; $session | Remove-PSSession</dev:code>
        <dev:remarks>
          <maml:para>Creates a PSSession to the process with the id `1234` and runs the `$pid` command in the session.</maml:para>
        </dev:remarks>
      </command:example>
    </command:examples>
    <command:relatedLinks>
      <maml:navigationLink>
        <maml:linkText>Online Version:</maml:linkText>
        <maml:uri>https://github.com/jborean93/PSDetour/blob/main/docs/en-US/New-PSDetourHook.md</maml:uri>
      </maml:navigationLink>
    </command:relatedLinks>
  </command:command>
  <command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
    <command:details>
      <command:name>Start-PSDetour</command:name>
      <command:verb>Start</command:verb>
      <command:noun>PSDetour</command:noun>
      <maml:description>
        <maml:para>Starts a detour session.</maml:para>
      </maml:description>
    </command:details>
    <maml:description>
      <maml:para>Starts a detour session with all the hooks defined in the current session. Use `New-PSDetourHook` to define the hooks to setup for the session. Once started, the detours will be in place until `Stop-PSDetour` is called.</maml:para>
    </maml:description>
    <command:syntax>
      <command:syntaxItem>
        <maml:name>Start-PSDetour</maml:name>
        <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="0" aliases="none">
          <maml:name>Hook</maml:name>
          <maml:description>
            <maml:para>The hooks from `New-PSDetourHook` to setup in the detour session.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">DetourHook[]</command:parameterValue>
          <dev:type>
            <maml:name>DetourHook[]</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
          <maml:name>State</maml:name>
          <maml:description>
            <maml:para>A custom object to inject into the running hooks accessible under `$this.State`. This can be any object that will be accessible in the hook context regardless of whether it is running in the same Runspace or a custom one. Alternatively, the `$using:var` syntax can be used which will force the hook to run in a new Runspace with the injected variable present.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">Object</command:parameterValue>
          <dev:type>
            <maml:name>Object</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
      </command:syntaxItem>
    </command:syntax>
    <command:parameters>
      <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="0" aliases="none">
        <maml:name>Hook</maml:name>
        <maml:description>
          <maml:para>The hooks from `New-PSDetourHook` to setup in the detour session.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">DetourHook[]</command:parameterValue>
        <dev:type>
          <maml:name>DetourHook[]</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
        <maml:name>State</maml:name>
        <maml:description>
          <maml:para>A custom object to inject into the running hooks accessible under `$this.State`. This can be any object that will be accessible in the hook context regardless of whether it is running in the same Runspace or a custom one. Alternatively, the `$using:var` syntax can be used which will force the hook to run in a new Runspace with the injected variable present.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">Object</command:parameterValue>
        <dev:type>
          <maml:name>Object</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
    </command:parameters>
    <command:inputTypes>
      <command:inputType>
        <dev:type>
          <maml:name>PSDetour.Commands.ScriptBlockHook[]</maml:name>
        </dev:type>
        <maml:description>
          <maml:para>The hook as input by value or by name.</maml:para>
        </maml:description>
      </command:inputType>
    </command:inputTypes>
    <command:returnValues>
      <command:returnValue>
        <dev:type>
          <maml:name>System.Object</maml:name>
        </dev:type>
        <maml:description>
          <maml:para>None</maml:para>
        </maml:description>
      </command:returnValue>
    </command:returnValues>
    <maml:alertSet>
      <maml:alert>
        <maml:para></maml:para>
      </maml:alert>
    </maml:alertSet>
    <command:examples>
      <command:example>
        <maml:title>-------------------------- Example 1 --------------------------</maml:title>
        <dev:code>PS C:\&gt; $hook | Start-PSDetour
PS C:\&gt; ... do stuff
PS C:\&gt; Stop-PSDetour</dev:code>
        <dev:remarks>
          <maml:para>Starts the detour session with the hooks specified and does work that should be hooked before stopping the session</maml:para>
        </dev:remarks>
      </command:example>
    </command:examples>
    <command:relatedLinks>
      <maml:navigationLink>
        <maml:linkText>Online Version:</maml:linkText>
        <maml:uri>https://github.com/jborean93/PSDetour/blob/main/docs/en-US/Start-PSDetour.md</maml:uri>
      </maml:navigationLink>
    </command:relatedLinks>
  </command:command>
  <command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
    <command:details>
      <command:name>Stop-PSDetour</command:name>
      <command:verb>Stop</command:verb>
      <command:noun>PSDetour</command:noun>
      <maml:description>
        <maml:para>Stops a PSDetour session and removes all active hooks.</maml:para>
      </maml:description>
    </command:details>
    <maml:description>
      <maml:para>Stops the active PSDetour session that was started by `Start-PSDetour`.</maml:para>
    </maml:description>
    <command:syntax>
      <command:syntaxItem>
        <maml:name>Stop-PSDetour</maml:name>
      </command:syntaxItem>
    </command:syntax>
    <command:parameters />
    <command:inputTypes>
      <command:inputType>
        <dev:type>
          <maml:name>None</maml:name>
        </dev:type>
        <maml:description>
          <maml:para></maml:para>
        </maml:description>
      </command:inputType>
    </command:inputTypes>
    <command:returnValues>
      <command:returnValue>
        <dev:type>
          <maml:name>System.Object</maml:name>
        </dev:type>
        <maml:description>
          <maml:para>None</maml:para>
        </maml:description>
      </command:returnValue>
    </command:returnValues>
    <maml:alertSet>
      <maml:alert>
        <maml:para></maml:para>
      </maml:alert>
    </maml:alertSet>
    <command:examples>
      <command:example>
        <maml:title>-------------------------- Example 1 --------------------------</maml:title>
        <dev:code>PS C:\&gt; Stop-PSDetour</dev:code>
        <dev:remarks>
          <maml:para>Stops the detour session.</maml:para>
        </dev:remarks>
      </command:example>
    </command:examples>
    <command:relatedLinks>
      <maml:navigationLink>
        <maml:linkText>Online Version:</maml:linkText>
        <maml:uri>https://github.com/jborean93/PSDetour/blob/main/docs/en-US/Start-PSDetour.md</maml:uri>
      </maml:navigationLink>
    </command:relatedLinks>
  </command:command>
  <command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
    <command:details>
      <command:name>Trace-PSDetourProcess</command:name>
      <command:verb>Trace</command:verb>
      <command:noun>PSDetourProcess</command:noun>
      <maml:description>
        <maml:para>Starts a PSDetour hook in either the current process or specified process and provides hook helpers for getting data back.</maml:para>
      </maml:description>
    </command:details>
    <maml:description>
      <maml:para>Can be used to easily start a hook session in the same or other process. The trace will stay alive until the target process has ended or a pipeline stop has been signaled through ctrl+c. The hook actions will have access to a special helper state that can be used to stream data back to the `Trace-PSDetourProcess` caller's cmdlet like `WriteObject`, `WriteVerbose`, etc. Keep in mind these objects will be serialized so should only be used for simple objects that are sent back to the caller. It also provides some PSHost integrations like `WriteLine` to write to the cmdlet's host.</maml:para>
      <maml:para>See PSDetour-Hooks (https://github.com/jborean93/PSDetour-Hooks)for a collection of hooks that are designed to be used with this cmdlet.</maml:para>
    </maml:description>
    <command:syntax>
      <command:syntaxItem>
        <maml:name>Trace-PSDetourProcess</maml:name>
        <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="0" aliases="none">
          <maml:name>Hook</maml:name>
          <maml:description>
            <maml:para>The hooks to load in the target process.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">DetourHook[]</command:parameterValue>
          <dev:type>
            <maml:name>DetourHook[]</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="Functions">
          <maml:name>FunctionsToDefine</maml:name>
          <maml:description>
            <maml:para>Common functions to define that the `$this.State` will have access to in the hook. These function scriptblocks can be access through `$this.State.GetFunction("Function-Name").</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">IDictionary</command:parameterValue>
          <dev:type>
            <maml:name>IDictionary</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="Process">
          <maml:name>ProcessId</maml:name>
          <maml:description>
            <maml:para>The target process to trace as either the process id, process name, or process object. If a process name is used and multiple processes are found with that name, the cmdlet will output an error. If not specified, the current process will be traced.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">ProcessIntString</command:parameterValue>
          <dev:type>
            <maml:name>ProcessIntString</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
      </command:syntaxItem>
    </command:syntax>
    <command:parameters>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="Functions">
        <maml:name>FunctionsToDefine</maml:name>
        <maml:description>
          <maml:para>Common functions to define that the `$this.State` will have access to in the hook. These function scriptblocks can be access through `$this.State.GetFunction("Function-Name").</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">IDictionary</command:parameterValue>
        <dev:type>
          <maml:name>IDictionary</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="0" aliases="none">
        <maml:name>Hook</maml:name>
        <maml:description>
          <maml:para>The hooks to load in the target process.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">DetourHook[]</command:parameterValue>
        <dev:type>
          <maml:name>DetourHook[]</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="Process">
        <maml:name>ProcessId</maml:name>
        <maml:description>
          <maml:para>The target process to trace as either the process id, process name, or process object. If a process name is used and multiple processes are found with that name, the cmdlet will output an error. If not specified, the current process will be traced.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">ProcessIntString</command:parameterValue>
        <dev:type>
          <maml:name>ProcessIntString</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
    </command:parameters>
    <command:inputTypes>
      <command:inputType>
        <dev:type>
          <maml:name>PSDetour.DetourHook[]</maml:name>
        </dev:type>
        <maml:description>
          <maml:para>The hook as input by value or by name.</maml:para>
        </maml:description>
      </command:inputType>
    </command:inputTypes>
    <command:returnValues>
      <command:returnValue>
        <dev:type>
          <maml:name>System.Object</maml:name>
        </dev:type>
        <maml:description>
          <maml:para>Any objects output by the hook's `State` object will be output here. These objects will be serialized so will not be "live" and will be a snapshot of the object that was sent from the hook.</maml:para>
        </maml:description>
      </command:returnValue>
    </command:returnValues>
    <maml:alertSet>
      <maml:alert>
        <maml:para>See PSDetour-Hooks (https://github.com/jborean93/PSDetour-Hooks)for a collection of various APIs that have been written to be used with this cmdlet.</maml:para>
      </maml:alert>
    </maml:alertSet>
    <command:examples>
      <command:example>
        <maml:title>----------- Example 1 - Hook API in current process -----------</maml:title>
        <dev:code>PS C:\&gt; $hook = New-PSDetourHook -DllName Kernel32 -MethodName GetCurrentProcessId {
... [OutputType([int])]
... param()
... $this.Invoke()
... }
PS C:\&gt; $hook | Trace-PSDetourProcess</dev:code>
        <dev:remarks>
          <maml:para>This hooks `GetCurrentProcessId` in the current process and will wait until `ctrl+c` is pressed.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>----------- Example 2 - Hook API in another process -----------</maml:title>
        <dev:code>PS C:\&gt; $hook = New-PSDetourHook -DllName Kernel32 -MethodName GetCurrentProcessId {
... [OutputType([int])]
... param()
... $this.Invoke()
... }
PS C:\&gt; $hook | Trace-PSDetourProcess -ProcessId lsass</dev:code>
        <dev:remarks>
          <maml:para>This hooks `GetCurrentProcessId` in the target process called `lsass` and will wait until `ctrl+c` is pressed.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>-------- Example 3 - Writing output back to the caller --------</maml:title>
        <dev:code>PS C:\&gt; $hook = New-PSDetourHook -DllName Kernel32 -MethodName GetCurrentProcessId {
... [OutputType([int])]
... param()
...
... $this.State.WriteObject(@{foo = 'bar'})
... $this.Invoke()
... }
PS C:\&gt; $hook | Trace-PSDetourProcess</dev:code>
        <dev:remarks>
          <maml:para>Will write the hashtable to the output pipeline of `Trace-PSDetourProcess` whenever the hooked method is called. Other functions like `WriteVerbose`, `WriteLine`, `ReadLine` can be used on the `State` object, see about_PSDetour (./about_PSDetour.md)for more information on what these methods are and what they can do.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>-------------- Example 4 - Stopping trace in hook --------------</maml:title>
        <dev:code>PS C:\&gt; $hook = New-PSDetourHook -DllName Kernel32 -MethodName GetCurrentProcessId {
... [OutputType([int])]
... param()
...
... $this.Invoke()
... $this.State.StopTrace()
... }
PS C:\&gt; $hook | Trace-PSDetourProcess</dev:code>
        <dev:remarks>
          <maml:para>Hooks the first `GetCurrentProcessId` call and stops the trace once called.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>------------- Example 5 - Define common functions -------------</maml:title>
        <dev:code>PS C:\&gt; Function My-Function {
... "output"
... }
PS C:\&gt; $hook = New-PSDetourHook -DllName Kernel32 -MethodName GetCurrentProcessId {
... [OutputType([int])]
... param()
...
... Set-Item -Path Function:My-Function -Value $this.State.GetFunction("My-Function")
... $this.State.WriteObject((My-Function))
...
... $this.Invoke()
... }
PS C:\&gt; $hook | Trace-PSDetourProcess -FunctionsToDefine @{"My-Function" = ${function:My-Function}}</dev:code>
        <dev:remarks>
          <maml:para>Registers the function `My-Function` which can be redefined in the hook scope through `$this.State.GetFunction`. The function can then be called just like any other PowerShell function.</maml:para>
        </dev:remarks>
      </command:example>
    </command:examples>
    <command:relatedLinks>
      <maml:navigationLink>
        <maml:linkText>Online Version:</maml:linkText>
        <maml:uri>https://github.com/jborean93/PSDetour/blob/main/docs/en-US/New-PSDetourHook.md</maml:uri>
      </maml:navigationLink>
      <maml:navigationLink>
        <maml:linkText>PSDetour-Hooks</maml:linkText>
        <maml:uri>https://github.com/jborean93/PSDetour-Hooks</maml:uri>
      </maml:navigationLink>
    </command:relatedLinks>
  </command:command>
</helpItems>