Skip to content

Commit c5183b4

Browse files
committed
Added object list to access check.
1 parent 098b5d1 commit c5183b4

2 files changed

Lines changed: 64 additions & 8 deletions

File tree

NtApiDotNet/NtSecurity.cs

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -518,19 +518,42 @@ private static NtResult<NtToken> DuplicateForAccessCheck(NtToken token, bool thr
518518
}
519519
}
520520

521+
private static SafeArrayBuffer<ObjectTypeList> ConvertObjectTypes(IEnumerable<ObjectTypeEntry> object_types)
522+
{
523+
if (object_types == null || !object_types.Any())
524+
return SafeArrayBuffer<ObjectTypeList>.Null;
525+
526+
var guids = object_types.Select(o => o.ObjectType).ToArray();
527+
var ret = new SafeArrayBuffer<ObjectTypeList>(new ObjectTypeList[guids.Length], guids.Length * 16);
528+
try
529+
{
530+
IntPtr ptr = ret.Data.DangerousGetHandle();
531+
var arr = object_types.Select((t, i) => new ObjectTypeList() { Level = (short)t.Level, ObjectType = ptr + (i * 16) }).ToArray();
532+
ret.WriteArray(0, arr, 0, arr.Length);
533+
ret.Data.WriteArray(0, guids, 0, guids.Length);
534+
return ret;
535+
}
536+
catch
537+
{
538+
ret?.Dispose();
539+
throw;
540+
}
541+
}
542+
521543
/// <summary>
522544
/// Do an access check between a security descriptor and a token to determine the allowed access.
523545
/// </summary>
524546
/// <param name="sd">The security descriptor</param>
525547
/// <param name="token">The access token.</param>
526-
/// <param name="access_rights">The set of access rights to check against</param>
548+
/// <param name="desired_access">The set of access rights to check against</param>
527549
/// <param name="principal">An optional principal SID used to replace the SELF SID in a security descriptor.</param>
528550
/// <param name="generic_mapping">The type specific generic mapping (get from corresponding NtType entry).</param>
551+
/// <param name="object_types">List of object types to check against.</param>
529552
/// <param name="throw_on_error">True to throw on error.</param>
530553
/// <returns>The result of the access check.</returns>
531554
/// <exception cref="NtException">Thrown if an error occurred in the access check.</exception>
532555
public static NtResult<AccessCheckResult> AccessCheck(SecurityDescriptor sd, NtToken token,
533-
AccessMask access_rights, Sid principal, GenericMapping generic_mapping,
556+
AccessMask desired_access, Sid principal, GenericMapping generic_mapping, IEnumerable<ObjectTypeEntry> object_types,
534557
bool throw_on_error)
535558
{
536559
if (sd == null)
@@ -543,7 +566,7 @@ public static NtResult<AccessCheckResult> AccessCheck(SecurityDescriptor sd, NtT
543566
throw new ArgumentNullException("token");
544567
}
545568

546-
if (access_rights.IsEmpty)
569+
if (desired_access.IsEmpty)
547570
{
548571
return new AccessCheckResult(NtStatus.STATUS_ACCESS_DENIED, 0, null).CreateResult();
549572
}
@@ -558,13 +581,14 @@ public static NtResult<AccessCheckResult> AccessCheck(SecurityDescriptor sd, NtT
558581
}
559582
var self_sid = list.AddResource(principal?.ToSafeBuffer() ?? SafeSidBufferHandle.Null);
560583
var privs = list.AddResource(new SafePrivilegeSetBuffer());
584+
var object_type_list = list.AddResource(ConvertObjectTypes(object_types));
561585
int repeat_count = 1;
562586

563587
while (true)
564588
{
565589
int buffer_length = privs.Length;
566-
NtStatus status = NtSystemCalls.NtAccessCheckByType(sd_buffer, self_sid, imp_token.Result.Handle, access_rights,
567-
SafeHGlobalBuffer.Null, 0, ref generic_mapping, privs,
590+
NtStatus status = NtSystemCalls.NtAccessCheckByType(sd_buffer, self_sid, imp_token.Result.Handle, desired_access,
591+
object_type_list, 0, ref generic_mapping, privs,
568592
ref buffer_length, out AccessMask granted_access, out NtStatus result_status);
569593
if (repeat_count == 0 || status != NtStatus.STATUS_BUFFER_TOO_SMALL)
570594
{
@@ -583,15 +607,33 @@ public static NtResult<AccessCheckResult> AccessCheck(SecurityDescriptor sd, NtT
583607
/// </summary>
584608
/// <param name="sd">The security descriptor</param>
585609
/// <param name="token">The access token.</param>
586-
/// <param name="access_rights">The set of access rights to check against</param>
610+
/// <param name="desired_access">The set of access rights to check against</param>
611+
/// <param name="principal">An optional principal SID used to replace the SELF SID in a security descriptor.</param>
612+
/// <param name="generic_mapping">The type specific generic mapping (get from corresponding NtType entry).</param>
613+
/// <param name="throw_on_error">True to throw on error.</param>
614+
/// <returns>The result of the access check.</returns>
615+
/// <exception cref="NtException">Thrown if an error occurred in the access check.</exception>
616+
public static NtResult<AccessCheckResult> AccessCheck(SecurityDescriptor sd, NtToken token,
617+
AccessMask desired_access, Sid principal, GenericMapping generic_mapping,
618+
bool throw_on_error)
619+
{
620+
return AccessCheck(sd, token, desired_access, principal, generic_mapping, null, throw_on_error);
621+
}
622+
623+
/// <summary>
624+
/// Do an access check between a security descriptor and a token to determine the allowed access.
625+
/// </summary>
626+
/// <param name="sd">The security descriptor</param>
627+
/// <param name="token">The access token.</param>
628+
/// <param name="desired_access">The set of access rights to check against</param>
587629
/// <param name="principal">An optional principal SID used to replace the SELF SID in a security descriptor.</param>
588630
/// <param name="generic_mapping">The type specific generic mapping (get from corresponding NtType entry).</param>
589631
/// <returns>The result of the access check.</returns>
590632
/// <exception cref="NtException">Thrown if an error occurred in the access check.</exception>
591633
public static AccessCheckResult AccessCheck(SecurityDescriptor sd, NtToken token,
592-
AccessMask access_rights, Sid principal, GenericMapping generic_mapping)
634+
AccessMask desired_access, Sid principal, GenericMapping generic_mapping)
593635
{
594-
return AccessCheck(sd, token, access_rights, principal, generic_mapping, true).Result;
636+
return AccessCheck(sd, token, desired_access, principal, generic_mapping, true).Result;
595637
}
596638

597639
/// <summary>

NtApiDotNet/NtSecurityNative.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,20 @@ public enum AppModelPolicy_PolicyValue
542542
ConvertCallerTokenToUserTokenForDeployment_ConvertTokenToUserToken = 0x2C0001,
543543
};
544544

545+
[StructLayout(LayoutKind.Sequential)]
546+
public struct ObjectTypeList
547+
{
548+
public short Level;
549+
public short Sbz;
550+
public IntPtr ObjectType;
551+
}
552+
553+
public class ObjectTypeEntry
554+
{
555+
public int Level { get; set; }
556+
public Guid ObjectType { get; set; }
557+
}
558+
545559
public static partial class NtRtl
546560
{
547561
public const uint SecurityDescriptorRevision = 1;

0 commit comments

Comments
 (0)