沒有,內核不需要完整性級別和升降式的令牌與管理員組的狀態相匹配。這意味着具有高完整性級別或TokenElevationTypeFull的進程不一定具有管理員訪問權限。
尤其注意,使用runas /trustlevel:0x20000
從管理命令提示符下將導致沒有管理員權限,但仍然具有較高的完整性和運行(如果啓用UAC)將有TokenElevationTypeFull一個過程。 ()我認爲這代表runas
中的一個錯誤。
此示例代碼演示了該行爲;如果以管理員權限運行,它將啓動管理員組(除了SeChangeNotifyPrivilege之外的所有權限)的子進程,但仍然以高完整性和TokenElevationTypeFull運行。
#include <Windows.h>
#include <Sddl.h>
#include <stdio.h>
PSID admins_sid;
void get_membership(HANDLE token)
{
BOOL is_enabled;
HANDLE itoken;
if (!DuplicateToken(token, SecurityIdentification, &itoken))
{
printf("DuplicateToken: %u\n", GetLastError());
return;
}
if (!CheckTokenMembership(itoken, admins_sid, &is_enabled))
{
printf("CheckTokenMembership: %u\n", GetLastError());
CloseHandle(itoken);
return;
}
CloseHandle(itoken);
printf("Administrators group enabled: %u\n", is_enabled);
return;
}
void get_integrity(HANDLE token)
{
char buffer[4096];
char * stringsid;
TOKEN_MANDATORY_LABEL *token_mandatory_label = (TOKEN_MANDATORY_LABEL *)buffer;
DWORD dw;
if (!GetTokenInformation(token, TokenIntegrityLevel, buffer, sizeof(buffer), &dw))
{
printf("GetTokenInformation: %u\n", GetLastError());
return;
}
if (!ConvertSidToStringSidA(token_mandatory_label->Label.Sid, &stringsid))
{
printf("ConvertSidToStringSid: %u\n", GetLastError());
return;
}
printf("SID: %s\n", stringsid);
}
void get_elevation(HANDLE token)
{
TOKEN_ELEVATION_TYPE elevation;
DWORD dw;
if (!GetTokenInformation(token,
TokenElevationType, &elevation, sizeof(elevation), &dw))
{
printf("GetTokenInformation: %u\n", GetLastError());
return;
}
printf("Elevation type : %u\n", (DWORD)elevation);
}
void test(void)
{
HANDLE token1, token2;
SID_AND_ATTRIBUTES sids_to_disable;
STARTUPINFOA si = {sizeof(STARTUPINFOA)};
PROCESS_INFORMATION pi;
if (!OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token1))
{
printf("OpenProcessToken: %u\n", GetLastError());
return;
}
printf("token1:\n");
get_membership(token1);
get_integrity(token1);
get_elevation(token1);
sids_to_disable.Attributes = 0;
sids_to_disable.Sid = admins_sid;
if (!CreateRestrictedToken(token1,
DISABLE_MAX_PRIVILEGE, 1, &sids_to_disable, 0, NULL, 0, NULL, &token2))
{
printf("CreateRestrictedToken: %u\n", GetLastError());
return;
}
printf("token2:\n");
get_membership(token2);
get_integrity(token2);
get_elevation(token2);
if (!CreateProcessAsUserA(token2,
NULL, "cmd", NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
{
printf("CreateProcessAsUser: %u\n", GetLastError());
return;
}
}
int main(int argc, char ** argv)
{
{
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
if(! AllocateAndInitializeSid(&SIDAuth, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&admins_sid))
{
printf("AllocateAndInitializeSid: %u\n", GetLastError());
return 1;
}
}
test();
return 0;
}
輸出從提升的命令提示符下運行:
token1:
Administrators group enabled: 1
SID: S-1-16-12288
Elevation type : 2
token2:
Administrators group enabled: 0
SID: S-1-16-12288
Elevation type : 2
如果從子進程再次運行示例代碼,你可以確認子進程也保留這些屬性:
token1:
Administrators group enabled: 0
SID: S-1-16-12288
Elevation type : 2
如果禁用UAC,則標高類型爲TokenElevationTypeDefault,否則結果相同:
token1:
Administrators group enabled: 1
SID: S-1-16-12288
Elevation type : 1
token2:
Administrators group enabled: 0
SID: S-1-16-12288
Elevation type : 1
正如預期的那樣,在有限令牌是這樣的:
token1:
Administrators group enabled: 0
SID: S-1-16-8192
Elevation type : 3
或者,如果你登錄的非管理員用戶,UAC是否啓用與否:
token1:
Administrators group enabled: 0
SID: S-1-16-8192
Elevation type : 1
(所有測試都在Windows 7 SP1 x64上運行。)
這在Windows 10 x64中對我來說是崩潰的。錯誤代碼是'STATUS_DLL_INIT_FAILED'。它發生在conhost.exe執行時,但在創建新窗口之前。我檢查了子cmd.exe和conhost.exe進程都將Administrators組設置爲只拒絕和高完整性。這可能是Windows 10中的一個錯誤,或者表明一個假設某個高完整性進程具有管理員權限。我的Windows 10版本過時(10.0.10074);它可能在更新的版本中工作。 – eryksun
@eryksun:你的意思是cmd.exe的子實例崩潰?聽起來像是與桌面/窗口站的權限有關。 (如果您不使用CREATE_NEW_CONSOLE,是否仍然會崩潰,讓它繼承現有的控制檯?)我已經在家裏安裝了最新的Windows 10安裝程序,如果我有時間我會在今晚嘗試它。 –
肯定是由於創建了一個新的控制檯。就像我說的,當新的conhost.exe實例啓動時,子cmd.exe失敗(可能是kernelbase的初始化,但我沒有檢查)。如果我刪除了'CREATE_NEW_CONSOLE'並等待進程句柄,那就好了。 – eryksun