public static List <string> GetGroupUsers(string groupName) { List <string> myList = new List <string>(); int EntriesRead; int TotalEntries; IntPtr Resume = IntPtr.Zero; IntPtr buffer; int val = NetLocalGroupGetMembers(null, groupName, 2, out buffer, -1, out EntriesRead, out TotalEntries, Resume); do { if (EntriesRead > 0) { LOCALGROUP_MEMBERS_INFO_2[] Members = new LOCALGROUP_MEMBERS_INFO_2[EntriesRead]; IntPtr iter = buffer; for (int i = 0; i < EntriesRead; i++) { Members[i] = (LOCALGROUP_MEMBERS_INFO_2)Marshal.PtrToStructure(iter, typeof(LOCALGROUP_MEMBERS_INFO_2)); iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LOCALGROUP_MEMBERS_INFO_2))); myList.Add(Members[i].lgrmi2_domainandname); } NetApiBufferFree(buffer); } } while (val != 0 && (val = NetLocalGroupGetMembers(null, groupName, 2, out buffer, -1, out EntriesRead, out TotalEntries, Resume)) == 234); return(myList); }
internal static extern NET_API_STATUS NetLocalGroupGetMembers( string servername, string localgroupname, int level, ref LOCALGROUP_MEMBERS_INFO_2 bufptr, int prefmaxlen, ref int entriesread, ref int totalentries, ref IntPtr resumehandle);
private List <LocalAdminInfo> LocalGroupAPI(string Target, string Group, string DomainSID) { int QueryLevel = 2; IntPtr PtrInfo = IntPtr.Zero; int EntriesRead = 0; int TotalRead = 0; IntPtr ResumeHandle = IntPtr.Zero; List <LocalAdminInfo> users = new List <LocalAdminInfo>(); int val = NetLocalGroupGetMembers(Target, Group, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ResumeHandle); if (EntriesRead > 0) { LOCALGROUP_MEMBERS_INFO_2[] Members = new LOCALGROUP_MEMBERS_INFO_2[EntriesRead]; IntPtr iter = PtrInfo; for (int i = 0; i < EntriesRead; i++) { Members[i] = (LOCALGROUP_MEMBERS_INFO_2)Marshal.PtrToStructure(iter, typeof(LOCALGROUP_MEMBERS_INFO_2)); iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LOCALGROUP_MEMBERS_INFO_2))); string ObjectType; string ObjectName = Members[i].lgrmi2_domainandname; if (ObjectName.Split('\\')[1].Equals("")) { continue; } if (ObjectName.EndsWith("$")) { ObjectType = "computer"; } else { ObjectType = Members[i].lgrmi2_sidusage == 1 ? "user" : "group"; } string ObjectSID; ConvertSidToStringSid((IntPtr)Members[i].lgrmi2_sid, out ObjectSID); users.Add(new LocalAdminInfo { server = Target, objectname = ObjectName, sid = ObjectSID, objecttype = ObjectType }); } NetApiBufferFree(PtrInfo); string MachineSID = users.First(s => s.sid.EndsWith("-500") && s.sid.StartsWith(DomainSID)).sid; MachineSID = MachineSID.Substring(0, MachineSID.LastIndexOf("-")); users = users.Where(element => element.sid.StartsWith(DomainSID)).ToList(); } return(users); }
public static IEnumerable <Principal>?GetLocalGroupMembers(string?computerName, string groupName) { // returns the "DOMAIN\user" members for a specified local group name // adapted from boboes' code at https://stackoverflow.com/questions/33935825/pinvoke-netlocalgroupgetmembers-runs-into-fatalexecutionengineerror/33939889#33939889 var members = new List <Principal>(); var retVal = NetLocalGroupGetMembers(computerName, groupName, 2, out var bufPtr, -1, out var EntriesRead, out var TotalEntries, out var Resume); if (retVal != 0) { var errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message; throw new Exception("Error code " + retVal + ": " + errorMessage); } if (EntriesRead == 0) { return(members); } var names = new string[EntriesRead]; var memberInfo = new LOCALGROUP_MEMBERS_INFO_2[EntriesRead]; var iter = bufPtr; for (var i = 0; i < EntriesRead; i++) { memberInfo[i] = (LOCALGROUP_MEMBERS_INFO_2)Marshal.PtrToStructure(iter, typeof(LOCALGROUP_MEMBERS_INFO_2)); //x64 safe iter = new IntPtr(iter.ToInt64() + Marshal.SizeOf(typeof(LOCALGROUP_MEMBERS_INFO_2))); var nameParts = memberInfo[i].lgrmi2_domainandname.Split('\\'); var domain = nameParts[0]; var userName = ""; if (nameParts.Length > 1) { userName = nameParts[1]; } Advapi32.ConvertSidToStringSid(memberInfo[i].lgrmi2_sid, out var sid); members.Add(new Principal( sid, memberInfo[i].lgrmi2_sidusage, userName, domain )); } NetApiBufferFree(bufPtr); return(members); }
public static LOCALGROUP_MEMBERS_INFO_2[] GetNetLocalGroupGetMembers(string hostname, string localgroup) { int EntriesRead, TotalEntries; IntPtr ResumeHandle = IntPtr.Zero; try { var result = NetLocalGroupGetMembers(hostname, localgroup, 2, out IntPtr BufferPtr, -1, out EntriesRead, out TotalEntries, ResumeHandle); if (EntriesRead > 0) { var BufferOffset = BufferPtr; var Results = new LOCALGROUP_MEMBERS_INFO_2[EntriesRead]; LOCALGROUP_MEMBERS_INFO_2 groupInfo = new LOCALGROUP_MEMBERS_INFO_2(); for (int i = 0; i < EntriesRead; i++) { Results[i] = (LOCALGROUP_MEMBERS_INFO_2)Marshal.PtrToStructure(BufferOffset, groupInfo.GetType()); BufferOffset = (IntPtr)(BufferOffset.ToInt64() + Marshal.SizeOf(groupInfo)); } NetApiBufferFree(BufferPtr); return(Results); } else { return(null); } } catch (Exception e) { Helper.PrintYellow("[x] ERROR:" + e.Message); return(null); } }
static void DumpLocalAdminMembers(string computer, string group) { IntPtr bufPtr = IntPtr.Zero; int entriesRead = 0; int totalEntries = 0; int resumeHandle = 0; int output = NetLocalGroupGetMembers(computer, group, 2, out bufPtr, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, ref resumeHandle); long offset = bufPtr.ToInt64(); if (output == NERR_Success && offset > 0) { int position = Marshal.SizeOf(typeof(LOCALGROUP_MEMBERS_INFO_2)); for (int i = 0; i < entriesRead; i++) { IntPtr nextPtr = new IntPtr(offset); LOCALGROUP_MEMBERS_INFO_2 data = (LOCALGROUP_MEMBERS_INFO_2)Marshal.PtrToStructure(nextPtr, typeof(LOCALGROUP_MEMBERS_INFO_2)); offset = nextPtr.ToInt64() + position; Console.WriteLine(data.lgrmi2_domainandname); } NetApiBufferFree(bufPtr); } }
public static string[] GetLocalGroupMembers(string server, string group) { try { string[] names = null; int EntriesRead, TotalEntries, Resume = 0; IntPtr bufPtr; int val = NetLocalGroupGetMembers(server, group, 2, out bufPtr, -1, out EntriesRead, out TotalEntries, ref Resume); if(EntriesRead > 0) { names = new string[EntriesRead]; LOCALGROUP_MEMBERS_INFO_2[] Members = new LOCALGROUP_MEMBERS_INFO_2[EntriesRead]; IntPtr iter = bufPtr; for(int i=0; i < EntriesRead; i++) { Members[i] = (LOCALGROUP_MEMBERS_INFO_2)Marshal.PtrToStructure(iter, typeof(LOCALGROUP_MEMBERS_INFO_2)); iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LOCALGROUP_MEMBERS_INFO_2))); names[i] = Members[i].lgrmi2_domainandname; } NetApiBufferFree(bufPtr); } return names; } catch(Exception) { throw; } }
List <LocalAdminInfo> LocalGroupAPI(string Target, string group, string DomainSID) { int QueryLevel = 2; IntPtr PtrInfo = IntPtr.Zero; IntPtr ResumeHandle = IntPtr.Zero; string MachineSID = "DUMMYSTRING"; Type LMI2 = typeof(LOCALGROUP_MEMBERS_INFO_2); List <LocalAdminInfo> users = new List <LocalAdminInfo>(); int val = NetLocalGroupGetMembers(Target, group, QueryLevel, out PtrInfo, -1, out int EntriesRead, out int TotalRead, ResumeHandle); if (val == 1722) { throw new SystemDownException(); } if (val != 0) { throw new APIFailedException(); } if (EntriesRead > 0) { IntPtr iter = PtrInfo; LOCALGROUP_MEMBERS_INFO_2[] list = new LOCALGROUP_MEMBERS_INFO_2[EntriesRead]; for (int i = 0; i < EntriesRead; i++) { LOCALGROUP_MEMBERS_INFO_2 data = (LOCALGROUP_MEMBERS_INFO_2)Marshal.PtrToStructure(iter, LMI2); list[i] = data; iter = (IntPtr)(iter.ToInt64() + Marshal.SizeOf(LMI2)); } List <API_Encapsulator> newlist = new List <API_Encapsulator>(); for (int i = 0; i < EntriesRead; i++) { ConvertSidToStringSid(list[i].lgrmi2_sid, out string s); newlist.Add(new API_Encapsulator { Lgmi2 = list[i], sid = s }); } NetApiBufferFree(PtrInfo); foreach (API_Encapsulator data in newlist) { if (data.sid == null) { continue; } if (data.sid.EndsWith("-500", StringComparison.CurrentCulture) && !(data.sid.StartsWith(DomainSID, StringComparison.CurrentCulture))) { MachineSID = data.sid.Substring(0, data.sid.LastIndexOf("-", StringComparison.CurrentCulture)); break; } } foreach (API_Encapsulator data in newlist) { string ObjectName = data.Lgmi2.lgrmi2_domainandname; if (!ObjectName.Contains("\\")) { continue; } string[] sp = ObjectName.Split('\\'); if (sp[1].Equals("")) { continue; } if (ObjectName.StartsWith("NT Authority", StringComparison.CurrentCulture)) { continue; } string ObjectType; string ObjectSID = data.sid; if (ObjectSID == null || ObjectSID.StartsWith(MachineSID, StringComparison.Ordinal)) { continue; } DBObject obj; switch (data.Lgmi2.lgrmi2_sidusage) { case (SID_NAME_USE.SidTypeUser): manager.FindUserBySID(ObjectSID, out obj, CurrentDomain); ObjectType = "user"; break; case (SID_NAME_USE.SidTypeComputer): manager.FindComputerBySID(ObjectSID, out obj, CurrentDomain); ObjectType = "computer"; break; case (SID_NAME_USE.SidTypeGroup): manager.FindGroupBySID(ObjectSID, out obj, CurrentDomain); ObjectType = "group"; break; default: obj = null; ObjectType = null; break; } if (obj == null) { DirectoryEntry entry = new DirectoryEntry($"LDAP://<SID={ObjectSID}>"); try { obj = entry.ConvertToDB(); if (obj == null) { Console.WriteLine("c"); continue; } manager.InsertRecord(obj); } catch (COMException) { //We couldn't resolve the object, so fallback to manual determination string domain = sp[0]; string username = sp[1]; Helpers.DomainMap.TryGetValue(domain, out domain); if (ObjectType == "user" || ObjectType == "group") { obj = new DBObject { BloodHoundDisplayName = $"{username}@{domain}".ToUpper(), Type = "user" }; } else { obj = new DBObject { Type = "computer", BloodHoundDisplayName = $"{username.Substring(0, username.Length - 1)}.{domain}" }; } } } users.Add(new LocalAdminInfo { Server = Target, ObjectName = obj.BloodHoundDisplayName, ObjectType = obj.Type }); } } return(users); }