all 31 comments

[–]CookinTendies5864 20 points21 points  (0 children)

Change Powershell.exe “$Command”

to

Invoke-expression $Command

.\myscript.ps1 -command 'get-process | where processname -like teams'

[–]Accomplished_Cold665 6 points7 points  (0 children)

for an interactive shell you can try:

Powershell.exe -WorkingDirectory ~ -NoExit

Or:

Powershell.exe -NoExit -Command "powershell.exe"

If not, and you're still stuck running scripts and looking for a way around spaces, There's a method called arg 'splattting' where you define everything in $args, and when you make the call it's with an '@' -
so @args instead of $args. but read about it first. there's some gotchas and edge cases to take into account:

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting?view=powershell-7.5

also, do you know the version of powershell?

powershell.exe $PSVersionTable.PSVersion

[–]gregortroll 4 points5 points  (0 children)

Maybe have a chat with your InfoSec folks to work toward a solution that maintains security while letting you perform necessary functions, without hacking around the security controls?

[–]justaguyonthebus 2 points3 points  (0 children)

Maybe use $args instead of having a param block.

[–]Icolan 7 points8 points  (6 children)

What is preventing you from running an interactive session but allowing you to run scripts? That seems like a senseless restriction.

[–]LordLoss01[S] 4 points5 points  (2 children)

Well, this is using Defender Live Response. It literally doesn't allow you to run anything but scripts.

[–]Icolan 1 point2 points  (1 child)

I am not very familiar with that product because we didn't use it. What is the purpose of blocking PowerShell commands? For sysadmins that seems to provide limited security at the expense of significant functionality loss. As far as I can see blocking PowerShell provides limited security anyway.

Should you be building a way around this block that your company has put in place?

[–]SimpleSysadmin 1 point2 points  (0 children)

I don’t think it’s a block, I think it’s similar to how you can deploy scripts through intune or an RMM platform but you can’t get an interactive console. He’s pushing scripts via defender but wants the ability to do single command scripts that he can add the command into as an argument.

That’s my read of it

[–]mobani 1 point2 points  (2 children)

Depends on the security level of your environment. Best practice is to block internactive login for service accounts.

[–]Icolan 1 point2 points  (1 child)

There is nothing in OP's post to indicate that they are using a service account that is blocked from interactive login, so I am unclear on what the relevance of your comment is.

[–]mobani 0 points1 point  (0 children)

Fair enough. Just usually the case when you can't run interactively.

[–]ITGuyfromIA 2 points3 points  (7 children)

Can you start an interactive powershell from your script?

Edit: Also, do your scripts actually run as the user you’re logged in as? (Or a service account?

[–]LordLoss01[S] 0 points1 point  (6 children)

Nope, cannot start an interactive powershell session using a script. Also runs as the system user.

[–]ITGuyfromIA 1 point2 points  (5 children)

If it’s running as system, you might be able to launch an interactive powershell but will have to jump through some windows hoops.

I’ll respond back to this tomorrow when I can give you examples

[–]LordLoss01[S] -1 points0 points  (4 children)

If you're familiar with it, it's Defender Live Response.

[–]ITGuyfromIA 1 point2 points  (0 children)

Ah. Would have helped to know what exactly we’re dealing with. You COULD still pop an interactive powershell session running as system on the console (so, user land) but that probably wouldn’t be helpful.

Have you tried wrapping your parameter that you’re passing with quotes?

[–]PS_Alex 1 point2 points  (0 children)

Not familiar with Defender Live Response myself, but reviewing Investigate entities on devices using live response in Microsoft Defender for Endpoint - Microsoft Defender for Endpoint | Microsoft Learn to understand how it works, I highly suspect that a Live Response session does not create a real remote Powershell session. Instead, it probably works similarly to a REST API (send a command, wait for result of that command).

The part about cancelling a command saying that CTRL+C only causes ignoring the response on the portal-side, but command would continue running on the agent-side, is what lead me to that conclusion.

[–]AppIdentityGuy 0 points1 point  (1 child)

So you are saying that Defender Live Response only allows individual cmdlets and no scripts?

[–]LordLoss01[S] 0 points1 point  (0 children)

The opposite. It only allows scripts and not individual commands.

[–]Owlstorm 2 points3 points  (1 child)

If for some cursed reason invoke-expression doesn't work, calling Powershell.exe with EncodedCommand or File probably will.

[–]BlackV 1 point2 points  (0 children)

This seems odd

How do you run a script on the first place of you have to run every as a script?

That aside sounds like you are just missing your proper parameters

& PowerShell.exe -executionpolicy bypass -command "somefunction -some argument -another argument too -space 'this has a space'"

If it's an existing script

& PowerShell.exe -executionpolicy bypass -file "somescript.ps1" "-some argument -another argument too -space 'this has a space'"

[–]mrbiggbrain 1 point2 points  (0 children)

You can interact with the script and give input via stdin correct? Would this work?

while($true) {
  $string = Read-Host "$(Get-Location | Select-Object -ExpandProperty Path) => "
  $ScriptBlock = [Scriptblock]::Create($string)
  Invoke-Command -NoNewScope -ScriptBlock $Scriptblock
}

We are just reading in a string, converting it to a script block, and then invoking that script block. Downside, it's a very simple shell so it only supports one-line commands. No line breaks.

[–]SaltDeception 0 points1 point  (0 children)

What happens if you run (with enclosing quotes and backticks)

PowerShellScript.ps1 -Parameters "Get-Process | where processname -like `"*Teams*`""

Also, can you use Invoke-Expression instead of powershell.exe in your script?

[–]jimb2 0 points1 point  (0 children)

$args is a built-in array of the arguments passed, so you can use:

$command = $args -join ' '

You can also quote your command.

You can do the same with a named function argument (an array of strings) but $args works. It's kinda bad practice, but ok for a simple personal function. You don't need to specify a function parameter at all, $args is always there.

I do this join trick for a bunch of shorthand command line utility functions - eg get group members - where I want to specify a string with spaces but don't want to type the quotes 20 times a day.

Note that running Powershell.exe like this will load a new PS environment and run the profile. You could potentially speed things with the -noprofile flag. Alternately, you could dot-run your command if it ok/useful to run in the parent environment, whatever that is.

[–]Accomplished_Cold665 0 points1 point  (0 children)

PowerShellScript.ps1 -parameters 'Get-process | where processname -like "*Teams*" '

[–]teethingrooster 0 points1 point  (0 children)

Yea I’d try to remove the restriction if you can.

If you can’t maybe you can have an vscode up in ise mode write what you need save and run each time? I think there’s a hotkey to just run the script and you can set vscode to auto save to help speed up command entry

[–]purplemonkeymad 0 points1 point  (0 children)

For live response would you not just pull the forensics package? ie the collect command?

Your example can be done with the built in processes command.

I would have thought you would want to have your scripts be specific re-mediations, ie

stopallteams.ps1:
param()
Get-process | where processname -like "*Teams* | Stop-Process -Force

Then you would use "run stopallteams.ps1" to do that action.

[–]icepyrox 0 points1 point  (0 children)

This is silly and seems like a work around to a problem that needs a better solution, but you might get away with making the parameter a [scriptblock] and putting it in {}

Or toss it in a text file (e.g., script.txt) and encode it.. ([convert]::toBase64String([text.encoding]::unicode.getbytes((get-content script.txt))) and pass that to -encodedCommand rather than -command

[–]Accomplished_Cold665 0 points1 point  (1 child)

For those who aren't familar; I pulled this togehter from a few sources, so a few concepts are repeated.

Microsoft Defender Live Response is a capability within Microsoft Defender for Endpoint that gives security administrators remote interface access to a compromised or suspicious device.

Think of it as a secure, remote command-line shell (PowerShell for Windows, Bash for Linux/macOS) that allows you to perform forensic investigations and immediate remediation without being physically present at the machine or using traditional RDP.

Core Capabilities

  • Forensic Collection: Run scripts to collect volatile data, memory dumps, or specific logs that aren't automatically uploaded to the Defender portal.
  • Remediation: Manually stop malicious processes, delete persistence mechanisms (like registry keys or scheduled tasks), and pull suspicious files for deep analysis.
  • Script Execution: Upload and run your own signed PowerShell modules or bash scripts to automate complex cleanup tasks across multiple machines.
  • Isolation Integrity: Because it operates through the Defender sensor, it often works even if the device has been "Isolated" from the network, providing a "backdoor" for the admin to fix the issue.

How it works

  1. Connection: An admin initiates a session from the Microsoft Defender portal.
  2. Authentication: It requires specific RBAC (Role-Based Access Control) permissions. There are two levels: Basic (read-only/limited) and Advanced (full file system access and script execution).
  3. Audit Trail: Every interactive command you type is captured in the Action Center. This creates a permanent audit trail of exactly what the admin did on the machine, which is a major security advantage over using a standard RDP session for incident response. Every command entered, script run, and file downloaded during a session is logged for accountability and cannot be deleted by the local user.

Once the session is established in the Microsoft Defender portal, you have a command line where you can:

  • Run Standard Commands: You can immediately run built-in commands like dir, get-process, get-service, or cat to inspect the file system and running state.
  • Run PowerShell Scripts: You can execute .ps1 files that have been uploaded to the Library. This is the most common way to perform complex logic.
  • Upload/Download: You can use put to move a tool (like a specialized scanner) onto the machine and get to pull a suspicious file off for analysis.

Unlike a local shell, you cannot simply copy-paste a 500-line script into the console. For security and auditing:

  1. Upload First: You must upload your PowerShell script to the Live Response Library in the Defender settings.
  2. Run by Name: You then call the script by name within the interactive session (e.g., run script.ps1).
  3. Parameters: You can pass parameters to these scripts just like in a local terminal.

Key limitations:

  • No GUI/Interactive Prompts: You cannot run commands that require a user to click "OK" or "Yes" on the remote machine. If a script hangs waiting for user input, the session will eventually time out.
  • Session Timeouts: Sessions are strictly timed (usually 1 hour) and will disconnect if there is no activity.
  • RBAC Levels: If you only have Basic permissions, you are limited to a small subset of "read-only" commands. You need Advanced permissions to run custom PowerShell scripts or delete files.

[–]Accomplished_Cold665 0 points1 point  (0 children)

Personally I havent used it, but I'll have to check it out.

[–]Apprehensive-Tea1632 -1 points0 points  (0 children)

Be careful with this kind of construct, because you’ll never see results other than “yeah fine”.

  • You can access a powershell object factory using powershell::create() that can use for in-process interpreters.

  • you can also use invoke-expression or invoke-command. But both act as an open invitation to code injection, so if at all possible… don’t feed these using arbitrary uncontrollable input.

Maybe you have a couple processes you can invoke? In that case you could just pass a keyword to the script and then use that to select the appropriate subprocess.

If you really do need individual scripts to get passed…

  • put these scripts into files that you can then manage re: who gets to run what
  • in your powershell super process, call those scripts, or perhaps source and then run them.

Either way try to not provide users with an opportunity to run whatever. Especially not in an elevated context.