两种方法编程实现锁屏注销关机操作

Sunshine

发布日期: 2018-12-20 12:33:41 浏览量: 1228
评分:
star star star star star star star star star_border star_border
*转载请注明来自write-bug.com

背景

我们对计算机锁屏、注销、关机通常都是点击鼠标去操作,但是,大家有没有试过编程去实现。

或许对命令行熟悉的读者,会想到可以使用CMD命令去实现注销、关机、重启等操作。是的,这个可以实现,而且使用命令行实现,是本文讲解的一种实现方法之一。另一种方法,就是使用Win32 API函数 ExitWindowsEx 去实现注销、关机等操作,使用 LockWorkStation 函数实现锁屏操作。

现在,本文就把实现过程和原理写成文档,分享给大家。

函数声明

LockWorkStation 函数

可以锁定工作站保护其免受未经授权者使用。

函数声明

  1. BOOL WINAPI LockWorkStation(void);

参数

  • 无参数

返回值

  • 如果函数成功,则返回值为非零值。由于该函数以异步方式执行,返回非零值指示操作已启动。它并不表示是否已成功锁定工作站。

ExitWindowsEx 函数

用来退出、重启或注销系统。

函数声明

  1. BOOL ExitWindowsEx(
  2. UINT uFlags, // 关闭参数
  3. DWORD dwReserved // 系统保留,一般取0
  4. )

参数

  • uFlags
    指定关闭的类型。此参数必须有下列值的组合:
VALUE MEANING
EWX_FORCE 强制终止进程。当此标志设置,Windows不会发送消息WM_QUERYENDSESSION和WM_ENDSESSION的消息给目前在系统中运行的程序。这可能会导致应用程序丢失数据。因此,你应该只在紧急情况下使用此标志。
EWX_LOGOFF 关闭所有进程,然后注销用户。
EWX_POWEROFF 关闭系统并关闭电源。该系统必须支持断电。Windows NT中调用进程必须有 SE_SHUTDOWN_NAME 特权。
EWX_REBOOT 关闭系统,然后重新启动系统。Windows NT中:调用进程必须有SE_SHUTDOWN_NAME特权。
EWX_SHUTDOWN 关闭系统,安全地关闭电源。所有文件缓冲区已经刷新到磁盘上,所有正在运行的进程已经停止。Windows NT中:调用进程必须有SE_SHUTDOWN_NAME特权。
  • dwReserved
    系统保留,这参数被忽略。一般取0。

返回值

  • 如果函数成功,返回值为非零。
  • 如果函数失败,返回值是零。想获得更多错误信息,请调用GetLastError函数。

实现原理

我们可以使用命令行 shutdown 指令来实现注销、关机和重启等功能,但这个指令支持实现锁屏功能。

Win32 API 函数 LockWorkStation 支持实现锁屏功能。

Win32 API 函数 ExitWindowsEx 支持实现注销、关机、重启、关电源等功能。而且,实现这些操作需要有权限才行。

所以,对于使用命令行方式,我们可以使用函数 system 去实现CMD命令。

关机的CMD指令是:

  1. system("shutdown -p");
  2. // 或者
  3. system("shutdown -s");

注销的CMD命令是:

  1. system("shutdown -l");

重启的CMD命令是:

  1. system("shutdown -r");

那么对于使用API函数来实现的话,我们直接调用相应的API。

锁屏实现的核心代码是:

  1. ::LockWorkStation();

系统注销实现的核心代码是:

  1. ::ExitWindowsEx(EWX_LOGOFF, 0)

系统关机实现的核心代码是:

  1. ::ExitWindowsEx(EWX_SHUTDOWN, 0)

系统关机实现的核心代码是:

  1. ::ExitWindowsEx(EWX_REBOOT, 0)

需要注意的是,如果使用 ExitWindowsEx 函数来实现关机和重启的操作,需要进程必须要有 SE_SHUTDOWN_NAME 权限,如果没有,则必须先提权,才可以成功使用此函数。因为进程提权的知识,超出了本文讲解的内容范畴,所以在本文就不详细讲解进程提权的操作了,只给出实现代码。

编码实现

进程提权到 SE_SHUTDOWN_NAME 权限

  1. // 进程提权
  2. BOOL EnableProcessPrivilege()
  3. {
  4. HANDLE hToken;
  5. if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
  6. {
  7. ShowError("OpenProcessToken");
  8. return FALSE;
  9. }
  10. TOKEN_PRIVILEGES tkp;
  11. // 修改进程权限
  12. if (!::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid))
  13. {
  14. ShowError("LookupPrivilegeValue");
  15. return FALSE;
  16. }
  17. tkp.PrivilegeCount = 1;
  18. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  19. // 通知系统修改进程权限
  20. if (!::AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL))
  21. {
  22. ShowError("AdjustTokenPrivileges");
  23. return FALSE;
  24. }
  25. return TRUE;
  26. }

CMD方式实现 注销

  1. // CMD方式实现 注销
  2. BOOL CMD_LogOff()
  3. {
  4. system("shutdown -l");
  5. return TRUE;
  6. }

CMD方式实现 关机

  1. // CMD方式实现 关机
  2. BOOL CMD_Shutdown()
  3. {
  4. system("shutdown -p");
  5. return TRUE;
  6. }

CMD方式实现 重启

  1. // CMD方式实现 重启
  2. BOOL CMD_Reboot()
  3. {
  4. system("shutdown -r");
  5. return TRUE;
  6. }

API方式实现 锁屏

  1. // API方式实现 锁屏
  2. BOOL API_Lock()
  3. {
  4. BOOL bRet = ::LockWorkStation();
  5. return bRet;
  6. }

API方式实现 注销

  1. // API方式实现 注销
  2. BOOL API_LogOff()
  3. {
  4. BOOL bRet = ::ExitWindowsEx(EWX_LOGOFF, 0);
  5. return bRet;
  6. }

API方式实现 关机

  1. // API方式实现 关机
  2. BOOL API_Shutdown()
  3. {
  4. BOOL bRet = ::ExitWindowsEx(EWX_SHUTDOWN, 0);
  5. return bRet;
  6. }

API方式实现 重启

  1. // API方式实现 重启
  2. BOOL API_Reboot()
  3. {
  4. BOOL bRet = ::ExitWindowsEx(EWX_REBOOT, 0);
  5. return bRet;
  6. }

总结

需要注意的是,如果使用 ExitWindowsEx 函数来实现关机和重启的操作,需要进程必须要有 SE_SHUTDOWN_NAME 权限,如果没有,则必须先提权,才可以成功使用此函数。

注意,此程序的功能实现不需要管理员权限就可以实现,上面提到的提升进程权限,并不是指获取管理员权限,而是指将修改进程令牌,实现进程权限的提升。而本文,进程提升到 SE_SHUTDOWN_NAME 权限不需要程序以管理员权限运行就可以成功提升。而对于其它的进程权限提升,例如进程提升到 SE_DEBUG_NAME 权限,则需要程序以管理员权限运行方可成功提权。

参考

参考自《Windows黑客编程技术详解》一书

上传的附件 cloud_download SystemOperate_Test.7z ( 6.52kb, 3次下载 )

keyboard_arrow_left上一篇 : 内存快速搜索遍历 磁盘盘符隐藏并访问隐藏磁盘的文件数据 : 下一篇keyboard_arrow_right



Sunshine
2018-11-07 10:57:15
一是通过CMD命令:shutdown;另一种是调用 ExitWindowsEx 和 LockWorkStation 函数实现
ranter
2018-11-10 15:44:35
### dk
Gentleman
2019-03-31 07:41:49
命令行也可以~~

发送私信

这个世界上我只相信两个人,一个是我,另一个不是你

15
文章数
15
评论数
最近文章
eject