Shadowing RDP session automatically - powershell

I want to create a powershell script. One of our supporting companies needs to connect to our server from time to time to make their work and I need to connect their RDP session to watch them if their doing is OK.
Server: MS Server 2012 R2 x64
The case is I want to create a script which;
1- Checks the server's current sessions
2- Finds the specific session ID come from the username (the which I will give them to connect) currently logged in as RDP
3- When I pull the correct session ID from the username (and that means he is currently online and connected), I want to shadow his/her session without prompting/requesting their approvals.
Yes, I can do these separately but looking a powershell script or something like that to these. In one attempt, I want to shadow rdp to correct session and if he/she is not online, I want the system return an information message to me that the username is not currently online.
Is it possible?
Thanks&Regards
Melih

If memory serves PoSh does not natively supports querying RDP sessions (unless using the RDS broker, but I could be wrong here) but you can easily do that via query session
I cannot test it right now but something like this should do the trick:
C:\>query session
SESSIONNAME USERNAME ID STATE TYPE DEVICE
console Administrator1 0 active wdcon
rdp-tcp#1 User1 1 active wdtshare
rdp-tcp 2 listen wdtshare
You can even call it with the username directly if that is known to you.
Shadowing the session would be easily accomplished with something like
mstsc /v:"$srv" /shadow:"$id" /control /noconsentprompt
I did not test this so maybe it needs some tweaking but a possible starting point could be
$userSessions = query session user01 /SERVER:server01 | Select-Object -skip 1 | ForEach-Object{$_.Split(' ',[System.StringSplitOptions]::RemoveEmptyEntries)}
$sessionId = $userSessions[2]
mstsc /v:"$srv" /shadow:"$sessionId" /control /noconsentprompt
Of course if running from the local server you can omit the /SERVER:XXX argument.
Hope this can help getting you started.

Related

Connect to an existing session in Powershell by its id

For a really specific use, i need to connect to an existing session which have a opened desktop (with gui). To maintain the gui, we opened the session with rdp and already use a powershell script which transform the rdp session into a console session (without exiting gui since the session technicaly stay open).
Before, I used psexec with the -i parameter set (I got the session's Id by the username) but now, I'm trying to do the same with pure powershell.
Any thought?

Get-NetFirewallRule User{GIUD}

We are having a problem with our Windows 10 computers either not adding all of the Firewall rules from GPOs when the computer restarts or somewhere along the line.
We have multiple users that log onto the consoles (usually with a roaming profile) and a small percentage of them throw a firewall exception when trying to open necessary apps that should have been allowed through GPOs.
My questions are:
1.) Why is this happening?
2.) How to get information about the "USER" GUID that is returned from Get-NetFirewallRule?
Get-NetFirewallRule -Action Block
One partial result is:
TCP Query User{E2507D53-3CCE-4791-8BBF-9830003E90C5}
So how do i get information about this guid (E2507D53-3CCE-4791-8BBF-9830003E90C5)?
3.) Also, some of the computers that have this issue also block PSRemoting so I cannot fix this issue remotely, which is just as bad as the other issue!
Any ideas?
Thank you
PS: I have searched high and low for info about that GUID. It has become a personal goal to resolve the guid to an object name at this point.
So what is happening is when Windows prompts you for a application to create a firewall exception (even if you hit cancel), 2 rules are created by windows.
TCP Query User and UDP Query User
The rules are stored in the registry under the path HKLM\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\FirewallRules
You might have this prompt with many applications. Which would mean the same name would be created over and over again. The GUID is just so that there is a unique name per application attempt.

Run powershell script as logged in user

Let's say I am logged into a server using "user1".
I have a project where the powershell process runs under "user2".
So every time I execute a script it will be under "user2".
Is there a way to specify powershell to run a certain script under "user1" without prompting for credentials (like mentioned before I'm already logged in as that user)?
Thanks in advance!
No, there is not a way to do this.
The process is running under the context of user2, it cannot run anything in the context of user1 without giving it user1 credentials. As you may be able to imagine if there were a way to do that, it would be a pretty significant security vulnerability.
Bonus Information
If however, you are looking to do something like open a web page as user1 from a process running as user2, you can do so by passing the http/https protocol to the user session IIRC. However, this is only if the process running as user2 is running in the user1 session.
For example:
Logged in to a console session as User1
Powershell Process running under User2 context, within the User1 session
Within the Powershell process, run start-process http://www.google.com
Default http application opens the URL in the User1 session

Inconsistent query on remote mapped drives

I used below Powershell script to check the mapped drives on remote PCs.
Some PC gives the desired result but some does not.
Get-WmiObject Win32_MappedLogicalDisk -computer HW059 | select name, providername
The account I am using got the same administrator right on all the PCs so I don't think the issue is due to the user privilege.
I am wondering if there is any services need to be started / relevant to the script?
I checked that WMI service is running on all the PCs.
Sorry that I am new to scripting.
Would someone please help?
Powershell result
Mapped drives are feature of user session, they do not exist by default on a system. Even if all users would have same disk mapped (i.e. S: mapped to \\server\share), S: would not exist there if there is no logged in user.
Please see remarks from MSDN (you are user A in description below)
The instances returned for this class are as follows, supposing that user A is enumerating the instances:
The provider looks for a logon session of user A on that machine: If there is one (and only one) such logon session, then the provider returns the mapped drives of that session. If there is more than one session for user A on the machine, then no mapped drive instances are returned (because the provider has no reasonable way of deciding which session to use).
If there are no sessions of user A running, and there is a locally logged on user B:
If there is a single session for user B, then the provider impersonates A and returns the mapped drives of user B. This case supports the scenario of Helpdesk wanting to see the instances of a locally logged on user. However, whether instances are returned depends on the Local Security Policy settings in the Control Panel Administrative Tools. If the following policy is set to "Object Creator", then no mapped drive instances are returned, even if A is a member of the Administrators group: "System object: default owner for objects created by members of the administrators group." Again, if there is more than one session of user B running on the machine, then the provider has no way of deciding which to use. In this case, no mapped drive instances are returned.

Modify Active Directory Client OU from Client Machine

I am trying to create a powershell startup script for my domain controlled computers that will place the computer into the the specified OU. I would like for the variables to be taken on the local computer and then passed to the remote server. Once there I would like to execute the last two lines on the server.
The script below does work if it is ran on the server however as stated above I would like to be able to execute this from a client machine. How can I make this happen?
$computername = $env:ComputerName
$new_ou = "OU=TestOU,DC=Test,DC=Controller,DC=com"
Import-Module ActiveDirectory
Get-ADComputer $computername | Move-ADObject -TargetPath $new_ou
Note: Before anyone asks...my goal is to have the OU be determined by the client IP address. I understand that there are scripts that will do the discribed above but they run strictly on the server and query the DNS. I would rather have this run as a startup script on the local computer so I an better control which computers are being moved. At this point I am not interested in tackling this issue. Only the issue of how to execute the above lines on a local machine.
I assume you want to run the last 2 lines on the server because you expect that most of your domain computers won't have the RSAT tools or AD cmdlets installed.
The way to run it on a server is to have PowerShell Remoting enabled on the server and then use Invoke-Command.
That authentication is typically done with kerberos, though you could change the method, and you can supply credentials manually (though I doubt you want to be embedding credentials in the script).
You need to consider that the user making the AD changes needs permission to do so. Usually that's a domain admin, although permission could be delegated.
If you're running this as a startup script, it's running as SYSTEM. That account authenticates on the domain as the computer account (COMPUTERNAME$). This means that the computer account needs permission to move itself, which may mean it needs the ability to write objects into all possible OUs (I don't recall offhand which permissions are needed).
So you would either need to grant this ability to all computers (any computer in Domain Computers would have the ability to move any other computer to any OU), or somehow give each computer only the ability to move itself into the correct OU (which might still be too much in the way of permissions).
Another option is to make a customized session configuration on the server with a RunAs user. You could limit the users allowed to connect to the session (to Domain Computers), and limit the allowed commands so that the connecting computers can only run a limited set of functions/cmdlets. Even better, you can write your own function to do the change and only let them run that one. With the RunAs user being a privileged user in AD, the changes will work without the connecting user having the ability to make the changes directly, and without giving the connecting user the ability to use the privileged user or elevate their own permission. Remember that the connecting user in this case is the computer account.
This last method is, I think, the best/most secure way to do what you want, if you insist that it must be initiated from the client machine.
Reconsider doing this as a server-side process. Get-ADComputer can return an IPv4 address for the object, so you could use that instead of DNS. Centralizing it would make it easier to manage and troubleshoot the process.