Running application as System (without PSTools) - vb.net

There are some registry keys that are owned by System, and I can't edit them unless I run as System. I want to be able to edit these keys from my VB application. Any tutorials I've found suggest using PSTools, the now deprecated At command, or schtasks. PSTools seems great, but its license seems to restrictive (about redistributing). At and schtasks are too messy, and require scheduling delays.
This is related to my previous question. I want to take what I discovered, and implement it via VB.
Modify audit policy (group policy)
I also found this, but am getting error 1314. I realized despite running VS2010 "requireAdministrator", and even Running my EXE as Administrator, it still says my username in Task Manager (running as me, not Administrator). I logged in as Administrator, and got Error 5 instead. Even after ensuring I had the rights set, as suggested by this post (CreateProcessAsUser error 1314), it still gave me Error 5.
Using a vb.net application running as SYSTEM, how do I start a detached process for each logged on user?
I changed the example to "TokenAccessLevels.Read and Duplicate" rather than MaximumAllowed.
If Not DuplicateTokenEx(hToken.DangerousGetHandle,
TokenAccessLevels.Read & TokenAccessLevels.Duplicate,
Nothing,
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
TOKEN_TYPE.TokenPrimary,
phNewToken) Then
I get Error 5 from CreateProcessAsUser. This is while running VS2010 as Administrator.

http://forum.sysinternals.com/tip-run-process-in-system-account-scexe_topic16714.html
This post was the best I could do. Basically, install a service, run it, then delete it. According to the OP, this is his explanation.
So how does it work?
The & symbol tells cmd.exe to parse treat the text that follows as if it were a new line in a batch file (It basically is a new line
delimiter which allows multiple commands to be combined into 1 line)
To break it down: Create Service - sc create -- binPath= "cmd /c start
calc" type= own type= interact Start Service net start -- (This could
also be done with: sc start --) Delete Service sc delete --
Variables
Service Name: --
App to run: calc
Variables:
How it works:
cmd /c - allows us to pass in parameters to cmd (Without this initial
part, it will work if you copy & paste in cmd.exe, but not in the Run
Dialog. So this fixes it) sc create binPath= - Since cmd.exe does not
respond to service commands, when the SCM runs the app in binPath (Reg
= ImagePath) then it will terminate it, when not responding in a timely fasion, therefore cmd.exe cannot be used. It has to call
something else which in this case is calc.exe sc create type= This one
took a while to figure out. The inital problem is the Window Station
in which cmd.exe is launched in (which in turn is inherited by
calc.exe (its child process)). Luckily after reading Mark's Windows
Internals e4, I was able to solve it by specifying the service as
being Interactive. (Experimenting, it actually has to be BOTH
interactive(256) and own(16) (256|16 = 272) . Basically what this
allows is for the windows to run in \WinSta0\Default (The current
user's desktop, allowing the window to be displayed.) After some
research from being frustrated that sc would not accept type
=own|interact, I found out that it allows us to specify it again, and instead of overwriting Type (dword) it bitwise-ORs it (Adds it).
Problems Solved! net start - start the service (probably calls
StartService) cmd.exe runs with the command line (CL) of start [File]
in which start probably calls ShellExecute (Its ashame that MS didn't
allow start to specify a SW_* commands (like hide). Although it does
allowing us to min/max windows. cmd.exe opens the app/file, the SCM
terminates cmd.exe for not responding in a timely fashion to its
commands, and the window is now shown to the user. sc delete - Finally
we clean up our path by removing the service
For me, this worked.
cmd /c sc create -- binPath= "cmd /c start app.exe" type= own type= interact & net start -- & sc delete --
Now, I had trouble with getting absolute paths to work. I had to put my .EXE in System32 and SysWOW64, so I didn't have to use an absolute path. According to the site, this is supposed to allow absolute paths to work.
cmd /c sc create -- binPath= "cmd /c start \"\" \"C:\windows\regedit.exe\" " type= own type= interact & net start -- & sc delete --
It never worked for me, as it would hang for some time and never start the app. It should almost instantly complete.

Related

Auto-start my program in administrative mode when system starts up without the UAC prompt

My problem :
I made a program and i have this program for example now under this directory : "C:\Program Files (x86)\AppName", now in the program i'm saving some images in my program directory, but since this is in the C drive, it's giving me a access denied error, now i made the program to always run in administrative mode and that worked just fine, but also there is in my program a feature to auto-start my program when the system starts up using a registry key, but when the "always run in administrative mode" is ON, the program will not start even though there is a start-up key in the registry, and when the "always run in administrative mode" is OFF, it will start.
What I have tried so far :
I tried making an another executable file that will start when the system starts up and then it will run my main program and close it self and i knew that will work but now every time i start my computer, the User Access Control prompt ask me if i trust this program even and that is not very user-friendly.
So i searched and i found that i can create scheduled task but i didn't find a lot of examples and but i tried creating one manually and it did work as wanted!
But here is a code which didn't work :
Imports Microsoft.Win32.TaskScheduler
Using ts As New TaskService("\\RemoteServer")
'Create a new task definition and assign properties
Dim td As TaskDefinition = ts.NewTask()
td.RegistrationInfo.Description = "Does something"
'Create a trigger that will fire the task at this time every other day
td.Triggers.Add(New DailyTrigger() With {
Key.DaysInterval = 2
})
'Create an action that will launch Notepad whenever the trigger fires
td.Actions.Add(New ExecAction("notepad.exe", "c:\test.log", Nothing))
'Register the task in the root folder
ts.RootFolder.RegisterTaskDefinition("Test", td)
End Using
And the problem with the code is :
It couldn't find the TaskService and it has no use of the TaskScheduler library!
Hope someone have some previous experience with that who can help me!
To answer your question:
To use that code you've got to download the Managed Task Scheduler Wrapper first. Then to make it run with administrative privileges you've got to set the RunLevel to TaskRunLevel.Highest on your TaskDefinition:
td.Principal.RunLevel = TaskRunLevel.Highest
However like Plutonix says you shouldn't be writing files to the directory of your program (as that's usually located in the restricted %ProgramFiles% folder).
Instead, use the %ProgramData% directory. You can get the path to it from your code via Environment.GetFolderPath():
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
'Example:
Dim ConfigPath As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "AppName")
Dim ImagePath As String = Path.Combine(ConfigPath, "MyImage.png")
If Directory.Exists(ConfigPath) = False Then Directory.CreateDirectory(ConfigPath)

How allow only one python code process to run if same is executed at the same time

if I have two or more running python console applications at the same time of same application, but executed several times by hand or any other way.
Is there any method from python code itself to stop all extra processes, close console window and keep running only one
The solution I would use would be to have a lockfile created in the tmp directory.
The first instance would start, check for the existence of the file, create the file since it is not there, then run; the following instances will start, check for the existence of the file, then quit since it's there. The original instance would remove the lockfile as its last instruction. NOTE: If the app runs into an error and does not execute the instruction to remove the lockfile, you would need to manually remove it else the app will always see the file.
I've seen on other threads that some suggest using the ps command and look for your app's name, which would work; however, if your app will ever run on Windows, you would need to use tasklist.

Call an external program to run as standard user from a requiredAdministrator program

My Visual Basic program will copy files to a program files folder, so I have to use requiredAdministrator privileges since asInvoker won't allow to write in the program files folder.
After I copy the files I invoke an AutoIt script automating setup of files within the external program (for that the script calls the external program to start automation). The program that creates and copies the files to the "end" program functions fine. The script that calls the "end" program and does the automatic setup also works.
When I combine the 2 the "end" program (which I didn't write nor have the source code of) behaves erratically when run as admin (doesn't read the database or the needed files return an error and terminates itself). So run as admin is not an option. But since my program has to run as admin it looks like it passes the sames privileges to the AutoIt script which calls the "end" program as admin as well. It also happens if I call the "end" program from my app instead of the AutoIt script.
Is there any way to demote my app from admin to standard user after it copies the files, right before it calls either the AutoIt script or the "end" program so that the "end" program is not run as admin or a parameter that specifically makes the app to call the external program as standard user?
I'm using Process.start("autoitscript.exe") to call it. Or any other workaround that doesn't involve the AutoIt script calling the "end" program and my app because that works but not as I intent.
This is a tricky task to perform, but how about this:
Have your application start asInvoker, don't show any windows, and make check if it runs with elevated privileges using this code:
Public Shared Function IsAdministrator() As Boolean
Return (New WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator)
End Function
If it's not running with elevated privileges make it start an invisible cmd instance where you redirect the standard input.
Get the cmd process's PID and now start a new instance of your application with elevated privileges (can be done by setting StartInfo.Verb = "runas") and pass the PID as a command-line parameter.
Now your new instance of the app starts and IsAdministrator() should return True.
So now that you know that your app has administrator privileges you can check if the app has a command-line parameter that is parsable to an Integer. If so, store that Integer somewhere and then do all your admin-required work.
In the end where you want to start the autoitscript.exe application you create a process variable and assigns Process.GetProcessById(<your PID Integer here>) to it.
For example:
Dim cmdProcess As Process = Process.GetProcessById(cmdPID)
Now that you have control over the cmd instance again you just have to write to it's standard input (this article describes a little how it works).
You want to write two lines. The first is to start the other application:
autoitscript.exe
and the second is to close the cmd instance:
exit
If anything's unclear just let me know.

Running a Command that will run on every computer

I have this code which gives me all of the information I need regarding tasks, information etc. I have it all shelled into a VB program and I want to be able to run this from one computer and have it return the data from all computers on the domain.
I am lost as to what to add next.
Dim sCommand As String
'all processes here, ipconfig, java info, etc etc
sCommand = "java.exe -version2 > C:\Info.txt && ipconfig >> C:\INfo.txt"
Shell("cmd.exe /c" & sCommand)
I have script that will list all users on the domain, can I implement that or is there an easier way?
Edit: If I could search the entire domain for a specific file that would work too.
At the moment I just need all the data returned to a text file, I am not worried about it being sorted, or how long a process like this would take.
thanks a bunch
You could do one of two things.
1) You could use WMI to get both the network config off the remote machines and execute a process on the remote machine.
Or
2) You could use PsExec to kick off a command on a remote machine and pipe that out. I personally wouldn't use shell to execute a command as it's pretty poor really. If I was going to kick off a process locally I'd use this, and use StdOut to grab the output from the shell, parse it to give you something you can work with instead of piping the output to a file locally and then reading it later.
EDIT
So you want to do all this from one central location? If you don't want to use PSExec, you'll have to use WMI to create a process on a remote machine to run the java.exe, but you can't redirect the output, you'll have to pipe to a file and read the file in another step.

Hiding the console without losing std err/out streams

My question is similar to Running a CMD or BAT in silent mode, but with one additional constraint.
If you use WshScript.Run in vbscript, you lose access to the standard in/error/out streams of the process. WshScript.Exec gives you access to the standard streams, but you can't hide your windows. How can you have your cake (hide the windows) and eat it too (have direct access to the console streams)?
I'm currently thinking about a C++ executable which creates a new Windows Station and Desktop, (see MSDN) and runs a specified script within that new Desktop (I'm not yet an expert on Window Stations and Desktops, so this idea may be retarded).
This idea is based loosely on Condor's USE_VISIBLE_DESKTOP feature, which, if disabled, runs Condor jobs in a non-visible Desktop. I haven't quite figured out if this requires elevated priveledge.
The tradeoff of this approach is that your script can disappear into limbo if it blocks on user input.
Does anyone have any additional ideas? Or feedback on the approach outlined above?
Edit:
Also, the purpose of our script is to set up the user environment, so running as another user, or as a system scheduled task isn't really an option (unless there are clever tricks I don't know about).
I didn't have any luck with the VBScript fragment above - the windows would still pop up. However I did find a tool called hstart, which looks like about what I need. Unfortunately it isn't open source, or free for commercial use.
Cygwin (http://www.cygwin.com/) comes with a utility named run.exe which does what you are asking for a generic process. You could use this to wrap your call to cscript. Cygwin is GNU so free for commercial or personal use.
I only tested this a little bit, so YMMV...
Put the following code into a .vbs file (I called mine HideWindow.vbs):
Const HIDDEN_WINDOW = 12
computer = "."
Set oWmiService = GetObject("winmgmts:" & _
"{impersonationLevel=impersonate}!\\" & _
computer & "\root\cimv2")
Set oStartup = oWmiService.Get("Win32_ProcessStartup")
Set oConfig = oStartup.SpawnInstance_
oConfig.ShowWindow = HIDDEN_WINDOW
Set oProcess = GetObject("winmgmts:root\cimv2:Win32_Process")
ret = oProcess.Create("cmd.exe /c C:\Scripts\test.cmd", null, oConfig, pid)
Call it from a batch file or command line like this:
CSCRIPT HideWindow.vbs
Whatever you put in test.cmd will run without displaying a window. This could be improved in several ways, but especially by parameterizing the program that gets called by oProcess.Create.
You could use Exec, a freeware tool I wrote that provides a command-line interface for the CreateProcess Windows API call. The GUI version doesn't have a console itself, and you can use it to start a shell script (batch file) in a hidden window.
Bill