Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node-Windows - Run GUI app on Logon screen

I need to run a GUI app on the logon screen on Windows 7 to 10.

I have a nodejs app registered as a service which runs as SYSTEM (the default), using node-windows module. This seems to be a prerequisite to what I need, but something more is necessary.

The app is just a basic socket client that connects to a socket server, nothing special as of yet.

I am thinking maybe if I use child_process.spawn() to open an elevated command-prompt and/or runas another user-- but what user? SYSTEM doesn't do it. I'm thinking whatever winlogon.exe runs as, but that doesn't seem to be SYSTEM even though that's what it shows as in task manager.

Is there a windows command to run a GUI in the logon screen if you have SYSTEM-level access?

UPDATE:

Ok. As of now I have a reverse telnet-like client running on the "remote host" as a Windows Service under the SYSTEM user. It periodically connects to a test server text interface (also node), from which you can enter nodejs commands-- basically a home-brew JS REPL.

I am able to spawn a hidden, interactive windows commands prompt under Session 0, type commands and get output through my little reverse command-line terminal.

Obvi, encryption and security will be important here, but for now Windows is running in a VM inside Linux on my laptop, and the app(s) only talk to each other through private NIC's on a Host-only Virtual Network, so packets are not spilling out onto the the real network.

At my windows command prompt in Session 0, I tried running my remote-control GUI app. Instead of being presented with a GUI, I get the following error:

[5472:5492:0828/031356.901:ERROR:gpu_process_transport_factory.cc(1024)] Lost UI shared context.

If I tasklist, I get:

winlogon.exe 2140 Console 3 6,704 K Unknown NT AUTHORITY\SYSTEM 0:00:00 N/A
LogonUI.exe 4772 Console 3 19,104 K Unknown NT AUTHORITY\SYSTEM 0:00:00 N/A

So, I can see winlogon.exe and LogonUI.exe are running in session 3 as user 'SYSTEM'.

How can I put the service in the GUI context of winlogon and logonui, or spawn my app in it's ?

Is there a windows commands to do this? A nodejs command/module/function?

MORE INFO:

It needs to be a programmatic, automatable solution I can work into the program-- no manual tweaking using another GUI app to get it working.

Registry edits or anything accomplishable via node or windows console commands should be acceptable, however, since those I can incorporate into my code.

Background: This is mostly to run a remote-desktop app I wrote, much like Screen-Connect or LogMeIn. It works great-- except for the part where it pauses anytime you invoke anything calling up the UAC or enter the logon screen, making it not yet practical for remote IT work.

The nodejs windows service app also works good for it's part, autostarts as a service at boot time, autoconnects/reconnects to the test server without requiring login or a continuous connection, and stays alive persistently.

Basically I am thinking if I can run an instance of it in the logon screen it should be able to then grab desktop video capture for output to the network, and invoke remote mouse and keyboard input from the network.

The desktop-capture is done using NW.js, and child_process.spawn()ed robotjs-based socket-client running on the remote host.

Unfortunately, implanting robotjs in the service app doesn't work-- I tried that as I was thinking at the very least I could have a custom remote logon screen in the controller-app and have robotjs input the password in the remote pc's logon screen-- but no luck. It appears I am only getting the legacy Desktop 0, not the logon screen for robotjs-based keyboard/mouse input.

I am really hoping all I need is to 'runas' some other user or process. **Note: I am looking for a way to do this that does not involve auto-logon, reboots, or workarounds. I know MicroSoft has officially supported ways for accomplishing such tasks-- but I have yet to find a way to do it through Node rather than C. If there's a node-module using native code to do it, that's fine by me. I just want my code to be JavaScript.

Anyway, that is the actual goal I'm asking this question for-- to run my remote desktop app on the logon screen to grap video and invoke mouse actions and keystrokes.

If there is a better way that doesn't match the question in the title, please do answer and I will edit the question to match the answer, if it works.

like image 663
jdmayfield Avatar asked Jan 27 '23 12:01

jdmayfield


2 Answers

The answer is 'paexec'. psexec works exactly the same, but paexec is open-source, freely distributable, and usable in your apps for both personal and commercial applications.


Requirements:

Download paexec.exe .

Place it where you can execute it, OR cd to the folder you put it in, OR place it in the command path, OR add the folder you put it in to the command path, OR reference it by pathname (i.e. c:\folder\subfolder\paexec -your_options).


Recommended:

Execute this from a Windows Service (in my case an npm node-windows service). This allows you to run it as SYSTEM. There are other ways, but this one seems to work the best.


Example use:

paexec -d -s -x -w c:\path\to\your\app_folder cmd /c app.exe -your_options

How this works:

-d prevent paexec from waiting for app to exit, therefore allows non-blocking.

-s executes as SYSTEM user.

-x causes it to run on the logon screen

-w sets the current working directory

cmd /c yourappname.exe allows you to run a GUI interactive app with the previous options (it doesn't seem to work without opening the prompt first).


Addition considerations:

Using 'cmd /c', you can call a .bat or .cmd script and use 'start /b your_app.exe' to make the cmd.exe window go away (otherwise you are stuck with it on your logon screen until you close it or your app).

Your app will continue running after logging in, however it won't be running in the users login session, so if you want your app to do both, I recommend using 'taskkill /f /im your_app.exe' or other means to stop in and then running on the users login session.

You can run it on the user's desktop session via:

paexec -d -s -i 1 -w... (the rest is the same as above).

...assuming there is only one user logged in, they will be on Session 1. This is what the '-i 1' option does, is run it on session 1. If there is more than one user logged in (i.e. via Switch User etc.) they may have a different Session number, so just replace '-i 1' with '-i x' where 'x' is the users Session ID.

You can lookup the Session id via Windows command 'tasklist /v'.

If you're trying run this from a node.js service, you will need to use process_child built-in module and spawn a cmd prompt to run it from. There are lots of examples for this, so not tackling that here. The nice thing about running it from a Windows Service is it won't open a visible window, and you can provide i/o via the standard child_process.spawn() methods and events.


Security:

Running this from a Windows Service (i.e. via node-windows and child_process.spawn) allows you to run your GUI app not only on the logon screen, but at boot-time before login, GUI or not-- without any of the typical insecure hacks, like autologon to a special user account then locking the screen or logging out, etc. It is actually using a tool that mirrors MicroSoft/SysInternals own tool for doing this under MS's officially prescribed methods.

The weak-point here is only your app, so button it up and be safe!


Note: Obvi this is a complicated issue, which is probably why there don't seem to be any good answers-- and likely the few who have figured it out don't want to share. So here you go.

Enjoy!


PS: You could be really Evil with this. Please don't use it for nefarious purposes. That's exactly why they have made it so difficult. Be good, so we can all benefit from it's power.


Aside Regarding task names:

If you wish to refer to your node or nw.js app, and see it as yourappname.exe in tasklist and task manager, you can simply rename the node.exe and nw.exe executables to whatever you want them to show as (i.e. rename nw.exe to myapp.exe and it will show and be referred to as myapp.exe in Windows). This is assuming you have a local copy of node.exe etc. in your app folder... Don't do this with the globally installed executable!


One more thing:

If anyone has a better, tried and tested method, please add it as an answer!

If it works for me, I will gladly unaccept my answer and accept yours!!

like image 167
jdmayfield Avatar answered Feb 06 '23 14:02

jdmayfield


Thank you so much for sharing your discovery! Here's another piece that may help others:

If you don't want to make a separate app to just start a service, you can use NSSM (https://nssm.cc/). Download it and run the following to create the service:

nssm install your-app-name c:\tmp\paexec.exe -s -x -w c:\path\to\your\app_folder cmd /c app.exe -your_options

Then, starting the service will launch paexec in blocking mode (so if the service is running, paexec is running, and hence, your app is running), with the same flags as jdmayfield's awesome answer.

If anyone has any suggestions on how to get remote desktop access working on Windows without having to switch between the service session and the user session, please share it!

like image 20
J Sherwani Avatar answered Feb 06 '23 14:02

J Sherwani