| | 1 | | using System; |
| | 2 | | using System.Runtime.InteropServices; |
| | 3 | | using System.Security; |
| | 4 | | using System.Security.Principal; |
| | 5 | | using SharpHoundRPC.Handles; |
| | 6 | | using SharpHoundRPC.Shared; |
| | 7 | |
|
| | 8 | | namespace SharpHoundRPC.LSANative |
| | 9 | | { |
| | 10 | | [SuppressUnmanagedCodeSecurity] |
| | 11 | | public class LSAMethods |
| | 12 | | { |
| | 13 | | internal static (NtStatus status, LSAHandle policyHandle) LsaOpenPolicy(string computerName, |
| | 14 | | LSAEnums.LsaOpenMask desiredAccess) |
| 0 | 15 | | { |
| 0 | 16 | | var us = new SharedStructs.UnicodeString(computerName); |
| 0 | 17 | | var objectAttributes = default(LSAStructs.ObjectAttributes); |
| 0 | 18 | | var status = LsaOpenPolicy(ref us, ref objectAttributes, desiredAccess, out var policyHandle); |
| | 19 | |
|
| 0 | 20 | | return (status, policyHandle); |
| 0 | 21 | | } |
| | 22 | |
|
| | 23 | | [DllImport("advapi32.dll")] |
| | 24 | | private static extern NtStatus LsaOpenPolicy( |
| | 25 | | ref SharedStructs.UnicodeString server, |
| | 26 | | ref LSAStructs.ObjectAttributes objectAttributes, |
| | 27 | | LSAEnums.LsaOpenMask desiredAccess, |
| | 28 | | out LSAHandle policyHandle |
| | 29 | | ); |
| | 30 | |
|
| | 31 | | [DllImport("advapi32.dll")] |
| | 32 | | internal static extern NtStatus LsaClose( |
| | 33 | | IntPtr handle |
| | 34 | | ); |
| | 35 | |
|
| | 36 | | [DllImport("advapi32.dll")] |
| | 37 | | internal static extern NtStatus LsaFreeMemory( |
| | 38 | | IntPtr buffer |
| | 39 | | ); |
| | 40 | |
|
| | 41 | | internal static (NtStatus status, LSAPointer pointer) LsaQueryInformationPolicy(LSAHandle policyHandle, |
| | 42 | | LSAEnums.LSAPolicyInformation policyInformation) |
| 0 | 43 | | { |
| 0 | 44 | | var status = LsaQueryInformationPolicy(policyHandle, policyInformation, out var pointer); |
| | 45 | |
|
| 0 | 46 | | return (status, pointer); |
| 0 | 47 | | } |
| | 48 | |
|
| | 49 | | [DllImport("advapi32.dll")] |
| | 50 | | private static extern NtStatus LsaQueryInformationPolicy( |
| | 51 | | LSAHandle policyHandle, |
| | 52 | | LSAEnums.LSAPolicyInformation policyInformation, |
| | 53 | | out LSAPointer buffer |
| | 54 | | ); |
| | 55 | |
|
| | 56 | | internal static (NtStatus status, LSAPointer sids, int count) LsaEnumerateAccountsWithUserRight( |
| | 57 | | LSAHandle policyHandle, |
| | 58 | | string userRight) |
| 0 | 59 | | { |
| 0 | 60 | | var arr = new SharedStructs.UnicodeString[1]; |
| 0 | 61 | | arr[0] = new SharedStructs.UnicodeString(userRight); |
| | 62 | |
|
| 0 | 63 | | var status = LsaEnumerateAccountsWithUserRight(policyHandle, arr, out var sids, out var count); |
| | 64 | |
|
| 0 | 65 | | return (status, sids, count); |
| 0 | 66 | | } |
| | 67 | |
|
| | 68 | | [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true)] |
| | 69 | | private static extern NtStatus LsaEnumerateAccountsWithUserRight( |
| | 70 | | LSAHandle policyHandle, |
| | 71 | | SharedStructs.UnicodeString[] userRight, |
| | 72 | | out LSAPointer sids, |
| | 73 | | out int count |
| | 74 | | ); |
| | 75 | |
|
| | 76 | | internal static (NtStatus status, LSAPointer referencedDomains, LSAPointer names, int count) |
| | 77 | | LsaLookupSids(LSAHandle policyHandle, |
| | 78 | | LSAPointer sids, int count) |
| 0 | 79 | | { |
| 0 | 80 | | var status = LsaLookupSids(policyHandle, count, sids, out var referencedDomains, out var names); |
| 0 | 81 | | return (status, referencedDomains, names, count); |
| 0 | 82 | | } |
| | 83 | |
|
| | 84 | | internal static (NtStatus status, LSAPointer referencedDomains, LSAPointer names, int count) |
| | 85 | | LsaLookupSids(LSAHandle policyHandle, |
| | 86 | | SecurityIdentifier[] sids) |
| 0 | 87 | | { |
| 0 | 88 | | var count = sids.Length; |
| 0 | 89 | | if (count == 0) |
| 0 | 90 | | return (NtStatus.StatusInvalidParameter, null, null, 0); |
| | 91 | |
|
| 0 | 92 | | var gcHandles = new GCHandle[count]; |
| 0 | 93 | | var pSids = new IntPtr[count]; |
| | 94 | |
|
| 0 | 95 | | for (var i = 0; i < count; i++) |
| 0 | 96 | | { |
| 0 | 97 | | var sid = sids[i]; |
| 0 | 98 | | var b = new byte[sid.BinaryLength]; |
| 0 | 99 | | sid.GetBinaryForm(b, 0); |
| 0 | 100 | | gcHandles[i] = GCHandle.Alloc(b, GCHandleType.Pinned); |
| 0 | 101 | | pSids[i] = gcHandles[i].AddrOfPinnedObject(); |
| 0 | 102 | | } |
| | 103 | |
|
| | 104 | | try |
| 0 | 105 | | { |
| 0 | 106 | | var status = LsaLookupSids(policyHandle, count, pSids, out var referencedDomains, out var names); |
| 0 | 107 | | return (status, referencedDomains, names, count); |
| | 108 | | } |
| | 109 | | finally |
| 0 | 110 | | { |
| 0 | 111 | | foreach (var handle in gcHandles) |
| 0 | 112 | | if (handle.IsAllocated) |
| 0 | 113 | | handle.Free(); |
| 0 | 114 | | } |
| 0 | 115 | | } |
| | 116 | |
|
| | 117 | | [DllImport("advapi32.dll")] |
| | 118 | | private static extern NtStatus LsaLookupSids( |
| | 119 | | LSAHandle policyHandle, |
| | 120 | | int count, |
| | 121 | | LSAPointer sidArray, |
| | 122 | | out LSAPointer referencedDomains, |
| | 123 | | out LSAPointer names |
| | 124 | | ); |
| | 125 | |
|
| | 126 | | [DllImport("advapi32.dll")] |
| | 127 | | private static extern NtStatus LsaLookupSids( |
| | 128 | | LSAHandle policyHandle, |
| | 129 | | int count, |
| | 130 | | [MarshalAs(UnmanagedType.LPArray)] IntPtr[] sidArray, |
| | 131 | | out LSAPointer referencedDomains, |
| | 132 | | out LSAPointer names |
| | 133 | | ); |
| | 134 | | } |
| | 135 | | } |