Opening command line program with elevated rights - c++

I am currently writing a DLL injection program (C++) which adds specified certificate to certmgr.exe.
I wrote the whole thing connected with injection (OpenProcess, etc.). When I am executing it - attached to svchost - my DLL is not loading since it seems that it doesn't have such rights as svchost has.
How can I pass rights?
In my DLL file, I am using system("certmgr.exe -add ....") and I think this might be the problem because the command line opens as a separate program (as if I opened it via start).

Use ShellExecute() using the "runas" argument, which will make it try to run as administrator
ShellExecuteA( NULL,
"runas",
"c:\\windows\\certmgr.exe",
"-add ....",
NULL,
SW_SHOWNORMAL
);

Related

Run a console application and then close the console and run in background in C++

I want to make a console application in C++ and then when the information is displayed, close the console and run in background. Is this possible? Is another way to do that? Python maybe?
You will have to either close the console window while the process is still running, which is system dependent, or start another process, and even though the standard library offers the system function to do that, its argument is a system dependent command line.
So the upshot is: this is system dependent.
In Windows the full-version of Microsoft's Visual Studio IDE has always, as far back as I can remember, used a peculiar approach for this, with two executable files devenv.com and devenv.exe. The former is a console subsystem executable, which by default runs the latter, which is a GUI subsystem executable:
[C:\]
> where devenv
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe
[C:\]
> _
The basic idea here is that for historical reasons the command interpreter's search for an executable finds the .com file first, so the command devenv just works, either for starting the IDE or just getting the help text via the /? option.
Yes, this is possible with a small variant:
fork another process. But this is heavily system dependent:
posix/linux allow to simply clone the process;
windows requires new process to be created from an executable. You then have to communicate the state. Its less trivial as explained in this article, in the paragraph on porting fork())
then exit the program (it's the only way to give back control to the console).
On Windows use ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false) to hide the console window. It will still be running in the background and is not visible on the taskbar.
However you will have to run a task manager like Taskmgr.exe to find it and shut it down.
#include <windows.h>
#include <iostream>
using namespace std;
int main () {
cout<<"Some information is displayed.. \n\n";
Sleep(5000);
cout<<"wait.. the console is going to hide and run in background.. \n";
Sleep(5000);
ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
while(true) {
// Do your hidden stuff in here
}
return 0;
}
The other answers given here overcomplicate things. The most easy way to close the console window in Windows is to simply detach from it. Once the last user of a console window datached, the console window gets closed.
If you start a program from a CLI (e.g. cmd.exe) then this CLI is also attaches to to the console and thus the console window will not close.
Anyway, detaching from a console is as simple as calling
FreeConsole();
… done!
Also you can attach to a newly created console at any time using AttachConsole, which takes a process ID. Now in a CLI situation the parent will usually be the CLI shell, so you may want to attach to the console of that.

C++ ShellExecute batch script won't recognize commands

As the title may suggest, i am trying to open a .bat file via "ShellExecute" function.
It works with very basic .bat scripts, such as "hello world" ones, but won't work with others containing commands for running game servers.
For example, here is a batch script for a "Killing Floor 1" server:
ucc server KF-Mountainpass.rom?game=KFmod.KFGameType?VACSecured=true?MaxPlayers=6?GamePassword=genrl -log=server.log
PAUSE
Please note that this batch works perfectly when manually clicking on it, but gives the following error when opened via ShellExecute:
"ucc" is not recognized as an internal or external command, operable program or batch file.
I have also tested on other batch files for other game servers, having the same result.
So, here is a list of what i have tried so far, and did not work:
ShellExecute(NULL, "open", "cmd.exe", "C:\\windows\\system32\\cmd.exe /C C:\\Cartella_Server\\Server_KF1\\System\\KF_Server_Launcher.bat", NULL, SW_SHOW);
ShellExecute(NULL,"open", C:\\Cartella_Server\\Server_KF1\\System\\KF_Server_Launcher.bat", NULL, NULL, SW_SHOW);
ShellExecute(NULL, "open", "cmd.exe", "/C C:\\Cartella_Server\\Server_KF1\\System\\KF_Server_Launcher.bat", NULL, SW_SHOW);
Is there any solution to this?
Thanks in advance for your time :)
It is because the script is loading inside the directory of cmd.exe
Why? Because you didn't fill the working directory field.
Have a look at the 5th parameter of ShellExecute:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153%28v=vs.85%29.aspx
Most likely, the ucc program is in the same directory as tha launcher script. So it works when you click on it, because your current directory is one with the file, but when you run your program your current directory is different.
Solution - provide proper directory in fifth ShellExecute argument, as per https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx

I want to open Msconfig from a button on my GUI

In my line of work I use msconfig a lot and I'm wanting to create a tool with various buttons on it so I can easily access my most commonly used programs. I'm using the Win32API to create the GUI and buttons, however I am having trouble getting msconfig to run. In my program I have
void callMsconfig()
{
ShellExecute(NULL,(LPCWSTR)L"open", (LPCWSTR)L"C:\\Windows\\System32\\msconfig.exe", NULL, NULL, SW_SHOWDEFAULT);
}
and an action statement so when the button is pressed the function is called. I've tried replacing ShellExecute() with system() and CreateProcess(). I've also replaced "open" with "runas" and the most I've gotten is the error saying C:\Windows\System32\msconfig.exe cannot be found when I know it is there because I've checked. What am I doing wrong? I'm using Windows 10 Home if that helps any.
If you have created a 32bit app that is running inside of the WOW64 emulator on 64bit systems, the C:\Windows\System32\ folder is silently redirected by WOW64 to the C:\Windows\SysWOW64\ folder, which does not have an msconfig.exe file. You need to account for that. Either create a 64bit executable, or use the Sysnative alias in 32bit code that runs inside of WOW64. Sysnative is documented on MSDN:
File System Redirector:
32-bit applications can access the native system directory by substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes Sysnative as a special alias used to indicate that the file system should not redirect the access. This mechanism is flexible and easy to use, therefore, it is the recommended mechanism to bypass file system redirection. Note that 64-bit applications cannot use the Sysnative alias as it is a virtual directory not a real one.
Try something more like this:
#include <shlwapi.h>
void callMsconfig()
{
BOOL IsWow64 = FALSE;
WCHAR szCmdLine[MAX_PATH] = {0};
IsWow64Process(GetCurrentProcess(), &IsWow64);
if (IsWow64)
{
GetWindowsDirectoryW(szCmdLine, MAX_PATH);
PathAppendW(szCmdLine, L"Sysnative");
}
else
{
GetSystemDirectoryW(szCmdLine, MAX_PATH);
}
PathAppendW(szCmdLine, L"msconfig.exe");
ShellExecuteW(NULL, NULL, szCmdLine, NULL, NULL, SW_SHOWDEFAULT);
}
However, do note that if UAC is enabled and you try to launch msconfig.exe from a 32bit process running inside of WOW64, the 32bit process MUST be running elevated or else ShellExecute() (and CreateProcess()) will fail to find the file correctly. I don't know why, but that is how it works. UAC Elevation is not required when launching msconfig.exe from a 64bit process.
If you don't want to elevate your entire program, you will have to make it launch a separate elevated process that can then launch msconfig.exe. You could just have the program launch a second copy of itself with a command-line parameter so it knows to just launch msconfig.exe and then exit itself. To launch an elevated process, you can use ShellExecute() specifying the runas verb.

C++ file permissions when automatically started by Windows on login

Problem: my C++ program cannot write to a file after reboot because it is denied access.
The program is added into the registry at the following location, thus enabling it during start up:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
The following snipper within the code is similar to the one that is causing the problems:
ofstream myfile;
myfile.open ("example.txt", ios:app);
myfile << "Writing this to a file.\n";
myfile.close();
Because this snippet of code runs within a loop the file is repeatedly opened and closed, but when the computer is rebooted the program seems to loose file permissions to it, and .open says it got an Acess Denied error with respect to the file.
What is the problem here? How come the program runs when it is initiated by me without admin rights, but not when Windows initiates it?
As I understand the problem is not in C++ libs but in rights that your application has when windows run it. So, try the following:
1) create shortcut for your exe-file;
2) in HKEY_CURRENT_USER\...\Run change name of application from *.exe to *.lnk (just to run application with help of shortcut);
3) in the shortcut's properties in the Advanced Security Settings section change OWNER to SYSTEM.
perhaps this helps.
"example.txt" is relative to your working directory, which is probably different when run at startup. Add a hardcoded path to test this hypothesis.

How to call system() in an opened administrator program and gives it the same privileges?

I am writing a c++ application in Windows that runs as administrator. However, while calling the system() command, it seems that the command doesn't have admin privileges (can't create file in the C:\Program Files (x86)\ directory).
How can I avoid using CreateProcess ?
If you use system you can use:
system("runas /user:<admin-user> \"program.exe\"");
Or ShellExecute:
ShellExecute(hwnd, "runas", "program.exe", 0, 0, SW_SHOWNORMAL);
This Stackoverflow Question
details the CreateProcess method pretty well.