Windows.Detection.PipeHunter

Takes a pipe name and returns the owning process and access rights. The primary motivation for this artifact is a vulnerability in RemCom. RemCom is most notably used by impacket psexec.py. It creates a null DACL for its communication pipe. This means a low privileged user could use a stale pipe to get remote execution as SYSTEM. If you uncover any named pipes with the name RemCom_communication, investigate the owning proc and remove it from the system. #impacket


name: Windows.Detection.PipeHunter
author: ACEResponder.com
description: |
   Takes a pipe name and returns the owning process and access rights. The primary
   motivation for this artifact is a vulnerability in RemCom. RemCom is most 
   notably used by impacket psexec.py. It creates a null DACL for its 
   communication pipe. This means a low privileged user
   could use a stale pipe to get remote execution as SYSTEM. If you uncover any
   named pipes with the name RemCom_communication, investigate the owning proc
   and remove it from the system.
   #impacket

reference:
  - https://twitter.com/bugch3ck

parameters:
  - name: pipe_name
    default: "RemCom_communicaton"

sources:
  - precondition:
      SELECT OS From info() where OS = 'windows'

    query: |
        LET ps = '''Add-Type -TypeDefinition  @"
            using System;
            using System.Diagnostics;
            using System.Runtime.InteropServices;
        
            public static class Kernel32
            {
                [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
                public static extern IntPtr CreateFile(
                      string filename,
                      System.IO.FileAccess access,
                      System.IO.FileShare share,
                      IntPtr securityAttributes,
                      System.IO.FileMode creationDisposition,
                      uint flagsAndAttributes,
                      IntPtr templateFile);
                [DllImport("kernel32.dll", SetLastError = true)]
                public static extern bool GetNamedPipeServerProcessId(IntPtr hPipe, out int ClientProcessId);
            
                [DllImport("kernel32.dll", SetLastError=true)]
                public static extern bool CloseHandle(IntPtr hObject);
            }
        "@
        $remcom=$null
        $pipeOwner=0

        try {
          #gci directly on the pipe does not work in some versions of posh for some reason
          $remcom = Get-ChildItem -ErrorAction Stop \\.\pipe\ -Filter '''
        LET ps2='''
          $output = New-Object PSObject -Property @{
            ProcessId         = $null;
            ProcessName       = $null;
            NamedPipe         = $remcom.FullName;
            AccessControlType = $null;
            IdentityReference = $null;
          }
          try {
            $acl = $remcom.GetAccessControl();
            $output.AccessControlType = $acl.Access.AccessControlType;
            $output.IdentityReference = $acl.Access.IdentityReference.Value;
          }
          catch {
          }
          $hPipe = [Kernel32]::CreateFile($remcom.FullName, [System.IO.FileAccess]::Read, [System.IO.FileShare]::None, [System.IntPtr]::Zero, [System.IO.FileMode]::Open, [System.UInt32]::0x80, [System.IntPtr]::Zero);
          $pipeOwnerFound = [Kernel32]::GetNamedPipeServerProcessId([System.IntPtr]$hPipe, [ref]$pipeOwner);
          if ($pipeOwnerFound) {
            # Now that we have the process id, Get process name
            $processName = Get-WmiObject -Query "SELECT Caption FROM Win32_Process WHERE ProcessID = $pipeOwner" | select -ExpandProperty Caption;
                    
            # Add to the name and ID to output
            $output.ProcessID = $pipeOwner;
            $output.ProcessName = $processName;
        
          }
          if($output.NamedPipe){
            $output | ConvertTo-JSON
          }
          #close the handle to the pipe
          $closed = [Kernel32]::CloseHandle($hPipe);
        
        }
        catch {
          write-host $_;
        }
        
        '''

        SELECT * FROM execve(argv=["Powershell", "-ExecutionPolicy",
            "unrestricted", "-c", ps+pipe_name+ps2])