如何检查当前批处理脚本是否具有管理权限?
我知道如何使它调用自己与runas,但不知道如何检查管理权限。我所见过的唯一解决方案是粗糙的黑客工作或使用外部程序。好吧,其实我不在乎这是不是一份苦差事,只要它能在Windows XP或更新版本上运行就行。
如何检查当前批处理脚本是否具有管理权限?
我知道如何使它调用自己与runas,但不知道如何检查管理权限。我所见过的唯一解决方案是粗糙的黑客工作或使用外部程序。好吧,其实我不在乎这是不是一份苦差事,只要它能在Windows XP或更新版本上运行就行。
当前回答
从字面上看,在SE上有几十个答案和相关的问题,所有这些都在这样或那样的方式上存在缺陷,清楚地表明Windows没有提供可靠的内置控制台实用程序。所以,是时候推出你自己的了。
下面的C代码,基于检测程序是否以完全管理员权限运行,在Win2k+1中工作,在任何地方和所有情况下(UAC,域,可传递组…)-因为它在检查权限时与系统本身相同。它用消息(可以用开关使其静音)和退出代码表示结果。
它只需要编译一次,然后你可以复制。exe到处-它只依赖于kernel32.dll和advapi32.dll(我已经上传了一个副本)。
chkadmin.c:
#include <malloc.h>
#include <stdio.h>
#include <windows.h>
#pragma comment (lib,"Advapi32.lib")
int main(int argc, char** argv) {
BOOL quiet = FALSE;
DWORD cbSid = SECURITY_MAX_SID_SIZE;
PSID pSid = _alloca(cbSid);
BOOL isAdmin;
if (argc > 1) {
if (!strcmp(argv[1],"/q")) quiet=TRUE;
else if (!strcmp(argv[1],"/?")) {fprintf(stderr,"Usage: %s [/q]\n",argv[0]);return 0;}
}
if (!CreateWellKnownSid(WinBuiltinAdministratorsSid,NULL,pSid,&cbSid)) {
fprintf(stderr,"CreateWellKnownSid: error %d\n",GetLastError());exit(-1);}
if (!CheckTokenMembership(NULL,pSid,&isAdmin)) {
fprintf(stderr,"CheckTokenMembership: error %d\n",GetLastError());exit(-1);}
if (!quiet) puts(isAdmin ? "Admin" : "Non-admin");
return !isAdmin;
}
1MSDN声称api是XP+,但这是错误的。CheckTokenMembership是2k+,另一个甚至更老。最后一个链接还包含一种更复杂的方法,即使在NT中也可以工作。
其他回答
问题
blak3r / Rushyo的解决方案适用于除Windows 8以外的所有系统。在Windows 8上运行AT会导致:
The AT command has been deprecated. Please use schtasks.exe instead.
The request is not supported.
(参见截图#1),将返回%errorLevel% 1。
研究
所以,我开始寻找其他需要更高权限的命令。rationallyparanoid网站上列出了一些这样的命令,所以我在当前Windows操作系统的两个极端(XP和8)上运行了每个命令,希望找到一个在两种操作系统上使用标准权限时都被拒绝访问的命令。
最终,我找到了一个- NET SESSION。一个真正的、干净的、普遍的解决方案,不包括:
在安全位置上创建数据或与数据交互 分析FOR循环返回的数据 搜索“管理员”字符串 使用AT (Windows 8不兼容)或WHOAMI (Windows XP不兼容)。
每一个都有自己的安全性、可用性和可移植性问题。
测试
我已经独立确认,这适用于:
Windows XP, x86 Windows XP, x64 Windows Vista, x86 Windows Vista, x64 Windows 7, x86 Windows 7, x64 Windows 8, x86 Windows 8, x64 Windows 10 v1909, x64
(见截图#2)
实施/使用
所以,要使用这个解决方案,只需像这样做:
@echo off
goto check_Permissions
:check_Permissions
echo Administrative permissions required. Detecting permissions...
net session >nul 2>&1
if %errorLevel% == 0 (
echo Success: Administrative permissions confirmed.
) else (
echo Failure: Current permissions inadequate.
)
pause >nul
解释
NET SESSION是一个用于“管理服务器计算机连接”的标准命令。不带参数使用时,[它]显示与本地计算机的所有会话信息。”
所以,这是我给出的实现的基本过程:
@echo off Disable displaying of commands goto check_Permissions Jump to the :check_Permissions code block net session >nul 2>&1 Run command Hide visual output of command by Redirecting the standard output (numeric handle 1 / STDOUT) stream to nul Redirecting the standard error output stream (numeric handle 2 / STDERR) to the same destination as numeric handle 1 if %errorLevel% == 0 If the value of the exit code (%errorLevel%) is 0 then this means that no errors have occurred and, therefore, the immediate previous command ran successfully else If the value of the exit code (%errorLevel%) is not 0 then this means that errors have occurred and, therefore, the immediate previous command ran unsuccessfully The code between the respective parenthesis will be executed depending on which criteria is met
截图
Windows 8 AT %errorLevel%:
NET SESSION在Windows XP x86 - Windows 8 x64上:
谢谢你,@Tilka,把你接受的答案改成了我的。:)
whoami /groups在一种情况下不起作用。如果你已经完全关闭了UAC(不仅仅是关闭了通知),并且你从一个管理员提示开始,然后发出:
runas /trustlevel:0x20000 cmd
你将运行非提升,但发出:
whoami /groups
会说你升职了。这是错误的。这就是为什么它是错误的:
当在这种状态下运行时,如果IsUserAdmin (https://msdn.microsoft.com/en-us/library/windows/desktop/aa376389(v=vs.85).aspx)返回FALSE并且UAC完全禁用,并且GetTokenInformation返回TokenElevationTypeDefault (http://blogs.msdn.com/b/cjacks/archive/2006/10/24/modifying-the-mandatory-integrity-level-for-a-securable-object-in-windows-vista.aspx),那么进程不是在运行elevated,但是whoami /groups声称它是。
实际上,从批处理文件中做到这一点的最好方法是:
net session >nul 2>nul
net session >nul 2>nul
echo %errorlevel%
你应该做两次net session,因为如果有人事先做了at,你会得到错误的信息。
另一种方法。
REM # # # # CHECKING OR IS STARTED AS ADMINISTRATOR # # # # #
FSUTIL | findstr /I "volume" > nul&if not errorlevel 1 goto Administrator_OK
cls
echo *******************************************************
echo *** R U N A S A D M I N I S T R A T O R ***
echo *******************************************************
echo.
echo.
echo Call up just as the Administrator. Abbreviation can be done to the script and set:
echo.
echo Shortcut ^> Advanced ^> Run as Administrator
echo.
echo.
echo Alternatively, a single run "Run as Administrator"
echo or in the Schedule tasks with highest privileges
pause > nul
goto:eof
:Administrator_OK
REM Some next lines code ...
还有两种方法——快速和向后兼容。
fltmc >nul 2>&1 && (
echo has admin permissions
) || (
echo has NOT admin permissions
)
fltmc命令在自XP以来的每个windows系统上都可用,所以这应该是相当可移植的。
在XP,8.1,7上测试的另一个真正快速的解决方案-有一个特定的变量=::,仅当控制台会话没有管理特权时才会显示。因为在它的名称中创建包含=的变量并不容易,这是一种相对可靠的检查管理权限的方法(它不调用外部可执行文件,所以它执行得很好)
setlocal enableDelayedExpansion
set "dv==::"
if defined !dv! (
echo has NOT admin permissions
) else (
echo has admin permissions
)
如果你想通过命令行直接使用,而不是从批处理文件,你可以使用:
set ^"|find "::"||echo has admin permissions
Net user %username% >nul 2>&1 && & echo admin || echo not admin