Windows 7 Shutdown Issue / ExitWindowsEx/AdjustTokenPrivileges - c++

Hello to all stackoverflow great minds!! I need some explanation and suggestion on how to determine what have cause this problem. I hope nobody would be harass and will judge directly. If there are not clear here please be kind to reply.
I have an application that i am investigating right now. The application will shutdown the Windows if a power-off message was posted from one of its child processes.
Scenario:
When i start the application and post a power-off message nothing happens to windows only the application was exited. The second time I start the application then post again a power off message the windows shutdown or reboot depending on the condition i had send.
HANDLE hToken;
TOKEN_PRIVILEGES tp;
OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL,
SE_SHUTDOWN_NAME, &(tp.Privileges[0].Luid));
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
if ( iApplicationProblemOccured == 1 ){
ExitWindowsEx(EWX_FORCE | EWX_SHUTDOWN | EWX_POWEROFF, 0L);
} else {
if(wShutdownType != 1) {
ExitWindowsEx(EWX_FORCE | EWX_REBOOT, 0L);
} else {
ExitWindowsEx(EWX_FORCE | EWX_SHUTDOWN | EWX_POWEROFF, 0L);
}
}
AdjustTokenPrivileges(hToken, TRUE, &tp, sizeof(tp), NULL, NULL);
ExitProcess(0);
The problem is why the execution of the ExitWindowsEx from the first power off does not works?
I have checked the tokenpriveleges from the first poweroff but it was enabled.
I have also change the dwReason to planned in the ExitWindowsEx but nothing happens.
From what i read in
https://msdn.microsoft.com/en-us/library/windows/desktop/aa376868(v=vs.85).aspx
if the return of ExitWindowsEx is 0, it does not necessarily determines that the execution of windows shutdown will be successful because the function will only initiate the shutdown process.
I am thinking that there is something process/services that blocks stops the windows shutdown process from the first power off..
Is there a way to debug the windows shutdown process after my application send the shutdown request?
I am hoping someone can help me with this issue!!
Thanks a lot..

Related

Windows Resource Monitors "Network Activity" c++

I'm trying to figure out how to get all network activity for a given process. In the Windows "Resource Monitor" application in the "Network Activity" box, you are able to see all tcp / udp connections, and the data being sent etc. I first tried using the cmd netstat, and was going to parse this but quickly realized it "misses" a whole bunch of udp connections. So that was out. Now I've been looking into using iphlpapi.h in c++ along with its GetExtendedUdpTable function. But even this doesn't seem to be showing all the data that Resource Monitor shows. Can anyone direct me to the proper windows API that can get the same information as seen in the Network Activity tab under Resource Monitor. I've been searching for a while now and everything I've found is extremely old, I'm hoping to use whatever is the current/modern approach. This doesn't have to be backwards compatible, windows 10 only is fine.
Basically my end-goal is to build an app that can geo-locate ip's using a database automatically for a target application (including UDP connections). Now I'm sure there are many libraries/apps out there that can already do this. I'm just wanting to do it as a learning process so I'd like to avoid any libraries/API other than windows provided ones.
This is currently what I've been working with, please forgive the use of poor practices such as using printf and not using static_cast etc. I'll be rewriting everything properly once I've found a way of obtaining the information I'm after.
MIB_UDPTABLE_OWNER_PID* pUdpTable;
MIB_UDPROW_OWNER_PID* owner;
DWORD dwSize;
DWORD dwResult;
dwResult = GetExtendedUdpTable(NULL, &dwSize, false, AF_INET, UDP_TABLE_OWNER_PID, 0);
pUdpTable = (MIB_UDPTABLE_OWNER_PID*)MALLOC(dwSize);
dwResult = GetExtendedUdpTable(pUdpTable, &dwSize, false, AF_INET, UDP_TABLE_OWNER_PID, 0);
for (DWORD dwLoop = 0; dwLoop < pUdpTable->dwNumEntries; dwLoop++) {
owner = &pUdpTable->table[dwLoop];
printf("%ld ", owner->dwOwningPid);
HANDLE Handle = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
owner->dwOwningPid
);
if (Handle) {
TCHAR Buffer[MAX_PATH];
if (GetModuleFileNameEx(Handle, 0, Buffer, MAX_PATH)) {
printf(Buffer);
printf("\n");
} else {
printf("Error GetModuleFileNameEx : %lu\n", GetLastError());
}
CloseHandle(Handle);
} else {
printf("Error OpenProcess : %lu\n", GetLastError());
}
}
FREE(pUdpTable);

Named pipe: ReadFile after ConnectNamedPipe return ERROR_BROKEN_PIPE

I reactivated code that I am sure used to work some months ago. It drives me crazy but it does not anymore. I could not find an answer in other questions.
On the server side, I create a pipe using
#define MAX_MESSAGE_LENGTH 1024
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, static_cast<PACL>(0), FALSE);
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
auto pipe_name = _T("\\\\.\\pipe\\") + _serviceName;
HANDLE pipe = CreateNamedPipe(
pipe_name.c_str(),
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1,
MAX_MESSAGE_LENGTH, MAX_MESSAGE_LENGTH, // buffer lengths (advisory)
0, // default timeout of 50ms when WaitNamedPipe uses NMPWAIT_USE_DEFAULT_WAIT
&sa));
Then a thread waits for incoming clients with ConnectNamedPipe. ConnectNamedPipe blocks until a client connects with
HANDLE pipe = CreateFile(
pipe_name.c_str(), // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
FILE_ATTRIBUTE_NORMAL, // default attributes
NULL); // no template file
ConnectNamedPipe on the server then returns with TRUE and GetLastError == 0. But when it tries to call ReadFile to read incoming data on the pipe, ReadFile immediately returns FALSE and GetLastError==ERROR_BROKEN_PIPE.
On client side, CreateFile has returned GetLastError==231, "All pipe instances are busy". Although it is the only client! A call to WaitNamedPipe(pipe, 2000)returns with error code 121, "The semaphore timeout period has expired".
Increasing the number of allowed clients in CreateNamedPipe does not change anything.
It seems the pipe got completely broken in the moment the client tries to connect. But why? Both client and server run on the same machine with same user and even same session.
Another call to ConnectNamedPipe then failed with GLE=232:"The pipe is being closed".
I also had other SECURITY_ATTRIBUTES for CreateNamedPipe, which shall allow for non-elevated users to connect, but that makes no difference.
Also I tried to use CallNamedPipe on the client with the same result.
PathFileExists is the pipe killer! After hours of trying I finally found what breaks the pipe: a simple call to PathFileExists on the pipe name! This was added recently on the client side to check whether the pipe is already created. I had a look at the code changes but I totally missed that. PathFileExists correctly returns true or false but seems to mess up the pipe (as I told it did not help to allow more than one client to connect). Argh!!!

WinAPI: OpenProcess() returns error 5 with SeDebugPrivilege enabled for host process

I've got a routine where I process-walk to obtain the HANDLE of each process as I 'walk' down the list (which works fine), but my issue lies when I do:
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID) where PROCESS_ALL_ACCESS is the access token, handle inheritance is set to FALSE, and pe32 is a PROCESSENTRY32
GetLastError() returns error code 5, and all the handles that are made are addresses which do not correspond to any appropriate process in Spy++32/64 (I've tried building the application under both platform targets, but as you'd expect, the result is the same).
The code for setting SeDebugPrivilege for the host process which I'm using is:
BOOL EnableDebugPrivilege(BOOL bEnable)
{
HANDLE hToken = nullptr;
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) return FALSE;
TOKEN_PRIVILEGES tokenPriv;
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Luid = luid;
tokenPriv.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) return FALSE;
return TRUE;
}
Some questions that would be helpful to you:
I'm running Windows 7 x64 Professional.
Yes, devenv.exe is started with "Run as Administrator" privileges, which means that the debugger and the application itself are started under the same affinity.
I have tried toggling UAC or running the application with UAC off altogether. Still error code 5.
I just attempted doing it with PROCESS_QUERY_LIMITED_INFORMATION and I receive error code 6, or ERROR_INVALID_HANDLE. Also attempted with PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, result is error 5 again.
SeDebugPrivilege is enabled, verified with SysInternals' Process Explorer. Additionally, all processes that spawn from devenv/whatever the debugger is called inherit SeDebugPrivilege so...this is weird.
Thank you all very much for your time, I'm reaching wits end with this issue :S
Are you sure you are not passing 0 as a process ID value? The system idle process with ID 0 is included in the snapshot under the name [System Process], but you can't open a handle for it as the documentation for OpenProcess specifically says it'll fail. Well it says a bit more:
If the specified process is the System Process (0x00000000), the
function fails and the last error code is ERROR_INVALID_PARAMETER. If
the specified process is the Idle process or one of the CSRSS
processes, this function fails and the last error code is
ERROR_ACCESS_DENIED because their access restrictions prevent
user-level code from opening them.
Well, it's not completely true as I was able to open handle to CSRSS (of course, it doesn't actually have the requested rights). But it may fail for some protected processes (audiodg), so you shouldn't not do this. Instead, check the name of the process if it's the one you want.

How to Reboot Programmatically?

How can I reboot in c++? Is there any provision in WinSDK? What kind of rights should my program(process) have to do so?
There is the ExitWindowsEx Function that can do this. You need to pass the EWX_REBOOT (0x00000002) flag to restart the system.
Important note here (quote from MSDN):
The ExitWindowsEx function returns as soon as it has initiated the shutdown process. The shutdown or logoff then proceeds asynchronously. The function is designed to stop all processes in the caller's logon session. Therefore, if you are not the interactive user, the function can succeed without actually shutting down the computer. If you are not the interactive user, use the InitiateSystemShutdown or InitiateSystemShutdownEx function.
You can choose between the appropriate function depending on your situation.
Before calling the ExitWindowsEx function you need to enable the SE_SHUTDOWN_NAME privilege:
OpenProcessToken(GetCurrentProcess (),TOKEN_ADJUST_PRIVILEGES,...)
LookupPrivilegeValue
AdjustTokenPrivileges
CloseHandle
I presume you have a very good case for wanting to reboot a PC that may be running lots of other applications.
It sounds like you are looking for InitiateShutdown(), passing SHUTDOWN_RESTART in dwShutdownFlags.
#Anders solution would look, Not sure if this is fully functional as I wrote this a while ago and have not run it in a while. Documentation below.
https://learn.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-adjusttokenprivileges
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lookupprivilegevaluea
https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-initiatesystemshutdowna
void shutSystemOff(const bool &shutReboot = true)
{
// Create all required variables
int vRet = 0;
bool adjustRet;
HANDLE hToken = NULL;
LUID luid;
TOKEN_PRIVILEGES tp;
// Get LUID for current boot for current process.
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &luid);
// Modify and Adjust token privileges for current process.
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
adjustRet = AdjustTokenPrivileges(hToken, false, &tp, sizeof(tp), NULL, 0);
// Check if token privileges were set.
if (adjustRet)
{
// Initiates system shutdown ( Local system, Shutdown Message, Dwell time, Prompt user, Reboot )
InitiateSystemShutdownA(NULL, NULL, 0, true, shutReboot);
}
}

How to turn off pc via windows API?

I never programmed a winapi so i have a little problem here .
I need turn off my pc from my application .
I found this example link text then i found this example how to change privileges link text
But i have problem how to get that parameter HANDLE hToken // access token handle
I think i need to make it in the next order to get the parameter
OpenProcessToken LookupPrivilegeValue AdjustTokenPrivileges
but there are a lot parameters that i have no idea what to do with them .
maybe you have jere some example how i get that HANDLE hToken parameter to make that work .
By the way I already saw the following post link text
Thanks a lot all you .
// ==========================================================================
// system shutdown
// nSDType: 0 - Shutdown the system
// 1 - Shutdown the system and turn off the power (if supported)
// 2 - Shutdown the system and then restart the system
void SystemShutdown(UINT nSDType)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp ;
::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken);
::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1 ; // set 1 privilege
tkp.Privileges[0].Attributes= SE_PRIVILEGE_ENABLED;
// get the shutdown privilege for this process
::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
switch (nSDType)
{
case 0: ::ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE, 0); break;
case 1: ::ExitWindowsEx(EWX_POWEROFF|EWX_FORCE, 0); break;
case 2: ::ExitWindowsEx(EWX_REBOOT |EWX_FORCE, 0); break;
}
}
You could use ShellExecute() to call shutdown.exe
This is a bit much for the comments on Daniel's answer, so I'll put it here.
It looks like your main issue at this point is that your process isn't running with the priveleges required to perform a system shutdown.
The docs for ExitWindowsEx contain this line:
To shut down or restart the system,
the calling process must use the
AdjustTokenPrivileges function to
enable the SE_SHUTDOWN_NAME privilege.
For more information, see Running with
Special Privileges.
They also have some example code. In a pinch, you can just copy that.
http://msdn.microsoft.com/en-us/library/aa376868(VS.85).aspx
Try
ExitWindowsEx(EWX_POWEROFF, 0);
#include<iostream>
using namespace std;
int main(){
system("shutdown -s -f -t 0");
}
Some working code for InitiateSystemShutdownEx:
// Get the process token
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken);
// Build a token privilege request object for shutdown
TOKEN_PRIVILEGES tk;
tk.PrivilegeCount = 1;
tk.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue(NULL, TEXT("SeShutdownPrivilege"), &tk.Privileges[0].Luid);
// Adjust privileges
AdjustTokenPrivileges(hToken, FALSE, &tk, 0, NULL, 0);
// Go ahead and shut down
InitiateSystemShutdownEx(NULL, NULL, 0, FALSE, FALSE, 0);
So far as I can tell, the advantage to this over the ExitWindowsEx solution is that the calling process does not need to belong to the active user.