Powershell & Plink - How to capture the message "Access Denied"

2.6k Views Asked by At

I have a list of ips in a text file. The script reads the list of ips and attempts a connection to each of the ips. This part is working.

When the script finds an IP that does not have access to the user some messages are returned. I want to capture the string "Access denied" to create a list of ips that do not have access to the my user.

    PS X:\PATH\USER> .\script.ps1
    XXX.XXX.XXX.XXX
    Access denied
    Access denied
    Access denied
    Access denied
    Access denied
    FATAL ERROR: Server sent disconnect message
    type 2 (protocol error):
    "Too many authentication failures for XXXX"
    Using username "XXXX".
    Access denied

Inside the file (ips.txt) contains:

    xxx.xxx.xxx.xx1
    xxx.xxx.xxx.xx2
    xxx.xxx.xxx.xx3
    xxx.xxx.xxx.xx4
    .
    .
    .
    xxx.xxx.xxx.xxn

The script.ps1

    $ipsarray=(get-content ips.txt)
    $size=(get-content ips.txt).Length

    Function Invoke-SSHCommands {
        Param($Hostname,$Username,$Password, $CommandArray, $PlinkAndPath, $ConnectOnceToAcceptHostKey = $true)

        $Target = $Username + '@' + $Hostname

        $plinkoptions = "-ssh $Target -pw $Password"

        $CommandArray += "exit"
        $remoteCommand = ""

        if($ConnectOnceToAcceptHostKey)
        {
            $PlinkCommand  = [string]::Format('echo y | & "{0}" {1} exit', $PlinkAndPath, $plinkoptions )
            $msg = Invoke-Expression $PlinkCommand
        }

        $PlinkCommand = [string]::Format('& "{0}" {1} "{2}"', $PlinkAndPath, $plinkoptions , $remoteCommand)
        $msg = Invoke-Expression $PlinkCommand
    }

    $PlinkAndPath = "XXXX\plink.exe"
    $Username = "XXX"
    $Password = "XXX"

    for ($i=0; $i -lt $size; $i++) {
        $Hostname=$ipsarray[$i]
        Write-Host $Hostname
        Invoke-SSHCommands -User $Username -Hostname $Hostname -Password $Password -PlinkAndPath $PlinkAndPath -CommandArray $Commands
    }      

Hi David. I changed the code inside the repeating structure for

for ($i=0; $i -lt $tamanho; $i++) {
  $Hostname=$vetor[$i]
  Write-Host $Hostname
  $response = Invoke-SSHCommands -User $Username -Hostname $Hostname -Password $Password -PlinkAndPath $PlinkAndPath -CommandArray $Commands

  if ($null -ieq $response) {
    write-host "EMPTY"
  }
  else {
    write-host $response
  } 
}

This line is interacting with the operating system. I do not see how to capture what it is returning. The response is sent to the terminal, in other words, does not return to the script.

$response = Invoke-SSHCommands -User $Username -Hostname $Hostname -Password $Password -PlinkAndPath $PlinkAndPath -CommandArray $Commands

The following conditional is always EMPTY

  if ($null -ieq $response) {
    write-host "EMPTY"
  }
  else {
    write-host $response
  } 

I changed the if statement to check the type of the variable

if ($null -ieq $response) {
  $response.GetType().Name
  write-host "EMPTY"
}

The result of the variable $response is always null

You can not call a method on a null expression.
X:\PATH\USER\script.ps1:xx caractere:xx
+     $response.GetType <<<< ().Name
+ CategoryInfo          : InvalidOperation: (GetType:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Now I decided to test what would be the result returned by the variable $msg and changed lines of code to:

$msg = Invoke-Expression $PlinkCommand
return $msg

Example of the loop(for) changed to test the return of the variable $msg.

for ($i=0; $i -lt $tamanho; $i++) {
  $Hostname=$vetor[$i]
  Write-Host $Hostname
  $response = Invoke-SSHCommands -User $Username -Hostname $Hostname -Password $Password -PlinkAndPath $PlinkAndPath -CommandArray $Commands

  if ($null -eq $response) {
    write-host "NULL"
  }
  else {
   write-host $response
  } 
}

Example of what is displayed in the if, after the function call. Never return "Access denied"

[email protected]'s password:  [email protected]'s password:  [email protected]'s password:  [email protected]'s password:  [email protected]'s password:
3

There are 3 best solutions below

2
On

I haven't tried your code, but presumably, the response is captured by your variable $msg, so it seems you need to add a return statement to your function, e.g.

return $msg

Then you need to do something with that return in your main program, e.g.

for ($i=0; $i -lt $size; $i++) {
    $Hostname=$ipsarray[$i]
    Write-Host $Hostname
    $response = Invoke-SSHCommands -User $Username -Hostname $Hostname -Password $Password -   PlinkAndPath $PlinkAndPath -CommandArray $Commands
    # Do something here with $response
}   
0
On

A little late to answer this, but I ran into the same problem.

You'd want to capture the std error (2). Currently you are probably only capturing std out (1) in $msg.

You could try adding 2>&1 to add std err to the output

$msg = Invoke-Expression $PlinkCommand 2>&1

Unfortunately in my experience this doesn't catch the FATAL ERROR though.

0
On

I have same problem. Unfortunatly i find out that: "Transcripts don’t capture any output from EXEs." This is old post from https://rkeithhill.wordpress.com/2007/09/16/effective-powershell-item-7-understanding-output/ but i think it is still actual.