News for hackers. Stuff that matters.
Re:Stronger Shell by useerup on Wednesday August 12, 2015 @02:35PM (#10049714)
Using the non-aliased verbose form of the cmdlets:

    $hosts = 'host1','host2','host3'
    $source = '\\host0\c$\source'
    $dest = 'c:\dest'
    $executable = 'C:\Program Files (x86)\Notepad++\notepad++.exe'

    Invoke-Command -Computer $hosts -ScriptBlock { 
        Get-Process | Where-Object Path -eq $using:executable | Stop-Process -Force
        Copy-Item -Path $using:source -Destination $using:dest
    }
Explanation:

Line 1-4: Set up variables to make the script more explanatory. Line 1 defines an array (the "," operator)

Line 6: Invoke-Command takes an array of (remote) hosts (the -Computer parameter) to execute the script block (the -ScriptBlock parameter).

Lines 7-9: The script to execute at each host simultaneously (the Invoke-Command executes the scripts in parallel at each host)

Line 7: Get the process list (Get-Process), pipe through the filter (Where-Object) which selects only the process(es) executing the desired executable, pipe those processes to the Stop-Process cmdlet which will forcably stop the process.

Line 8: Copy files from the desired source at an UNC path to the local machine at the destination

Now, the above script was the canonical way, using the long form. For casual scription, I could have written just this:

    $hosts = 'host1','host2','host3'
    $executable = 'C:\Program Files (x86)\Notepad++\notepad++.exe'
    icm $hosts { ps | ? Path -eq $using:executable | kill -f; cp \\host0\c$\source c:\dest }
Re:Stronger Shell by warfangle on Wednesday August 12, 2015 @02:54PM (#10049837)
While likely to work (I don't use powershell), I think you missed the main constraint posed: kill a running GUI with a certain name.

Your solution finds the process to kill only if the executable path is at a known location.

How would you do this if you only know what the process name will be -- e.g., what if the executable path is on D:\stuff\gui.exe on host1 and E:\secretstuff\gui.exe on host2, if gui.exe always runs as a process named "Updatable GUI Thing"?

Re:Stronger Shell by useerup on Wednesday August 12, 2015 @03:22PM (#10050021)
Silly me, I assumed that the executable path was the requirement. My bad. If you need to find a process just by it's name, it is even simpler: Just indicate the process name (possibly with wildcards) to Get-Process (alias ps):

ps Notepad++ | kill

Actually, kill (alias for Stop-Process) takes a name parameter directly, so the "kill" line from the script could be written as simply

kill notepad++

But your question is actually really good, because what if we did not know the neither the process name nor the executable, but -say- only the Window title? Get-process (alias ps) will produce a sequence objects describing the running processes. If I want to know what properties those objects have that I can possibly filter on, I can pipe the objects through the Get-Member cmdlet (alias gm):

    ps | gm
This produces a table-formatted list like this (shortened):

    TypeName: System.Diagnostics.Process

    Name                       MemberType     Definition
    ----                       ----------     ----------
    Handles                    AliasProperty  Handles = Handlecount
    Name                       AliasProperty  Name = ProcessName
	...
    MainModule                 Property       System.Diagnostics.ProcessModule MainModule {get;}
    MainWindowHandle           Property       System.IntPtr MainWindowHandle {get;}
    MainWindowTitle            Property       string MainWindowTitle {get;}
    MaxWorkingSet              Property       System.IntPtr MaxWorkingSet {get;set;}
	...
    Site                       Property       System.ComponentModel.ISite Site {get;set;}
    StandardError              Property       System.IO.StreamReader StandardError {get;}
    StandardInput              Property       System.IO.StreamWriter StandardInput {get;}
    StandardOutput             Property       System.IO.StreamReader StandardOutput {get;}
    StartInfo                  Property       System.Diagnostics.ProcessStartInfo StartInfo {get;set;}
	...
    Product                    ScriptProperty System.Object Product {get=$this.Mainmodule.FileVersionInfo.ProductName;}
    ProductVersion             ScriptProperty System.Object ProductVersion {get=$this.Mainmodule.FileVersionInfo.ProductVersion;}

Lo and behold, there is a property called MainWindowTitle. So to stop a process by it's main window title I could write:

    ps | ? MainWindowTitle -eq 'Deepthought Main Console' | kill
That is, find all processes, pipe them through a filter selecting only those where the MainWindowTitle equals the desired text, and pipe those processes to the Stop-Process cmdlet
Re:Stronger Shell by felixgallo on Wednesday August 12, 2015 @08:29PM (#10051644)
hey, this was a pretty good try! But here's what else you need to do:

https://rkeithhill.wordpress.com/2009/05/02/powershell-v2-re...

and if that's not hair-raisingly terrifying enough (note the super-intuitive 'set-item wsman://...' call), you'll quickly find that when you start a program (which you left off) using a script remotely, it doesn't show up anywhere on-screen, despite being authenticated as the logged-in user, but it does show up in the process list. Guess why THAT is.

There are some pretty parts to PS; but they fall apart, at the touch, instantly, like fairy buildings made of dew.

Re:Stronger Shell by useerup on Thursday August 13, 2015 @07:43AM (#10053433)
> hey, this was a pretty good try! But here's what else you need to do:

No I don't. To open up a machine for remote administration, all I have to do is run Enable-PSRemoting like so:

    Enable-PSRemoting -Force
For domain-joined machines the authentication from there is just automatic, -i.e. when I use Invoke-Command it automatically created an authenticated and encrypted connection for the duration of the script execution.

> you'll quickly find that when you start a program (which you left off) using a script remotely, it doesn't show up anywhere on-screen, despite being authenticated as the logged-in user, but it does show up in the process list. Guess why THAT is.

That has nothing to do with PowerShell and everything to do with your expectation that you have equally poor session separation as with your typical nix.

With sufficient rights you can of course stop any process. But to reach in and control another user session is something else.

On Windows, processes are separated not just by the account they run under, but also by the session* under which they are created. Security barriers prevents a process in one session from interacting with processes in another session, even if they run as the same user.

This security boundary was raised to prevent compromised user processes from reaching into services and vice versa. This is part of the protection against shatter attacks and more.

I know a utility like psexec (sysinternals) may be able to launch a process in a foreign session, but I'm honestly not sure how it achieves this without some kernel support.

> but it does show up in the process list. Guess why THAT is.

That is because when you launch a process is launches in your session. A session is associated with a Windows Desktop (an operating system object type) which is a namespace separation somewhat like cnames in Linux. Windows on your (remote) session lives on the non-visible desktop associated with that session. When you log off it destroys the session and any processes running under the session.

You may not agree with the extra security features built into Windows, but the separation they create has noting to do with PowerShell.