To implement this function, you must call a system API.
ExitWindowsEx
The function is to log out of the current user, shut down the system, or restart the system.
It sends a WM_QUERYENDSESSION message to all applications so that they can decide whether they can be closed.
Function prototype
[Cpp] <SPAN style = "FONT-SIZE: 18px"> bool winapi ExitWindowsEx (
_ In UINT uFlags,
_ In DWORD dwReason
);
</SPAN>
Bool winapi ExitWindowsEx (
_ In UINT uFlags,
_ In DWORD dwReason
);
The first parameter is the closing type, and the second parameter is the reason for closing.
The first parameter can be:
EWX_LOGOFF
0
EWX_POWEROFF
Zero x 00000008
EWX_REBOOT
Zero x 00000002
EWX_RESTARTAPPS
Zero x 00000040
EWX_SHUTDOWN
Zero x 00000001
This parameter can also include the following two optional values:
EWX_FORCE
0x00000004 includes this parameter to force the system to shut down, which may cause data loss to applications.
EWX_FORCEIFHUNG
Zero x 00000010
If the application process still does not respond to the WM_QUERYENDSESSION or WM_ENDSESSION message after the timeout, disable them forcibly.
Return Value:
If the call succeeds, a non-zero value is returned. If the call fails, 0 is returned.
You can use GetLastError () to obtain more error information.
In addition to understanding this function, we should also be clear:
For windows NT and later operating systems, we need to upgrade the SE_SHUTDOWN permission to complete the shutdown operation.
NT, such as, 98, ME
NT and above systems include:
Microsoft Windows 2000 (Windows NT 5.0) (1999) (2000-2010)
Microsoft Windows XP (Windows NT 5.1) (2001-2014)
Microsoft Windows Server 2003 (Windows NT 5.2) (2003-2015)
Microsoft Windows Server 2003 R2 (Windows NT 5.2) (2006-2015)
Microsoft Windows Vista (Windows NT 6.0) (2006-2017)
Microsoft Windows Server 2008 (Windows NT 6.0) (2008-2018)
Microsoft Windows 7 (Windows NT 6.1) (2009-2020)
The following describes the implementation:
Shutdown
1. Check the system version to see if it is NT or above. If yes, upgrade the permission.
2. Call the system API, ExitWindowsEx.
[Cpp] # pragma region function implementation
BOOL ReSetWindows (DWORD dwFlags, BOOL bForce)
{
// Check whether the parameters are correct
If (dwFlags! = EWX_LOGOFF & dwFlags! = EWX_REBOOT & dwFlags! = EWX_SHUTDOWN)
Return FALSE;
// Obtain the version information of the system. Let's determine whether to upgrade the system permission later.
OSVERSIONINFO osvi = {0 };
// Obtain the parameter size and provide it to GetVersionEx to determine whether it is a new version of OSVERSIONINFO or an old version
// The new version is OSVERSIONINFOEX. Extended version
Osvi. dwOSVersionInfoSize = sizeof (OSVERSIONINFO );
If (! GetVersionEx (& osvi ))
{
Return FALSE;
}
// Check the version of the operating system. If it is an NT-type system, you must upgrade the system permission.
If (osvi. dwPlatformId = VER_PLATFORM_WIN32_NT)
{
// EnableShutDownPriv ();
}
// Determine whether it is forced shutdown or system process shutdown.
DwFlags | = (bForce! = FALSE )? EWX_FORCE: EWX_FORCEIFHUNG;
// Call the API
Return ExitWindowsEx (dwFlags, 0 );
}
# Pragma region function implementation
BOOL ReSetWindows (DWORD dwFlags, BOOL bForce)
{
// Check whether the parameters are correct
If (dwFlags! = EWX_LOGOFF & dwFlags! = EWX_REBOOT & dwFlags! = EWX_SHUTDOWN)
Return FALSE;
// Obtain the version information of the system. Let's determine whether to upgrade the system permission later.
OSVERSIONINFO osvi = {0 };
// Obtain the parameter size and provide it to GetVersionEx to determine whether it is a new version of OSVERSIONINFO or an old version
// The new version is OSVERSIONINFOEX. Extended version
Osvi. dwOSVersionInfoSize = sizeof (OSVERSIONINFO );
If (! GetVersionEx (& osvi ))
{
Return FALSE;
}
// Check the version of the operating system. If it is an NT-type system, you must upgrade the system permission.
If (osvi. dwPlatformId = VER_PLATFORM_WIN32_NT)
{
// EnableShutDownPriv ();
}
// Determine whether it is forced shutdown or system process shutdown.
DwFlags | = (bForce! = FALSE )? EWX_FORCE: EWX_FORCEIFHUNG;
// Call the API
Return ExitWindowsEx (dwFlags, 0 );
} Code for permission escalation:
[Cpp] # Use pragma region to improve system Permissions
// This is a general permission escalation function.
// Modify the second SE_SHUTDOWN_NAME parameter of LookupPrivilegeValue.
BOOL EnableShutDownPriv ()
{
HANDLE hToken = NULL;
TOKEN_PRIVILEGES tkp = {0 };
// Open the permission token of the current program
If (! OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, & hToken ))
{
Return FALSE;
}
// Obtain the LUID of a specific permission and save it in tkp.
If (! LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, & tkp. Privileges [0]. Luid ))
{
CloseHandle (hToken );
Return FALSE;
}
Tkp. PrivilegeCount = 1;
Tkp. Privileges [0]. Attributes = SE_PRIVILEGE_ENABLED;
// Call AdjustTokenPrivileges to escalate the required system Permissions
If (! AdjustTokenPrivileges (hToken, FALSE, & tkp, sizeof (TOKEN_PRIVILEGES), NULL, NULL ))
{
CloseHandle (hToken );
Return FALSE;
}
Return TRUE;
}
# Pragma region is used to improve system Permissions
// This is a general permission escalation function.
// Modify the second SE_SHUTDOWN_NAME parameter of LookupPrivilegeValue.
BOOL EnableShutDownPriv ()
{
HANDLE hToken = NULL;
TOKEN_PRIVILEGES tkp = {0 };
// Open the permission token of the current program
If (! OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, & hToken ))
{
Return FALSE;
}
// Obtain the LUID of a specific permission and save it in tkp.
If (! LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, & tkp. Privileges [0]. Luid ))
{
CloseHandle (hToken );
Return FALSE;
}
Tkp. PrivilegeCount = 1;
Tkp. Privileges [0]. Attributes = SE_PRIVILEGE_ENABLED;
// Call AdjustTokenPrivileges to escalate the required system Permissions
If (! AdjustTokenPrivileges (hToken, FALSE, & tkp, sizeof (TOKEN_PRIVILEGES), NULL, NULL ))
{
CloseHandle (hToken );
Return FALSE;
}
Return TRUE;
} Call method:
[Cpp] ReSetWindows (EWX_LOGOFF, false); // logout
ReSetWindows (EWX_LOGOFF, false); // deregister [cpp] view plaincopyprint? ReSetWindows (EWX_REBOOT, true); // restart
ReSetWindows (EWX_REBOOT, true); // restart [cpp] view plaincopyprint? ReSetWindows (EWX_SHUTDOWN, true); // Shutdown
ReSetWindows (EWX_SHUTDOWN, true); // You must test the shutdown on the VM during testing. Otherwise, it would be quite depressing if the system is turned off!