// the host enumeration block we're using to enumerate all servers private static IEnumerable <string> _Find_LocalAdminAccess(string[] ComputerName, IntPtr TokenHandle) { var LogonToken = IntPtr.Zero; if (TokenHandle != IntPtr.Zero) { // impersonate the the token produced by LogonUser()/Invoke-UserImpersonation LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { TokenHandle = TokenHandle, Quiet = true }); } var TargetComputers = new List <string>(); foreach (var TargetComputer in ComputerName) { var Up = TestConnection.Ping(TargetComputer, 1); if (Up) { // check if the current user has local admin access to this server var Access = TestAdminAccess.Test_AdminAccess(new Args_Test_AdminAccess { ComputerName = new[] { TargetComputer } }).FirstOrDefault(); if (Access != null && Access.IsAdmin) { TargetComputers.Add(TargetComputer); } } } if (TokenHandle != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(TargetComputers); }
public static IEnumerable <AdminAccess> Test_AdminAccess(Args_Test_AdminAccess args = null) { if (args == null) { args = new Args_Test_AdminAccess(); } IntPtr LogonToken = IntPtr.Zero; if (args.Credential != null) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } var IsAdmins = new List <AdminAccess>(); foreach (var Computer in args.ComputerName) { // 0xF003F - SC_MANAGER_ALL_ACCESS // http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx var Handle = NativeMethods.OpenSCManagerW($@"\\{Computer}", "ServicesActive", 0xF003F); var LastError = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); var IsAdmin = new AdminAccess { ComputerName = Computer }; // if we get a non-zero handle back, everything was successful if (Handle != IntPtr.Zero) { NativeMethods.CloseServiceHandle(Handle); IsAdmin.IsAdmin = true; } else { Logger.Write_Verbose($@"[Test-AdminAccess] Error: {new System.ComponentModel.Win32Exception((int)LastError).Message}"); IsAdmin.IsAdmin = false; } IsAdmins.Add(IsAdmin); } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(IsAdmins); }
// the host enumeration block we're using to enumerate all servers private static IEnumerable <object> _Find_DomainLocalGroupMember(string[] ComputerName, string GroupName, MethodType Method, IntPtr TokenHandle) { // Add check if user defaults to/selects "Administrators" if (GroupName == "Administrators") { var AdminSecurityIdentifier = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.BuiltinAdministratorsSid, null); GroupName = AdminSecurityIdentifier.Translate(typeof(System.Security.Principal.NTAccount)).Value.Split('\\').LastOrDefault(); } var LogonToken = IntPtr.Zero; if (TokenHandle != IntPtr.Zero) { // impersonate the the token produced by LogonUser()/Invoke-UserImpersonation LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { TokenHandle = TokenHandle, Quiet = true }); } var Members = new List <object>(); foreach (var TargetComputer in ComputerName) { var Up = TestConnection.Ping(TargetComputer, 1); if (Up) { var NetLocalGroupMemberArguments = new Args_Get_NetLocalGroupMember { ComputerName = new[] { TargetComputer }, Method = Method, GroupName = GroupName }; var ret = GetNetLocalGroupMember.Get_NetLocalGroupMember(NetLocalGroupMemberArguments); if (ret != null) { Members.AddRange(ret); } } } if (TokenHandle != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(Members); }
public static IEnumerable <RDPSessionInfo> Get_NetRDPSession(Args_Get_NetRDPSession args = null) { if (args == null) { args = new Args_Get_NetRDPSession(); } IntPtr LogonToken = IntPtr.Zero; if (args.Credential != null) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } var RDPSessions = new List <RDPSessionInfo>(); foreach (var Computer in args.ComputerName) { // open up a handle to the Remote Desktop Session host var Handle = NativeMethods.WTSOpenServerEx(Computer); // if we get a non-zero handle back, everything was successful if (Handle != IntPtr.Zero) { // arguments for WTSEnumerateSessionsEx var ppSessionInfo = IntPtr.Zero; UInt32 pCount = 0; // get information on all current sessions UInt32 level = 1; var Result = NativeMethods.WTSEnumerateSessionsEx(Handle, ref level, 0, ref ppSessionInfo, ref pCount); var LastError = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); // locate the offset of the initial intPtr var Offset = ppSessionInfo.ToInt64(); if ((Result != 0) && (Offset > 0)) { // work out how much to increment the pointer by finding out the size of the structure var Increment = Marshal.SizeOf(typeof(NativeMethods.WTS_SESSION_INFO_1)); // parse all the result structures for (var i = 0; (i < pCount); i++) { // create a new int ptr at the given offset and cast the pointer as our result structure var NewIntPtr = new IntPtr(Offset); var Info = (NativeMethods.WTS_SESSION_INFO_1)Marshal.PtrToStructure(NewIntPtr, typeof(NativeMethods.WTS_SESSION_INFO_1)); var RDPSession = new RDPSessionInfo(); if (Info.pHostName != null) { RDPSession.ComputerName = Info.pHostName; } else { // if no hostname returned, use the specified hostname RDPSession.ComputerName = Computer; } RDPSession.SessionName = Info.pSessionName; if ((Info.pDomainName == null) || (Info.pDomainName == "")) { // if a domain isn't returned just use the username RDPSession.UserName = Info.pUserName; } else { RDPSession.UserName = $@"{Info.pDomainName}\{Info.pUserName}"; } RDPSession.ID = Info.SessionId; RDPSession.State = Info.State; var ppBuffer = IntPtr.Zero; uint pBytesReturned = 0; // query for the source client IP with WTSQuerySessionInformation // https://msdn.microsoft.com/en-us/library/aa383861(v=vs.85).aspx var Result2 = NativeMethods.WTSQuerySessionInformation(Handle, Info.SessionId, NativeMethods.WTS_INFO_CLASS.WTSClientAddress, out ppBuffer, out pBytesReturned); var LastError2 = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); if (Result2 == false) { Logger.Write_Verbose($@"[Get-NetRDPSession] Error: {new System.ComponentModel.Win32Exception((int)LastError2).Message}"); } else { var Offset2 = ppBuffer.ToInt64(); var NewIntPtr2 = new IntPtr(Offset2); var Info2 = (NativeMethods.WTS_CLIENT_ADDRESS)Marshal.PtrToStructure(NewIntPtr2, typeof(NativeMethods.WTS_CLIENT_ADDRESS)); string SourceIP; if (Info2.Address[2] != 0) { SourceIP = $@"{Info2.Address[2]}.{Info2.Address[3]}.{Info2.Address[4]}.{Info2.Address[5]}"; } else { SourceIP = null; } RDPSession.SourceIP = SourceIP; RDPSessions.Add(RDPSession); // free up the memory buffer NativeMethods.WTSFreeMemory(ppBuffer); Offset += Increment; } } // free up the memory result buffer NativeMethods.WTSFreeMemoryEx(WTS_TYPE_CLASS.WTSTypeSessionInfoLevel1, ppSessionInfo, pCount); } else { Logger.Write_Verbose($@"[Get-NetRDPSession] Error: {new System.ComponentModel.Win32Exception((int)LastError).Message}"); } // close off the service handle NativeMethods.WTSCloseServer(Handle); } else { Logger.Write_Verbose($@"[Get-NetRDPSession] Error opening the Remote Desktop Session Host (RD Session Host) server for: {Computer}"); } } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(RDPSessions); }
// the host enumeration block we're using to enumerate all servers private static IEnumerable <FoundFile> _Find_InterestingDomainShareFile(string[] ComputerName, string[] Include, string[] ExcludedShares, bool OfficeDocs, bool ExcludeHidden, bool FreshEXEs, bool CheckWriteAccess, DateTime?LastAccessTime, DateTime?LastWriteTime, DateTime?CreationTime, IntPtr TokenHandle) { var LogonToken = IntPtr.Zero; if (TokenHandle != IntPtr.Zero) { // impersonate the the token produced by LogonUser()/Invoke-UserImpersonation LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { TokenHandle = TokenHandle, Quiet = true }); } var FoundFiles = new List <FoundFile>(); foreach (var TargetComputer in ComputerName) { var SearchShares = new List <string>(); if (TargetComputer.StartsWith(@"\\")) { // if a share is passed as the server SearchShares.Add(TargetComputer); } else { var Up = TestConnection.Ping(TargetComputer, 1); if (Up) { // get the shares for this host and check what we find var Shares = GetNetShare.Get_NetShare(new Args_Get_NetShare { ComputerName = new[] { TargetComputer } }); foreach (var Share in Shares) { var ShareName = Share.Name; var Path = @"\\" + TargetComputer + @"\" + ShareName; // make sure we get a real share name back if ((!string.IsNullOrEmpty(ShareName)) && (ShareName.Trim() != "")) { // skip this share if it's in the exclude list if (!ExcludedShares.ContainsNoCase(ShareName)) { // check if the user has access to this path try { Directory.GetFiles(Path); SearchShares.Add(Path); } catch { Logger.Write_Verbose($@"[!] No access to {Path}"); } } } } } } foreach (var Share in SearchShares) { Logger.Write_Verbose($@"Searching share: {Share}"); var SearchArgs = new Args_Find_InterestingFile { Path = new[] { Share }, Include = Include }; if (OfficeDocs) { SearchArgs.OfficeDocs = OfficeDocs; } if (FreshEXEs) { SearchArgs.FreshEXEs = FreshEXEs; } if (LastAccessTime != null) { SearchArgs.LastAccessTime = LastAccessTime; } if (LastWriteTime != null) { SearchArgs.LastWriteTime = LastWriteTime; } if (CreationTime != null) { SearchArgs.CreationTime = CreationTime; } if (CheckWriteAccess) { SearchArgs.CheckWriteAccess = CheckWriteAccess; } FoundFiles.AddRange(Find_InterestingFile(SearchArgs)); } } if (TokenHandle != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(FoundFiles); }
public static IEnumerable <FoundFile> Find_InterestingDomainShareFile(Args_Find_InterestingDomainShareFile args = null) { if (args == null) { args = new Args_Find_InterestingDomainShareFile(); } var ComputerSearcherArguments = new Args_Get_DomainComputer { Properties = new[] { "dnshostname" }, Domain = args.ComputerDomain, LDAPFilter = args.ComputerLDAPFilter, SearchBase = args.ComputerSearchBase, OperatingSystem = args.OperatingSystem, ServicePack = args.ServicePack, SiteName = args.SiteName, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; string[] TargetComputers; if (args.ComputerName != null) { TargetComputers = args.ComputerName; } else { Logger.Write_Verbose($@"[Find-InterestingDomainShareFile] Querying computers in the domain"); TargetComputers = GetDomainComputer.Get_DomainComputer(ComputerSearcherArguments).Select(x => (x as LDAPProperty).dnshostname).ToArray(); } if (TargetComputers == null || TargetComputers.Length == 0) { throw new Exception("[Find-InterestingDomainShareFile] No hosts found to enumerate"); } Logger.Write_Verbose($@"[Find-InterestingDomainShareFile] TargetComputers length: {TargetComputers.Length}"); var LogonToken = IntPtr.Zero; if (args.Credential != null) { if (args.Delay != 0 || args.StopOnSuccess) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } else { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential, Quiet = true }); } } var rets = new List <FoundFile>(); // only ignore threading if -Delay is passed if (args.Delay != 0 || args.StopOnSuccess) { Logger.Write_Verbose($@"[Find-InterestingDomainShareFile] Total number of hosts: {TargetComputers.Count()}"); Logger.Write_Verbose($@"[Find-InterestingDomainShareFile] Delay: {args.Delay}, Jitter: {args.Jitter}"); var Counter = 0; var RandNo = new System.Random(); foreach (var TargetComputer in TargetComputers) { Counter = Counter + 1; // sleep for our semi-randomized interval System.Threading.Thread.Sleep(RandNo.Next((int)((1 - args.Jitter) * args.Delay), (int)((1 + args.Jitter) * args.Delay)) * 1000); Logger.Write_Verbose($@"[Find-InterestingDomainShareFile] Enumerating server {TargetComputer} ({Counter} of {TargetComputers.Count()})"); var ret = _Find_InterestingDomainShareFile(new[] { TargetComputer }, args.Include, args.ExcludedShares, args.OfficeDocs, /*args.ExcludeHidden*/ false, args.FreshEXEs, /*args.CheckWriteAccess*/ false, args.LastAccessTime, args.LastWriteTime, args.CreationTime, LogonToken); if (ret != null) { rets.AddRange(ret); } } } else { Logger.Write_Verbose($@"[Find-InterestingDomainShareFile] Using threading with threads: {args.Threads}"); // if we're using threading, kick off the script block with New-ThreadedFunction // if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params System.Threading.Tasks.Parallel.ForEach( TargetComputers, TargetComputer => { var ret = _Find_InterestingDomainShareFile(new[] { TargetComputer }, args.Include, args.ExcludedShares, args.OfficeDocs, /*args.ExcludeHidden*/ false, args.FreshEXEs, /*args.CheckWriteAccess*/ false, args.LastAccessTime, args.LastWriteTime, args.CreationTime, LogonToken); lock (rets) { if (ret != null) { rets.AddRange(ret); } } }); } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(rets); }
public static IEnumerable <object> Get_NetLocalGroupMember(Args_Get_NetLocalGroupMember args = null) { if (args == null) { args = new Args_Get_NetLocalGroupMember(); } var LogonToken = IntPtr.Zero; if (args.Credential != null) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } var LocalGroupMembers = new List <object>(); foreach (var Computer in args.ComputerName) { if (args.Method == MethodType.API) { // if we're using the Netapi32 NetLocalGroupGetMembers API call to get the local group information // arguments for NetLocalGroupGetMembers var QueryLevel = 2; var PtrInfo = IntPtr.Zero; var EntriesRead = 0; var TotalRead = 0; var ResumeHandle = IntPtr.Zero; // get the local user information var Result = NativeMethods.NetLocalGroupGetMembers(Computer, args.GroupName, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ResumeHandle); // locate the offset of the initial intPtr var Offset = PtrInfo.ToInt64(); var Members = new List <object>(); // 0 = success if ((Result == 0) && (Offset > 0)) { // Work out how much to increment the pointer by finding out the size of the structure var Increment = Marshal.SizeOf(typeof(LOCALGROUP_MEMBERS_INFO_2)); // parse all the result structures for (var i = 0; (i < EntriesRead); i++) { // create a new int ptr at the given offset and cast the pointer as our result structure var NewIntPtr = new System.IntPtr(Offset); var Info = (LOCALGROUP_MEMBERS_INFO_2)Marshal.PtrToStructure(NewIntPtr, typeof(LOCALGROUP_MEMBERS_INFO_2)); Offset = NewIntPtr.ToInt64(); Offset += Increment; var SidString = ""; var Result2 = NativeMethods.ConvertSidToStringSid(Info.lgrmi2_sid, out SidString); var LastError = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); if (!Result2) { Logger.Write_Verbose($@"[Get-NetLocalGroupMember] Error: {new System.ComponentModel.Win32Exception((int)Result).Message}"); } else { var Member = new LocalGroupMemberAPI { ComputerName = Computer, GroupName = args.GroupName, MemberName = Info.lgrmi2_domainandname, SID = SidString, IsGroup = Info.lgrmi2_sidusage == SID_NAME_USE.SidTypeGroup }; Members.Add(Member); } } // free up the result buffer NativeMethods.NetApiBufferFree(PtrInfo); // try to extract out the machine SID by using the -500 account as a reference var MachineSid = (Members.FirstOrDefault(x => (x as LocalGroupMemberAPI).SID.IsRegexMatch(".*-500") || (x as LocalGroupMemberAPI).SID.IsRegexMatch(".*-501")) as LocalGroupMemberAPI).SID; if (MachineSid != null) { MachineSid = MachineSid.Substring(0, MachineSid.LastIndexOf('-')); foreach (LocalGroupMemberAPI member in Members) { if (member.SID.IsRegexMatch(MachineSid)) { member.IsDomain = "false"; } else { member.IsDomain = "true"; } } } else { foreach (LocalGroupMemberAPI member in Members) { if (!member.SID.IsRegexMatch("S-1-5-21")) { member.IsDomain = "false"; } else { member.IsDomain = "UNKNOWN"; } } } LocalGroupMembers.AddRange(Members); } else { Logger.Write_Verbose($@"[Get-NetLocalGroupMember] Error: {new System.ComponentModel.Win32Exception((int)Result).Message}"); } } else { // otherwise we're using the WinNT service provider try { var GroupProvider = new System.DirectoryServices.DirectoryEntry($@"WinNT://{Computer}/{args.GroupName},group"); IEnumerable Members = (IEnumerable)GroupProvider.Invoke("Members"); foreach (var obj in Members) { var LocalUser = new System.DirectoryServices.DirectoryEntry(obj); var Member = new LocalGroupMemberWinNT { ComputerName = Computer, GroupName = args.GroupName }; var AdsPath = LocalUser.InvokeGet("AdsPath").ToString().Replace("WinNT://", ""); var IsGroup = LocalUser.SchemaClassName.IsLikeMatch("group"); bool MemberIsDomain; string Name; if (Regex.Matches(AdsPath, "/").Count == 1) { // DOMAIN\user MemberIsDomain = true; Name = AdsPath.Replace(@"/", @"\"); } else { // DOMAIN\machine\user MemberIsDomain = false; Name = AdsPath.Substring(AdsPath.IndexOf('/') + 1).Replace(@"/", @"\"); } Member.AccountName = Name; Member.SID = new System.Security.Principal.SecurityIdentifier((byte[])LocalUser.InvokeGet("ObjectSID"), 0).Value; Member.IsGroup = IsGroup; Member.IsDomain = MemberIsDomain; LocalGroupMembers.Add(Member); } } catch (Exception e) { Logger.Write_Verbose($@"[Get-NetLocalGroupMember] Error for {Computer} : {e}"); } } } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(LocalGroupMembers); }
public static IEnumerable <ShareInfo> Get_NetShare(Args_Get_NetShare args = null) { if (args == null) { args = new Args_Get_NetShare(); } var shareInfos = new List <ShareInfo>(); var LogonToken = IntPtr.Zero; if (args.Credential != null) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } foreach (var Computer in args.ComputerName) { // arguments for NetShareEnum var QueryLevel = 1; var PtrInfo = IntPtr.Zero; var EntriesRead = 0; var TotalRead = 0; var ResumeHandle = 0; // get the raw share information var Result = NativeMethods.NetShareEnum(Computer, QueryLevel, ref PtrInfo, MAX_PREFERRED_LENGTH, ref EntriesRead, ref TotalRead, ref ResumeHandle); // locate the offset of the initial intPtr var Offset = PtrInfo.ToInt64(); // 0 = success if ((Result == 0) && (Offset > 0)) { // work out how much to increment the pointer by finding out the size of the structure var Increment = Marshal.SizeOf(typeof(SHARE_INFO_1)); // parse all the result structures for (var i = 0; (i < EntriesRead); i++) { // create a new int ptr at the given offset and cast the pointer as our result structure var NewIntPtr = new System.IntPtr(Offset); var Info = (SHARE_INFO_1)Marshal.PtrToStructure(NewIntPtr, typeof(SHARE_INFO_1)); // return all the sections of the structure - have to do it this way for V2 shareInfos.Add(new ShareInfo { Name = Info.shi1_netname, Type = Info.shi1_type, Remark = Info.shi1_remark, ComputerName = Computer }); Offset = NewIntPtr.ToInt64(); Offset += Increment; } // free up the result buffer NativeMethods.NetApiBufferFree(PtrInfo); } else { Logger.Write_Verbose($@"[Get-NetShare] Error: {new System.ComponentModel.Win32Exception((int)Result).Message}"); } } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(shareInfos); }
public static IEnumerable <object> Get_NetLocalGroup(Args_Get_NetLocalGroup args = null) { if (args == null) { args = new Args_Get_NetLocalGroup(); } var LogonToken = IntPtr.Zero; if (args.Credential != null) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } var LocalGroups = new List <object>(); foreach (var Computer in args.ComputerName) { if (args.Method == MethodType.API) { // if we're using the Netapi32 NetLocalGroupEnum API call to get the local group information // arguments for NetLocalGroupEnum var QueryLevel = 1; var PtrInfo = IntPtr.Zero; var EntriesRead = 0; var TotalRead = 0; var ResumeHandle = 0; // get the local user information var Result = NativeMethods.NetLocalGroupEnum(Computer, QueryLevel, out PtrInfo, MAX_PREFERRED_LENGTH, out EntriesRead, out TotalRead, ref ResumeHandle); // locate the offset of the initial intPtr var Offset = PtrInfo.ToInt64(); // 0 = success if ((Result == 0) && (Offset > 0)) { // Work out how much to increment the pointer by finding out the size of the structure var Increment = Marshal.SizeOf(typeof(LOCALGROUP_INFO_1)); // parse all the result structures for (var i = 0; (i < EntriesRead); i++) { // create a new int ptr at the given offset and cast the pointer as our result structure var NewIntPtr = new System.IntPtr(Offset); var Info = (LOCALGROUP_INFO_1)Marshal.PtrToStructure(NewIntPtr, typeof(LOCALGROUP_INFO_1)); LocalGroups.Add(new LocalGroupAPI { ComputerName = Computer, GroupName = Info.lgrpi1_name, Comment = Info.lgrpi1_comment }); Offset = NewIntPtr.ToInt64(); Offset += Increment; } // free up the result buffer NativeMethods.NetApiBufferFree(PtrInfo); } else { Logger.Write_Verbose($@"[Get-NetLocalGroup] Error: {new System.ComponentModel.Win32Exception((int)Result).Message}"); } } else { // otherwise we're using the WinNT service provider var ComputerProvider = new System.DirectoryServices.DirectoryEntry($@"WinNT://{Computer},computer"); foreach (System.DirectoryServices.DirectoryEntry LocalGroup in ComputerProvider.Children) { if (LocalGroup.SchemaClassName.Equals("group", StringComparison.OrdinalIgnoreCase)) { var Group = new LocalGroupWinNT { ComputerName = Computer, GroupName = LocalGroup.Name, SID = new System.Security.Principal.SecurityIdentifier((byte[])LocalGroup.InvokeGet("objectsid"), 0).Value, Comment = LocalGroup.InvokeGet("Description").ToString() }; LocalGroups.Add(Group); } } } } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(LocalGroups); }
public static IEnumerable <RegLoggedOnUser> Get_RegLoggedOn(Args_Get_RegLoggedOn args = null) { if (args == null) { args = new Args_Get_RegLoggedOn(); } IntPtr LogonToken = IntPtr.Zero; if (args.Credential != null) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } var RegLoggedOnUsers = new List <RegLoggedOnUser>(); foreach (var Computer in args.ComputerName) { try { // retrieve HKU remote registry values var Reg = Microsoft.Win32.RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.Users, $@"{Computer}"); // sort out bogus sid's like _class var subkeys = Reg.GetSubKeyNames()?.Where(x => x.IsRegexMatch(@"S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$")); foreach (var subkey in subkeys) { var UserName = ConvertFromSID.ConvertFrom_SID(new Args_ConvertFrom_SID { ObjectSID = new[] { subkey } }).FirstOrDefault(); string UserDomain; if (UserName != null) { UserName = UserName.Split('@')[0]; UserDomain = UserName.Split('@')[1]; } else { UserName = subkey; UserDomain = null; } var RegLoggedOnUser = new RegLoggedOnUser { ComputerName = $@"{Computer}", UserDomain = UserDomain, UserName = UserName, UserSID = subkey }; RegLoggedOnUsers.Add(RegLoggedOnUser); } } catch (Exception e) { Logger.Write_Verbose($@"[Get-RegLoggedOn] Error opening remote registry on '{Computer}' : {e}"); } } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(RegLoggedOnUsers); }
public static IEnumerable <SessionInfo> Get_NetSession(Args_Get_NetSession args = null) { if (args == null) { args = new Args_Get_NetSession(); } var LogonToken = IntPtr.Zero; if (args.Credential != null) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } var SessionInfos = new List <SessionInfo>(); foreach (var Computer in args.ComputerName) { // arguments for NetSessionEnum var QueryLevel = 10; var PtrInfo = IntPtr.Zero; var EntriesRead = 0; var TotalRead = 0; var ResumeHandle = 0; var UserName = string.Empty; // get session information var Result = NativeMethods.NetSessionEnum(Computer, string.Empty, UserName, QueryLevel, out PtrInfo, -1, ref EntriesRead, ref TotalRead, ref ResumeHandle); // locate the offset of the initial intPtr var Offset = PtrInfo.ToInt64(); // 0 = success if ((Result == 0) && (Offset > 0)) { // work out how much to increment the pointer by finding out the size of the structure var Increment = Marshal.SizeOf(typeof(SESSION_INFO_10)); // parse all the result structures for (var i = 0; (i < EntriesRead); i++) { // create a new int ptr at the given offset and cast the pointer as our result structure var NewIntPtr = new System.IntPtr(Offset); var Info = (SESSION_INFO_10)Marshal.PtrToStructure(NewIntPtr, typeof(SESSION_INFO_10)); // return all the sections of the structure - have to do it this way for V2 var Session = new SessionInfo { ComputerName = Computer, CName = Info.sesi10_cname, UserName = Info.sesi10_username, Time = Info.sesi502_time, IdleTime = Info.sesi502_idle_time }; Offset = NewIntPtr.ToInt64(); Offset += Increment; SessionInfos.Add(Session); } // free up the result buffer NativeMethods.NetApiBufferFree(PtrInfo); } else { Logger.Write_Verbose($@"[Get-NetSession] Error: {new System.ComponentModel.Win32Exception((int)Result).Message}"); } } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(SessionInfos); }
// the host enumeration block we're using to enumerate all servers private static IEnumerable <UserLocation> _Find_DomainUserLocation(string[] ComputerName, string[] TargetUsers, string CurrentUser, bool Stealth, bool CheckAccess, IntPtr TokenHandle) { var LogonToken = IntPtr.Zero; if (TokenHandle != IntPtr.Zero) { // impersonate the the token produced by LogonUser()/Invoke-UserImpersonation LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { TokenHandle = TokenHandle, Quiet = true }); } var UserLocations = new List <UserLocation>(); foreach (var TargetComputer in ComputerName) { var Up = TestConnection.Ping(TargetComputer, 1); if (Up) { var Sessions = GetNetSession.Get_NetSession(new Args_Get_NetSession { ComputerName = new[] { TargetComputer } }); foreach (var Session in Sessions) { var UserName = Session.UserName; var CName = Session.CName; if (!CName.IsNullOrEmpty() && CName.StartsWith(@"\\")) { CName = CName.TrimStart('\\'); } // make sure we have a result, and ignore computer$ sessions if ((UserName != null) && (UserName.Trim() != "") && (!UserName.IsRegexMatch(CurrentUser)) && (!UserName.IsRegexMatch(@"\$$"))) { if ((TargetUsers == null) || (TargetUsers.Contains(UserName))) { var UserLocation = new UserLocation { UserDomain = null, UserName = UserName, ComputerName = TargetComputer, SessionFrom = CName }; // try to resolve the DNS hostname of $Cname try { var CNameDNSName = System.Net.Dns.GetHostEntry(CName).HostName; UserLocation.SessionFromName = CNameDNSName; } catch { UserLocation.SessionFromName = null; } // see if we're checking to see if we have local admin access on this machine if (CheckAccess) { var Admin = TestAdminAccess.Test_AdminAccess(new Args_Test_AdminAccess { ComputerName = new[] { CName } }).FirstOrDefault(); UserLocation.LocalAdmin = Admin != null ? Admin.IsAdmin : false; } else { UserLocation.LocalAdmin = false; } UserLocations.Add(UserLocation); } } } if (!Stealth) { // if we're not 'stealthy', enumerate loggedon users as well var LoggedOn = GetNetLoggedon.Get_NetLoggedon(new Args_Get_NetLoggedon { ComputerName = new[] { TargetComputer } }); foreach (var User in LoggedOn) { var UserName = User.UserName; var UserDomain = User.LogonDomain; // make sure wet have a result if ((UserName != null) && (UserName.Trim() != "")) { if ((TargetUsers == null) || (TargetUsers.Contains(UserName)) && (!UserName.IsRegexMatch(@"\$$"))) { var IPAddress = ResolveIPAddress.Resolve_IPAddress(new Args_Resolve_IPAddress { ComputerName = new[] { TargetComputer } }).FirstOrDefault()?.IPAddress; var UserLocation = new UserLocation { UserDomain = UserDomain, UserName = UserName, ComputerName = TargetComputer, IPAddress = IPAddress, SessionFrom = null, SessionFromName = null }; // see if we're checking to see if we have local admin access on this machine if (CheckAccess) { var Admin = TestAdminAccess.Test_AdminAccess(new Args_Test_AdminAccess { ComputerName = new[] { TargetComputer } }).FirstOrDefault(); UserLocation.LocalAdmin = Admin.IsAdmin; } else { UserLocation.LocalAdmin = false; } UserLocations.Add(UserLocation); } } } } } } if (TokenHandle != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(UserLocations); }
// the host enumeration block we're using to enumerate all servers private static IEnumerable <ShareInfo> _Find_DomainShare(string[] ComputerName, bool CheckShareAccess, IntPtr TokenHandle) { var LogonToken = IntPtr.Zero; if (TokenHandle != IntPtr.Zero) { // impersonate the the token produced by LogonUser()/Invoke-UserImpersonation LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { TokenHandle = TokenHandle, Quiet = true }); } var DomainShares = new List <ShareInfo>(); foreach (var TargetComputer in ComputerName) { var Up = TestConnection.Ping(TargetComputer, 1); if (Up) { // get the shares for this host and check what we find var Shares = GetNetShare.Get_NetShare(new Args_Get_NetShare { ComputerName = new[] { TargetComputer } }); foreach (var Share in Shares) { var ShareName = Share.Name; // $Remark = $Share.Remark var Path = @"\\" + TargetComputer + @"\" + ShareName; if ((!string.IsNullOrEmpty(ShareName)) && (ShareName.Trim() != "")) { // see if we want to check access to this share if (CheckShareAccess) { // check if the user has access to this path try { Directory.GetFiles(Path); DomainShares.Add(Share); } catch (Exception e) { Logger.Write_Verbose($@"Error accessing share path {Path} : {e}"); } } else { DomainShares.Add(Share); } } } } } if (TokenHandle != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(DomainShares); }
public static IEnumerable <ComputerSite> Get_NetComputerSiteName(Args_Get_NetComputerSiteName args = null) { if (args == null) { args = new Args_Get_NetComputerSiteName(); } var LogonToken = IntPtr.Zero; if (args.Credential != null) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } var ComputerSites = new List <ComputerSite>(); foreach (var item in args.ComputerName) { string IPAddress; var Computer = item; //if we get an IP address, try to resolve the IP to a hostname if (Computer.IsRegexMatch(@"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$")) { IPAddress = Computer; Computer = System.Net.Dns.GetHostEntry(Computer).HostName; } else { IPAddress = ResolveIPAddress.Resolve_IPAddress(new Args_Resolve_IPAddress { ComputerName = new[] { Computer } }).First().IPAddress; } var PtrInfo = IntPtr.Zero; var Result = NativeMethods.DsGetSiteName(Computer, out PtrInfo); var ComputerSite = new ComputerSite { ComputerName = Computer, IPAddress = IPAddress }; if (Result == 0) { var Sitename = System.Runtime.InteropServices.Marshal.PtrToStringAuto(PtrInfo); ComputerSite.SiteName = Sitename; } else { Logger.Write_Verbose($@"[Get-NetComputerSiteName] Error: {new System.ComponentModel.Win32Exception((int)Result).Message}"); ComputerSite.SiteName = @""; } // free up the result buffer NativeMethods.NetApiBufferFree(PtrInfo); ComputerSites.Add(ComputerSite); } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(ComputerSites); }
public static IEnumerable <UserLocation> Find_DomainUserLocation(Args_Find_DomainUserLocation args = null) { if (args == null) { args = new Args_Find_DomainUserLocation(); } var ComputerSearcherArguments = new Args_Get_DomainComputer { Properties = new[] { "dnshostname" }, Domain = args.Domain, LDAPFilter = args.ComputerLDAPFilter, SearchBase = args.ComputerSearchBase, Unconstrained = args.Unconstrained, OperatingSystem = args.OperatingSystem, ServicePack = args.ServicePack, SiteName = args.SiteName, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { ComputerSearcherArguments.Domain = args.ComputerDomain; } var UserSearcherArguments = new Args_Get_DomainUser { Properties = new[] { "samaccountname" }, Identity = args.UserIdentity, Domain = args.Domain, LDAPFilter = args.UserLDAPFilter, SearchBase = args.UserSearchBase, AdminCount = args.UserAdminCount, AllowDelegation = args.AllowDelegation, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.UserDomain)) { UserSearcherArguments.Domain = args.UserDomain; } string[] TargetComputers = null; // first, build the set of computers to enumerate if (args.ComputerName != null) { TargetComputers = args.ComputerName; } else { if (args.Stealth) { Logger.Write_Verbose($@"[Find-DomainUserLocation] Stealth enumeration using source: {args.StealthSource}"); var TargetComputerArrayList = new System.Collections.ArrayList(); if (args.StealthSource.ToString().IsRegexMatch("File|All")) { Logger.Write_Verbose("[Find-DomainUserLocation] Querying for file servers"); var FileServerSearcherArguments = new Args_Get_DomainFileServer { Domain = new[] { args.Domain }, SearchBase = args.ComputerSearchBase, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { FileServerSearcherArguments.Domain = new[] { args.ComputerDomain } } ; var FileServers = GetDomainFileServer.Get_DomainFileServer(FileServerSearcherArguments); TargetComputerArrayList.AddRange(FileServers); } if (args.StealthSource.ToString().IsRegexMatch("DFS|All")) { Logger.Write_Verbose(@"[Find-DomainUserLocation] Querying for DFS servers"); // { TODO: fix the passed parameters to Get-DomainDFSShare // $ComputerName += Get-DomainDFSShare -Domain $Domain -Server $DomainController | ForEach-Object {$_.RemoteServerName} } if (args.StealthSource.ToString().IsRegexMatch("DC|All")) { Logger.Write_Verbose(@"[Find-DomainUserLocation] Querying for domain controllers"); var DCSearcherArguments = new Args_Get_DomainController { LDAP = true, Domain = args.Domain, Server = args.Server, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { DCSearcherArguments.Domain = args.ComputerDomain; } var DomainControllers = GetDomainController.Get_DomainController(DCSearcherArguments).Select(x => (x as LDAPProperty).dnshostname).ToArray(); TargetComputerArrayList.AddRange(DomainControllers); } TargetComputers = TargetComputerArrayList.ToArray() as string[]; } } if (args.ComputerName != null) { TargetComputers = args.ComputerName; } else { if (args.Stealth) { Logger.Write_Verbose($@"[Find-DomainUserLocation] Stealth enumeration using source: {args.StealthSource}"); var TargetComputerArrayList = new System.Collections.ArrayList(); if (args.StealthSource.ToString().IsRegexMatch("File|All")) { Logger.Write_Verbose("[Find-DomainUserLocation] Querying for file servers"); var FileServerSearcherArguments = new Args_Get_DomainFileServer { Domain = new[] { args.Domain }, SearchBase = args.ComputerSearchBase, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { FileServerSearcherArguments.Domain = new[] { args.ComputerDomain } } ; var FileServers = GetDomainFileServer.Get_DomainFileServer(FileServerSearcherArguments); TargetComputerArrayList.AddRange(FileServers); } if (args.StealthSource.ToString().IsRegexMatch("DFS|All")) { Logger.Write_Verbose(@"[Find-DomainUserLocation] Querying for DFS servers"); // { TODO: fix the passed parameters to Get-DomainDFSShare // $ComputerName += Get-DomainDFSShare -Domain $Domain -Server $DomainController | ForEach-Object {$_.RemoteServerName} } if (args.StealthSource.ToString().IsRegexMatch("DC|All")) { Logger.Write_Verbose(@"[Find-DomainUserLocation] Querying for domain controllers"); var DCSearcherArguments = new Args_Get_DomainController { LDAP = true, Domain = args.Domain, Server = args.Server, Credential = args.Credential }; if (!string.IsNullOrEmpty(args.ComputerDomain)) { DCSearcherArguments.Domain = args.ComputerDomain; } var DomainControllers = GetDomainController.Get_DomainController(DCSearcherArguments).Select(x => (x as LDAPProperty).dnshostname).ToArray(); TargetComputerArrayList.AddRange(DomainControllers); } TargetComputers = TargetComputerArrayList.ToArray() as string[]; } else { Logger.Write_Verbose("[Find-DomainUserLocation] Querying for all computers in the domain"); TargetComputers = GetDomainComputer.Get_DomainComputer(ComputerSearcherArguments).Select(x => (x as LDAPProperty).dnshostname).ToArray(); } } Logger.Write_Verbose($@"[Find-DomainUserLocation] TargetComputers length: {TargetComputers.Length}"); if (TargetComputers.Length == 0) { throw new Exception("[Find-DomainUserLocation] No hosts found to enumerate"); } // get the current user so we can ignore it in the results string CurrentUser; if (args.Credential != null) { CurrentUser = args.Credential.UserName; } else { CurrentUser = Environment.UserName.ToLower(); } // now build the user target set string[] TargetUsers = null; if (args.ShowAll) { TargetUsers = new string[] { }; } else if (args.UserIdentity != null || args.UserLDAPFilter != null || args.UserSearchBase != null || args.UserAdminCount || args.UserAllowDelegation) { TargetUsers = GetDomainUser.Get_DomainUser(UserSearcherArguments).Select(x => (x as LDAPProperty).samaccountname).ToArray(); } else { var GroupSearcherArguments = new Args_Get_DomainGroupMember { Identity = args.UserGroupIdentity, Recurse = true, Domain = args.UserDomain, SearchBase = args.UserSearchBase, Server = args.Server, SearchScope = args.SearchScope, ResultPageSize = args.ResultPageSize, ServerTimeLimit = args.ServerTimeLimit, Tombstone = args.Tombstone, Credential = args.Credential }; TargetUsers = GetDomainGroupMember.Get_DomainGroupMember(GroupSearcherArguments).Select(x => x.MemberName).ToArray(); } Logger.Write_Verbose($@"[Find-DomainUserLocation] TargetUsers length: {TargetUsers.Length}"); if ((!args.ShowAll) && (TargetUsers.Length == 0)) { throw new Exception("[Find-DomainUserLocation] No users found to target"); } var LogonToken = IntPtr.Zero; if (args.Credential != null) { if (args.Delay != 0 || args.StopOnSuccess) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } else { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential, Quiet = true }); } } var rets = new List <UserLocation>(); // only ignore threading if -Delay is passed if (args.Delay != 0 /* || args.StopOnSuccess*/) { Logger.Write_Verbose($@"[Find-DomainUserLocation] Total number of hosts: {TargetComputers.Count()}"); Logger.Write_Verbose($@"[Find-DomainUserLocation] Delay: {args.Delay}, Jitter: {args.Jitter}"); var Counter = 0; var RandNo = new System.Random(); foreach (var TargetComputer in TargetComputers) { Counter = Counter + 1; // sleep for our semi-randomized interval System.Threading.Thread.Sleep(RandNo.Next((int)((1 - args.Jitter) * args.Delay), (int)((1 + args.Jitter) * args.Delay)) * 1000); Logger.Write_Verbose($@"[Find-DomainUserLocation] Enumerating server {TargetComputer} ({Counter} of {TargetComputers.Count()})"); var Result = _Find_DomainUserLocation(new[] { TargetComputer }, TargetUsers, CurrentUser, args.Stealth, args.CheckAccess, LogonToken); if (Result != null) { rets.AddRange(Result); } if (Result != null && args.StopOnSuccess) { Logger.Write_Verbose("[Find-DomainUserLocation] Target user found, returning early"); return(rets); } } } else { Logger.Write_Verbose($@"[Find-DomainUserLocation] Using threading with threads: {args.Threads}"); Logger.Write_Verbose($@"[Find-DomainUserLocation] TargetComputers length: {TargetComputers.Length}"); // if we're using threading, kick off the script block with New-ThreadedFunction // if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params System.Threading.Tasks.Parallel.ForEach( TargetComputers, TargetComputer => { var Result = _Find_DomainUserLocation(new[] { TargetComputer }, TargetUsers, CurrentUser, args.Stealth, args.CheckAccess, LogonToken); lock (rets) { if (Result != null) { rets.AddRange(Result); } } }); } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(rets); }
public static IEnumerable <LoggedOnUserInfo> Get_NetLoggedon(Args_Get_NetLoggedon args = null) { if (args == null) { args = new Args_Get_NetLoggedon(); } var LogonToken = IntPtr.Zero; if (args.Credential != null) { LogonToken = InvokeUserImpersonation.Invoke_UserImpersonation(new Args_Invoke_UserImpersonation { Credential = args.Credential }); } var LoggedOns = new List <LoggedOnUserInfo>(); foreach (var Computer in args.ComputerName) { // declare the reference variables var QueryLevel = 1; var PtrInfo = IntPtr.Zero; var EntriesRead = 0; var TotalRead = 0; var ResumeHandle = 0; // get logged on user information var Result = NativeMethods.NetWkstaUserEnum(Computer, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ref ResumeHandle); // locate the offset of the initial intPtr var Offset = PtrInfo.ToInt64(); // 0 = success if ((Result == 0) && (Offset > 0)) { // work out how much to increment the pointer by finding out the size of the structure var Increment = Marshal.SizeOf(typeof(WKSTA_USER_INFO_1)); // parse all the result structures for (var i = 0; (i < EntriesRead); i++) { // create a new int ptr at the given offset and cast the pointer as our result structure var NewIntPtr = new System.IntPtr(Offset); var Info = (WKSTA_USER_INFO_1)Marshal.PtrToStructure(NewIntPtr, typeof(WKSTA_USER_INFO_1)); // return all the sections of the structure - have to do it this way for V2 LoggedOns.Add(new LoggedOnUserInfo { UserName = Info.wkui1_username, LogonDomain = Info.wkui1_logon_domain, AuthDomains = Info.wkui1_oth_domains, LogonServer = Info.wkui1_logon_server, ComputerName = Computer }); Offset = NewIntPtr.ToInt64(); Offset += Increment; } // free up the result buffer NativeMethods.NetApiBufferFree(PtrInfo); } else { Logger.Write_Verbose($@"[Get-NetLoggedon] Error: {new System.ComponentModel.Win32Exception((int)Result).Message}"); } } if (LogonToken != IntPtr.Zero) { InvokeRevertToSelf.Invoke_RevertToSelf(LogonToken); } return(LoggedOns); }