vào quá trình XP mà chạy theo LocalSystem
(S-1-5-18) có tới DACL trên mã thông báo:
A 00 000F01FF S-1-5-18 'SYSTEM'
A 00 00020008 S-1-5-32-544 'Administrators'
Owner: S-1-5-32-544 'Administrators' @ 'BUILTIN' [Alias]
này có nghĩa là SYSTEM
có đầy đủ quyền truy cập TOKEN_ALL_ACCESS
(000F01FF
) và người dùng từ nhóm Quản trị viên (S-1-5-32-544
) có READ_DACL|TOKEN_QUERY
(00020008
) truy cập
quá trình Mà chạy theo bất kỳ một tài khoản khác có tiếp theo DACL trên Mã:
A 00 000F01FF S-1-5-18 'SYSTEM'
A 00 000F01FF <UserSid>
Owner: <UserSid>
nơi UserSid một số duy nhất (không nhóm!) Sid. nói cho các dịch vụ chạy không dưới LocalSystem nó trông giống như S-1-5-80- .., cho người dùng - S-1-5-21- .. điều này có nghĩa là dacl này cấp toàn quyền truy cập vào 'SYSTEM'
và bê tông người dùng. nhưng không cấp quyền truy cập vào nhóm Quản trị viên (S-1-5-32-544
). để bạn có thể mở bất kỳ mã thông báo quá trình nào chạy dưới cùng một người dùng. nhưng nếu bạn cố gắng mở toke quá trình, mà chạy dưới một người dùng khác (Sid khác) bạn không có bất kỳ quyền truy cập vào nó và có quyền truy cập bị từ chối. bạn thậm chí không thể đọc nó dacl (bạn không phải chủ sở hữu và không có READ_CONTROL
).
trong mã bạn thử mở mã thông báo từ một quy trình người dùng khác (sử dụng LogonUser
). trong mã thông báo dacl này - không có người dùng của bạn sid hoặc Quản trị viên sid. và kết quả là quyền truy cập bị từ chối
tuy nhiên nếu bạn có đặc quyền sở hữu - trước tiên bạn có thể mở mã thông báo WRITE_OWNER
và đặt làm chủ sở hữu, sau khi mở nó với WRITE_DAC
(chủ sở hữu có quyền truy cập này) và thay đổi dacl. hoặc, nếu bạn có sự cố gỡ rối, bạn có thể mạo danh luồng hệ thống, bằng cách sử dụng NtImpersonateThread
và có toàn quyền truy cập vào mã thông báo.
đang util:
#ifdef __cplusplus
extern "C" {
#endif
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenThread(
_Out_ PHANDLE ThreadHandle,
_In_ ULONG DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ PCLIENT_ID ClientId
);
extern "C"
NTSYSCALLAPI
NTSTATUS
NTAPI
NtImpersonateThread(
_In_ HANDLE ServerThreadHandle,
_In_ HANDLE ClientThreadHandle,
_In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos
);
#ifdef __cplusplus
}
#endif
ULONG gOsVersion;
volatile UCHAR guz;
OBJECT_ATTRIBUTES zoa = { sizeof(zoa) };
void GetVersionEx()
{
RTL_OSVERSIONINFOW VersionInformation;
RtlGetVersion(&VersionInformation);
gOsVersion = (VersionInformation.dwMajorVersion << 8) + VersionInformation.dwMinorVersion;
}
PCSTR GetSidNameUseName(::SID_NAME_USE snu)
{
switch (snu)
{
case SidTypeUser: return "User";
case SidTypeGroup: return "Group";
case SidTypeDomain: return "Domain";
case SidTypeAlias: return "Alias";
case SidTypeWellKnownGroup: return "WellKnownGroup";
case SidTypeDeletedAccount: return "DeletedAccount";
case SidTypeInvalid: return "Invalid";
case SidTypeUnknown: return "Unknown";
case SidTypeComputer: return "Computer";
case SidTypeLabel: return "Label";
case SidTypeLogonSession: return "LogonSession";
}
return "?";
}
#define MAX_DOMAIN_NAME_LEN 128
void DumpAcl(PACL acl, PCSTR caption)
{
DbgPrint(caption);
if (!acl)
{
DbgPrint("NULL\n");
return;
}
USHORT AceCount = acl->AceCount;
if (!AceCount)
{
DbgPrint("empty\n");
return;
}
DbgPrint("T FL AcessMsK Sid\n");
union {
PVOID pv;
PBYTE pb;
PACE_HEADER pah;
PACCESS_ALLOWED_ACE paaa;
};
pv = acl + 1;
char sz[16], sz2[16];
do
{
switch (pah->AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
case ACCESS_DENIED_ACE_TYPE:
case ACCESS_DENIED_CALLBACK_ACE_TYPE:
case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
break;
default:
DbgPrint("AceType=%u\n", pah->AceType);
continue;
}
UNICODE_STRING us;
if (0 <= RtlConvertSidToUnicodeString(&us, (PSID)&paaa->SidStart, TRUE))
{
WCHAR name[256], DomainName[MAX_DOMAIN_NAME_LEN];
ULONG cch = RTL_NUMBER_OF(name);
::SID_NAME_USE snu;
DWORD cchReferencedDomainName = MAX_DOMAIN_NAME_LEN;
if (!LookupAccountSidW(0, (PSID)&paaa->SidStart, name, &cch, DomainName, &cchReferencedDomainName, &snu))
{
name[0]=0;
}
ACCESS_MASK Mask = paaa->Mask;
sprintf(sz2, "%08X", Mask);
switch (pah->AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
sz[0] = 'A', sz[1] = 0;
break;
case ACCESS_DENIED_ACE_TYPE:
case ACCESS_DENIED_CALLBACK_ACE_TYPE:
sz[0] = 'D', sz[1] = 0;
break;
case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
sz[0] = 'L', sz[1] = 0;
sz2[0] = Mask & SYSTEM_MANDATORY_LABEL_NO_READ_UP ? 'R' : ' ';
sz2[1] = Mask & SYSTEM_MANDATORY_LABEL_NO_WRITE_UP ? 'W' : ' ';
sz2[2] = Mask & SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP ? 'E' : ' ';
sz2[3] = 0;
break;
default: __assume(false);
}
DbgPrint("%s %02X %s %wZ '%S'\n", sz, paaa->Header.AceFlags, sz2, &us, name);
RtlFreeUnicodeString(&us);
}
} while (pb += pah->AceSize, --AceCount);
}
void Dump(HANDLE hToken)
{
ULONG cb = 0, rcb = 128;
PVOID stack = alloca(guz);
union {
PVOID buf;
PSECURITY_DESCRIPTOR psd;
PTOKEN_USER ptu;
};
UNICODE_STRING us;
::SID_NAME_USE snu;
WCHAR name[256], DomainName[MAX_DOMAIN_NAME_LEN];
ULONG cch, cchReferencedDomainName;
NTSTATUS status;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (0 <= (status = NtQueryInformationToken(hToken, TokenUser, buf, cb, &rcb)))
{
if (0 <= RtlConvertSidToUnicodeString(&us, ptu->User.Sid, TRUE))
{
cch = RTL_NUMBER_OF(name);
cchReferencedDomainName = RTL_NUMBER_OF(DomainName);
if (!LookupAccountSidW(NULL, ptu->User.Sid, name, &cch, DomainName, &cchReferencedDomainName, &snu))
{
*name = 0;
*DomainName = 0;
}
DbgPrint("User: %wZ '%S' @ '%S' [%s]\r\n", &us, name, DomainName, GetSidNameUseName(snu));
RtlFreeUnicodeString(&us);
}
break;
}
} while (status == STATUS_BUFFER_TOO_SMALL);
if (0 > status)
{
DbgPrint("TokenUser=%x\n", status);
}
SECURITY_INFORMATION SecurityInformation = gOsVersion < _WIN32_WINNT_VISTA
? OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION
: OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|LABEL_SECURITY_INFORMATION;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (0 <= (status = NtQuerySecurityObject(hToken, SecurityInformation, psd, cb, &rcb)))
{
PACL Acl;
BOOLEAN bPresent, bDefault;
if (0 <= RtlGetDaclSecurityDescriptor(psd, &bPresent, &Acl, &bDefault))
{
DumpAcl(bPresent ? Acl : 0, "DACL:\n");
}
if (0 <= RtlGetSaclSecurityDescriptor(psd, &bPresent, &Acl, &bDefault))
{
DumpAcl(bPresent ? Acl : 0, "LABEL:\n");
}
PSID Owner;
if (0 <= RtlGetOwnerSecurityDescriptor(psd, &Owner, &bDefault) && Owner)
{
if (0 <= RtlConvertSidToUnicodeString(&us, Owner, TRUE))
{
cch = RTL_NUMBER_OF(name);
cchReferencedDomainName = RTL_NUMBER_OF(DomainName);
if (!LookupAccountSidW(NULL, Owner, name, &cch, DomainName, &cchReferencedDomainName, &snu))
{
*name = 0;
*DomainName = 0;
}
DbgPrint("Owner: %wZ '%S' @ '%S' [%s]\r\n", &us, name, DomainName, GetSidNameUseName(snu));
RtlFreeUnicodeString(&us);
}
}
}
} while (status == STATUS_BUFFER_TOO_SMALL);
if (0 > status)
{
DbgPrint("QuerySecurityObject=%x\n", status);
}
}
void Dump(ACCESS_MASK DesiredAccess, PSYSTEM_PROCESS_INFORMATION pspi)
{
HANDLE hProcess, hToken;
CLIENT_ID cid = { pspi->UniqueProcessId };
DbgPrint("==============\n%p %wZ\n", cid.UniqueProcess, &pspi->ImageName);
NTSTATUS status = NtOpenProcess(&hProcess, DesiredAccess, &zoa, &cid);
if (0 > status)
{
DbgPrint("OpenProcess=%x\n", status);
return;
}
status = NtOpenProcessToken(hProcess, READ_CONTROL|TOKEN_QUERY, &hToken);
NtClose(hProcess);
if (0 > status)
{
DbgPrint("OpenProcessToken=%x\n", status);
}
else
{
Dump(hToken);
NtClose(hToken);
}
}
void DumpProcessAndTokens(PVOID buf)
{
union {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
pv = buf;
ULONG NextEntryOffset = 0;
ACCESS_MASK DesiredAccess = gOsVersion < _WIN32_WINNT_VISTA
? PROCESS_QUERY_INFORMATION : PROCESS_QUERY_LIMITED_INFORMATION;
do
{
pb += NextEntryOffset;
if (pspi->UniqueProcessId)
{
Dump(DesiredAccess, pspi);
}
} while (NextEntryOffset = pspi->NextEntryOffset);
}
NTSTATUS GetSystemToken(PCLIENT_ID ClientId)
{
HANDLE hThread;
NTSTATUS status = NtOpenThread(&hThread, THREAD_DIRECT_IMPERSONATION, &zoa, ClientId);
if (0 <= status)
{
static SECURITY_QUALITY_OF_SERVICE sqos = {
sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE
};
if (0 <= (status = NtImpersonateThread(NtCurrentThread(), hThread, &sqos)))
{
HANDLE hToken;
if (0 <= (status = NtOpenThreadTokenEx(NtCurrentThread(), TOKEN_QUERY,FALSE, 0, &hToken)))
{
ULONG cb = 0, rcb = 32;
PVOID stack = alloca(guz);
union {
PVOID buf;
PTOKEN_USER ptu;
};
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (0 <= (status = NtQueryInformationToken(hToken, TokenUser, buf, cb, &rcb)))
{
static _SID LocalSystem = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_LOCAL_SYSTEM_RID } };
if (!RtlEqualSid(&LocalSystem, ptu->User.Sid))
{
RevertToSelf();
status = STATUS_SERVER_SID_MISMATCH;
}
break;
}
} while (status == STATUS_BUFFER_TOO_SMALL);
NtClose(hToken);
}
}
NtClose(hThread);
}
return status;
}
NTSTATUS ImpersonateLocalSystem(PVOID buf)
{
union {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
pv = buf;
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
if (pspi->UniqueProcessId && pspi->NumberOfThreads)
{
if (0 <= GetSystemToken(&pspi->TH->ClientId))
{
return STATUS_SUCCESS;
}
}
} while (NextEntryOffset = pspi->NextEntryOffset);
return STATUS_UNSUCCESSFUL;
}
void DumpProcessTokens()
{
BOOLEAN b;
NTSTATUS status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &b);
if (0 > status)
{
return ;
}
ULONG cb = 0x8000;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (PVOID buf = new UCHAR[cb])
{
if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
if (0 <= ImpersonateLocalSystem(buf))
{
DumpProcessAndTokens(buf);
RevertToSelf();
}
}
delete [] buf;
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
}
GetVersionEx();
DumpProcessTokens();
một số kết quả từ xp:
00000004 System
User: S-1-5-18 'SYSTEM' @ 'NT AUTHORITY' [User]
DACL:
T FL AcessMsK Sid
A 00 000F01FF S-1-5-18 'SYSTEM'
LABEL:
NULL
Owner: S-1-5-32-544 'Administrators' @ 'BUILTIN' [Alias]
==============
0000021C smss.exe
User: S-1-5-18 'SYSTEM' @ 'NT AUTHORITY' [User]
DACL:
T FL AcessMsK Sid
A 00 000F01FF S-1-5-18 'SYSTEM'
A 00 00020008 S-1-5-32-544 'Administrators'
LABEL:
NULL
Owner: S-1-5-32-544 'Administrators' @ 'BUILTIN' [Alias]
==============
000003B0 svchost.exe
User: S-1-5-20 'NETWORK SERVICE' @ 'NT AUTHORITY' [WellKnownGroup]
DACL:
T FL AcessMsK Sid
A 00 000F01FF S-1-5-18 'SYSTEM'
A 00 000F01FF S-1-5-80-979556362-403687129-3954533659-2335141334-1547273080 ''
LABEL:
NULL
Owner: S-1-5-80-979556362-403687129-3954533659-2335141334-1547273080 '' @ '' [WellKnownGroup]
==============
0000047C svchost.exe
User: S-1-5-20 'NETWORK SERVICE' @ 'NT AUTHORITY' [WellKnownGroup]
DACL:
T FL AcessMsK Sid
A 00 000F01FF S-1-5-18 'SYSTEM'
A 00 000F01FF S-1-5-20 'NETWORK SERVICE'
LABEL:
NULL
Owner: S-1-5-20 'NETWORK SERVICE' @ 'NT AUTHORITY' [WellKnownGroup]
==============
000004C4 svchost.exe
User: S-1-5-19 'LOCAL SERVICE' @ 'NT AUTHORITY' [WellKnownGroup]
DACL:
T FL AcessMsK Sid
A 00 000F01FF S-1-5-18 'SYSTEM'
A 00 000F01FF S-1-5-19 'LOCAL SERVICE'
LABEL:
NULL
Owner: S-1-5-19 'LOCAL SERVICE' @ 'NT AUTHORITY' [WellKnownGroup]
==============
000005EC explorer.exe
User: S-1-5-21-839522115-2025429265-725345543-500 'Administrator' @ '*' [User]
DACL:
T FL AcessMsK Sid
A 00 000F01FF S-1-5-21-839522115-2025429265-725345543-500 'Administrator'
A 00 000F01FF S-1-5-18 'SYSTEM'
LABEL:
NULL
Owner: S-1-5-21-839522115-2025429265-725345543-500 'Administrator' @ '*' [User]
PROCESS_QUERY_LIMITED_INFORMATION không tồn tại trên XP vì vậy nó nên thậm chí không nhận được rằng đến nay. – Anders
Bạn chính xác; đã cập nhật nguyên mẫu ... nhưng vẫn nhận được cùng một lỗi _Access bị từ chối_. – wulfgarpro
bạn có chắc chắn rằng sau khi quá trình mở với 'PROCESS_QUERY_INFORMATION' trên xp bạn vẫn có quyền truy cập bị từ chối không? không thể – RbMm