Сведения о вопросе

CPdeveloper

09:13, 24th August, 2020

Теги

Перечисление членов группы пользователей Windows на удаленной системе с помощью c#

Просмотров: 610   Ответов: 5

В пределах c#, я должен быть в состоянии

  • Подключитесь к удаленной системе, указав имя пользователя/пароль по мере необходимости
  • Перечислите членов локальной группы в этой системе
  • Получите результаты обратно на исполняющий компьютер

Так, например, я бы подключился к \SOMESYSTEM с соответствующими creds и получил назад список локальных администраторов, включая SOMESYSTEM\Administrator, SOMESYSTEM\Bob, DOMAIN\AlanH, "DOMAIN\Domain администраторов".

Я пробовал это с system.directoryservices.accountmanagement, но у меня возникли проблемы с аутентификацией. Иногда я получаю:

Несколько подключений к серверу или общему ресурсу одним и тем же пользователем, использующим более одного имени пользователя, не допускаются. Отключите все предыдущие подключения к серверу или общему ресурсу и повторите попытку. (Исключение из HRESULT: 0x800704C3)

Вышесказанное является попыткой, потому что будут ситуации, когда я просто не смогу размонтировать существующие диски или соединения UNC.

В других случаях моя программа получает неизвестную ошибку, и журнал безопасности на удаленной системе сообщает об ошибке 675, код 0x19, который является KDC_ERR_PREAUTH_REQUIRED.

Мне нужен более простой и менее подверженный ошибкам способ сделать это!



  Сведения об ответе

DINO

22:00, 15th August, 2020

дэвидг был на правильном пути, и я благодарен ему за ответ.

Но необходимый запрос WMI был немного меньше, чем прямой, поскольку мне нужен был не просто список пользователей для всей машины, а подмножество пользователей и групп , будь то локальные или доменные, которые были членами локальной группы администраторов. Для записи, что запрос WMI был:

SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = "Win32_Group.Domain='thehostname',Name='thegroupname'"

Вот полный фрагмент кода:

public string GroupMembers(string targethost, string groupname, string targetusername, string targetpassword)
        {
            StringBuilder result = new StringBuilder(); 
            try
            {
                ConnectionOptions Conn = new ConnectionOptions();
                if (targethost != Environment.MachineName) //WMI errors if creds given for localhost
                {
                    Conn.Username = targetusername; //can be null
                    Conn.Password = targetpassword; //can be null
                }
                Conn.Timeout = TimeSpan.FromSeconds(2);
                ManagementScope scope = new ManagementScope("\\\\" + targethost + "\\root\\cimv2", Conn);
                scope.Connect();
                StringBuilder qs = new StringBuilder();
                qs.Append("SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = \"Win32_Group.Domain='");
                qs.Append(targethost);
                qs.Append("',Name='");
                qs.Append(groupname);
                qs.AppendLine("'\"");
                ObjectQuery query = new ObjectQuery(qs.ToString());
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
                ManagementObjectCollection queryCollection = searcher.Get();
                foreach (ManagementObject m in queryCollection)
                {
                    ManagementPath path = new ManagementPath(m["PartComponent"].ToString());                                        
                    { 
                        String[] names = path.RelativePath.Split(',');
                        result.Append(names[0].Substring(names[0].IndexOf("=") + 1).Replace("\"", " ").Trim() + "\\"); 
                        result.AppendLine(names[1].Substring(names[1].IndexOf("=") + 1).Replace("\"", " ").Trim());                    
                    }
                }
                return result.ToString();
            }
            catch (Exception e)
            {
                Console.WriteLine("Error. Message: " + e.Message);
                return "fail";
            }
        }

Итак, если я вызову Groupmembers("Server1", "Administrators", "myusername", "mypassword"); я получаю одну строку, возвращенную с помощью:

SERVER1\Administrator
MYDOMAIN\Domain Админов

Фактическое возвращение WMI больше похоже на это:

\\SERVER1\root\cimv2:Win32_UserAccount.Domain="SERVER1", имя="Administrator" ...

так что, как вы можете видеть, мне пришлось сделать небольшую манипуляцию струной, чтобы привести ее в порядок.


  Сведения об ответе

DINO

08:57, 1st August, 2020

Это должно быть легко сделать с помощью WMI. Здесь у вас есть указатель на некоторые документы:

WMI документация для Win32_UserAccount

Даже если у вас нет предыдущего опыта работы с WMI, должно быть довольно легко превратить этот код скрипта VB в нижней части страницы в некоторый код .NET.

Надеюсь, это помогло!


  Сведения об ответе

LAST

17:28, 17th August, 2020

Я бы рекомендовал использовать функцию Win32 API NetLocalGroupGetMembers . Это гораздо более прямолинейно, чем пытаться понять сумасшедший синтаксис LDAP, который необходим для некоторых других решений, рекомендованных здесь. До тех пор, пока вы олицетворяете пользователя, которого хотите проверить, позвонив по номеру "LoginUser", вы не должны столкнуться с какими-либо проблемами безопасности.

Пример кода для выполнения олицетворения можно найти здесь .

Если вам нужна помощь, чтобы выяснить, как позвонить "NetLocalGroupGetMembers" из C#,, я рекомендую вам проверить PInvoke помощника Джареда Парсона, который вы можете скачать с codeplex.

Если вы запускаете код в приложении ASP.NET, работающем в IIS, и хотите выдать себя за пользователя, обращающегося к веб-сайту, чтобы сделать вызов, то вам может потребоваться предоставить разрешение "Trusted for Delegation" производственному веб-серверу.

Если вы работаете на рабочем столе, то использование учетных данных безопасности активного пользователя не должно быть проблемой.

Вполне возможно, что вы администратор сети могли бы отозвать доступ к "Securable Object" для конкретной машины, к которой вы пытаетесь получить доступ. К сожалению, этот доступ необходим для работы всех функций сетевого управления api . Если это так, то вам нужно будет предоставить доступ к "Securable Object" для всех пользователей, которых вы хотите выполнить как. Однако с настройками безопасности по умолчанию windows все аутентифицированные пользователи должны иметь доступ.

Надеюсь, это поможет.

-Скотт


  Сведения об ответе

darknet

22:55, 14th August, 2020

Вы должны быть в состоянии сделать это с System.DirectoryServices.DirectoryEntry. Если у вас возникли проблемы с удаленным запуском, возможно, вы могли бы установить что-то на удаленные машины, чтобы дать вам ваши данные через какой-то RPC, например удаленное управление или веб-сервис. Но я думаю, что то, что вы пытаетесь сделать, должно быть возможно удаленно, не слишком увлекаясь.


  Сведения об ответе

PROGA

16:50, 21st August, 2020

Если Windows не позволит вам подключиться через механизм входа в систему, я думаю, что ваш единственный вариант-запустить что-то на удаленной машине с открытым портом (либо напрямую, либо через удаленное подключение или веб-сервис, как уже упоминалось).


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться