March 3

Ослепить Sysmon. Выводим мониторинг из строя максимально незаметно

  1. Sysmon Internals
  2. Закрытие хендла через дубликат
  3. Объекты драйверов
  4. Как устроена безопасность в Windows
  5. Ослепляем Sysmon

По­лучив дос­туп к сис­теме, зло­умыш­ленник пер­вым делом пыта­ется осле­пить средс­тва ауди­та, что­бы как мож­но доль­ше оста­вать­ся незаме­чен­ным. В этой статье мы с тобой поп­робу­ем осле­пить Sysmon и сде­лать это мак­сималь­но незамет­но для штат­ного ауди­та Windows. Дос­тичь это­го нам поз­волят манипу­ляции с хен­дла­ми и дес­крип­торами безопас­ности.

SYSMON INTERNALS

Сра­зу ого­ворюсь, что тех­ники, опи­сан­ные в этой статье, тре­буют, что­бы у ата­кующе­го были адми­нис­тра­тив­ные при­виле­гии. Кто‑то ска­жет: зачем же нам углублять­ся во внут­рянку Windows, если с пра­вами адми­на мож­но оста­новить служ­бу Sysmon или вооб­ще уда­лить ее? Ответ прост. Во‑пер­вых, при реали­зации тра­дици­онных тех­ник, таких как оста­нов­ка служ­бы, завер­шение про­цес­са или пол­ное уда­ление Sysmon, штат­ный аудит Windows сфор­миру­ет мас­су событий (начиная с EventID 4689 в жур­нале Security и закан­чивая событи­ем EventID 1 в жур­нале System от про­вай­дера FilterManager). Во‑вто­рых, это прос­то полез­ное упражне­ние: мы дол­жны как мож­но глуб­же раз­бирать­ся в под­систе­ме безопас­ности любимой ОС, что­бы понимать тех­ники, которы­ми поль­зуют­ся хакеры.

Sysmon — это инс­тру­мент, пред­назна­чен­ный для углублен­ного монито­рин­га активнос­ти, про­исхо­дящей в сис­теме, который поз­воля­ет сущес­твен­но рас­ширить штат­ный аудит ОС Windows.

Вот как его работа выг­лядит изнутри.

Пер­вая коман­да (search <ServicePattern>) ищет зарегис­три­рован­ные в сис­теме служ­бы и драй­веры с помощью Win32-фун­кции EnumServicesStatus(). Вид­но, что в сис­теме дей­ству­ют две сущ­ности: служ­ба режима поль­зовате­ля — Sysmon64 и драй­вер SysmonDrv. Обе сущ­ности запус­кают­ся авто­мати­чес­ки при стар­те сис­темы (поле StartType). Эту информа­цию мы получа­ем с помощью коман­ды show all <ServiceName>, которая пос­ледова­тель­но вызыва­ет QueryServiceStatus() (для получе­ния текуще­го ста­туса работы — запуще­на или оста­нов­лена) и QueryServiceConfig() (для получе­ния оставшей­ся информа­ции).

Ло­гич­но пред­положить, что события (или часть событий), которые пишет служ­ба Sysmon64 в жур­нал Microsoft-Windows-Sysmon\Operational, фор­миру­ются модулем ядра SysmonDrv, а для вза­имо­дей­ствия служ­бы и драй­вера дол­жно быть ком­муника­цион­ное устрой­ство (device). Что­бы про­верить это, пос­мотрим на спи­сок хен­длов, откры­тых служ­бой Sysmon64 (про­цес­сом Sysmon64.exe).

По­лучим иден­тифика­тор про­цес­са Sysmon64.exe (search name <ProcessPattern>).

Ко­ман­да search name <ProcessPattern> работа­ет через вызов CreateToolhelp32Snapshot(): фун­кции Process32First() и Process32Next().

Пос­ле того как мы получим ID про­цес­са, пос­мотрим спи­сок его хен­длов.

Из вывода вид­но, что у про­цес­са Sysmon64.exe есть нес­коль­ко откры­тых хен­длов на устрой­ства. Обра­ти вни­мание на устрой­ство \Device\SysmonDrv, одно­имен­ное драй­веру. Ско­рее все­го, имен­но с помощью это­го устрой­ства служ­ба режима поль­зовате­ля Sysmon64 получа­ет информа­цию от драй­вера и впос­ледс­твии фор­миру­ет события ауди­та.

Ко­ман­да show handles <PID> <Type> реали­зует вызов NtQueryInformationProcess() с парамет­ром ProcessHandleInformation.

__kernel_entry NTSTATUS NtQueryInformationProcess( [in] HANDLE ProcessHandle, [in] PROCESSINFOCLASS ProcessInformationClass, [out] PVOID ProcessInformation, [in] ULONG ProcessInformationLength, [out, optional] PULONG ReturnLength );

Пер­вый параметр (ProcessHandle) — дес­крип­тор про­цес­са, хен­длы которо­го мы хотим уви­деть. Его мож­но получить при помощи фун­кции OpenProcess() с парамет­ром PROCESS_QUERY_INFORMATION.

ProcessInformationClass — это харак­тер зап­рашива­емой информа­ции. В нашем слу­чае этот параметр равен ProcessHandleInformation, то есть мы хотим получить информа­цию о хен­длах про­цес­са.

Сле­дующим идет ProcessInformation, ука­затель на память, в которую будет помещен резуль­тат нашего зап­роса — PPROCESS_HANDLE_SNAPSHOT_INFORMATION, то есть ука­затель на струк­туру, содер­жащую спи­сок всех хен­длов и их количес­тво.

Чет­вертый и пятый парамет­ры ука­зыва­ют раз­мер име­ющей­ся и тре­буемой памяти, в которую помеща­ется воз­вра­щаемый фун­кци­ей резуль­тат.

ЗАКРЫТИЕ ХЕНДЛА ЧЕРЕЗ ДУБЛИКАТ

Ес­ли наши пред­положе­ния вер­ны, то, что­бы Sysmon перес­тал фор­мировать события ауди­та, ата­кующий может зас­тавить про­цесс Sysmon64.exe зак­рыть хендл на это устрой­ство.

Су­щес­тву­ет нес­коль­ко спо­собов это сде­лать, но мы вос­поль­зуем­ся самым, на мой взгляд, прос­тым — с помощью вызова DuplicateHandle():

BOOL DuplicateHandle( [in] HANDLE hSourceProcessHandle, [in] HANDLE hSourceHandle, [in] HANDLE hTargetProcessHandle, [out] LPHANDLE lpTargetHandle, [in] DWORD dwDesiredAccess, [in] BOOL bInheritHandle, [in] DWORD dwOptions );

С помощью этой фун­кции мож­но копиро­вать хен­длы меж­ду про­цес­сами, при­чем у нее есть инте­рес­ная опция, которая поз­воля­ет при копиро­вании зак­рывать исходный хендл. Этим мы и вос­поль­зуем­ся. Наш код будет выг­лядеть сле­дующим обра­зом:

DuplicateHandle( hProcess, hObject, GetCurrentProcess(), &hDupObject, 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

Пер­вый параметр (hProcess) — дес­крип­тор про­цес­са, хендл из которо­го мы хотим ско­пиро­вать зак­рыть. Тут важ­но не забыть, что переда­ваемый объ­ект про­цес­са hProcess дол­жен быть открыт с мас­кой дос­тупа PROCESS_DUP_HANDLE.

Сле­дующий параметр (hObject) — сам зак­рыва­емый дес­крип­тор.

Тре­тий (GetCurrentProcess()) и чет­вертый (&hDupObject) парамет­ры ука­зыва­ют на про­цесс‑при­емник и сам хендл‑при­емник соот­ветс­твен­но.

Пос­ледний параметр содер­жит две кон­стан­ты: пер­вая (DUPLICATE_SAME_ACCESS) зна­чит, что новый хендл дол­жен иметь такую же мас­ку дос­тупа, как и исходный; вто­рая (DUPLICATE_CLOSE_SOURCE) — что необ­ходимо зак­рыть исходный хендл пос­ле опе­рации дуб­лирова­ния. Отлично, это то, что нам нуж­но.

Итак, как мы видели ранее, у про­цес­са Sysmon64.exe есть откры­тый опи­сатель для объ­екта \Device\SysmonDrv. Поп­робу­ем его зак­рыть.

Мы зак­рыли опи­сатель с иден­тифика­тором 0x310, одна­ко сра­зу пос­ле это­го про­цесс Sysmon64.exe успешно открыл его пов­торно (0x4с4) и про­дол­жил работать как ни в чем не бывало. Поэто­му перей­дем к тяжелой артилле­рии, а эта тех­ника нам еще понадо­бит­ся поз­же.

ОБЪЕКТЫ ДРАЙВЕРОВ

Раз уж не получи­лось манипу­лиро­вать с хен­длом, поп­робу­ем помани­пули­ровать с дес­крип­тором безопас­ности (Security Descriptor), который опре­деля­ет пра­вила пре­дос­тавле­ния дос­тупа к устрой­ству \Device\SysmonDrv. Но для начала давай вспом­ним, что такое объ­ект драй­вера (driver) и объ­ект устрой­ства (device), а так­же как устро­ена под­систе­ма управле­ния дос­тупом в Windows. Если ты хорошо зна­ком с такими поняти­ями, как Driver Object, Device Object, Security Descriptor и Access Token, можешь сме­ло про­пус­кать этот и сле­дующий раз­делы.

При заг­рузке драй­вера в адресное прос­транс­тво ядра сис­тема соз­дает струк­туру _DRIVER_OBJECT, то есть соз­дает спе­циаль­ный объ­ект типа драй­вер (driver). Для наг­ляднос­ти вос­поль­зуем­ся отладчи­ком WinDbg и пос­мотрим на содер­жимое этой струк­туры.

По сме­щению 0x008 от начала струк­туры живет эле­мент DeviceObject — ука­затель на струк­туру _DEVICE_OBJECT — это дру­гой объ­ект ядра, который необ­ходим для ком­муника­ций меж­ду про­цес­сом режима поль­зовате­ля и самим драй­вером. Ины­ми сло­вами, ком­муника­цион­ное устрой­ство обес­печива­ет переда­чу информа­ции меж­ду поль­зователь­ским про­цес­сом и драй­вером. Имен­но для этих целей драй­веры соз­дают объ­екты device, а поль­зователь­ские про­цес­сы могут вза­имо­дей­ство­вать с ними.

Са­мый инте­рес­ный эле­мент струк­туры — это SecurityDescriptor. Имен­но там хра­нят­ся све­дения о том, кому раз­решено вза­имо­дей­ство­вать с устрой­ством и по какой мас­ке дос­тупа. Его содер­жимым мы и будем манипу­лиро­вать.

КАК УСТРОЕНА БЕЗОПАСНОСТЬ В WINDOWS

В под­систе­ме управле­ния дос­тупом Windows есть три учас­тни­ка (роли):

  • субъ­ект дос­тупа;
  • объ­ект дос­тупа;
  • не­зави­симый арбитр.

Субъ­ектом дос­тупа при­нято называть поток (или про­цесс, в этой статье мы будем счи­тать эти понятия синони­мами), который пыта­ется получить дос­туп к ресур­су (нап­ример, фай­лу или клю­чу реес­тра) — объ­екту дос­тупа. Потоки исполня­ются в кон­тек­сте опре­делен­ного поль­зовате­ля. Это озна­чает, что про­цесс может получить ров­но столь­ко дос­тупа, сколь­ко пре­дос­тавле­но учет­ной записи, от име­ни которой запущен про­цесс.

За при­над­лежность потока к кон­тек­сту кон­крет­ного поль­зовате­ля отве­чает струк­тура ядра _Token (Access Token, мар­кер дос­тупа). Это сво­еоб­разный «пас­порт субъ­екта», который сис­тема про­веря­ет вся­кий раз, как толь­ко про­цесс зат­ребу­ет выпол­нение какой‑либо опе­рации над объ­ектом (чте­ние клю­ча реес­тра, запись в файл, чте­ние из ком­муника­цион­ного устрой­ства). Струк­тура _Token содер­жит сле­дующие све­дения:

  • от име­ни какой учет­ной записи запущен про­цесс (иден­тифика­тор учет­ной записи);
  • ка­ким груп­пам безопас­ности при­над­лежит учет­ная запись (иден­тифика­торы групп);
  • ка­кие у учет­ной записи при­виле­гии.

По­лучим адрес Token из струк­туры _EPROCESS (это струк­тура ядра, которая опи­сыва­ет объ­ект про­цес­са).

По фак­ту Token «ука­зыва­ет на ука­затель» _EX_FAST_REF, а не на сам Token. При­чем _EX_FAST_REF име­ет тип union (в тер­миноло­гии язы­ка C) и вклю­чает в себя три эле­мен­та. Напом­ню, union пред­полага­ет, что все эле­мен­ты типа сов­мес­тно исполь­зуют выделен­ную им память.

Эле­мен­ты Object и Value — 8 байт, RefCnt — 4 бита. Зна­чение RefCnt исполь­зует­ся внут­ренни­ми механиз­мами ядра Windows для под­сче­та количес­тва ссы­лок. Таким обра­зом, что­бы получить адрес ука­зате­ля на струк­туру _Token, нуж­но занулить пос­ледние 4 бита зна­чения в эле­мен­те Object.

Пос­мотреть на содер­жимое Access Token в удоб­ном виде мож­но с помощью рас­ширения !token.

Ви­дим, что Sysmon64.exe запущен от име­ни учет­ной записи Local System (S-1-5-18).

Объ­ектом дос­тупа называ­ется любой эле­мент Windows, дос­туп к которо­му может быть про­изволь­но огра­ничен. По сво­ей сути Windows име­ет объ­ектную модель, то есть все ресур­сы явля­ются объ­екта­ми. Фай­лы, клю­чи реес­тра, про­цес­сы, устрой­ства вво­да‑вывода — это всё объ­екты, дос­туп к которым кон­тро­лиру­ется средс­тва­ми ОС. Све­дения о том, кому мож­но получить дос­туп к объ­екту, а кому нет, содер­жатся в Security Descriptor (SD, дес­крип­тор безопас­ности объ­екта, струк­тура ядра _SECURITY_DESCRIPTOR). Пос­мотрим на содер­жимое дес­крип­тора безопас­ности для нашего устрой­ства \Device\SysmonDrv. Для это­го про­дела­ем сле­дующий путь:

  1. С помощью рас­ширения !drvobj получим адрес струк­туры _DRIVER_OBJECT для нашего драй­вера SysmonDrv.
  2. Отту­да получим зна­чение DeviceObject, ука­зыва­ющее на объ­ект ком­муника­цион­ного устрой­ства \Device\SysmonDrv (_DEVICE_OBJECT).
  3. А уже из _DEVICE_OBJECT — ука­затель на _SECURITY_DESCRIPTOR.

Пос­мотрим на содер­жимое дес­крип­тора безопас­ности нашего объ­екта.

В этой струк­туре хра­нят­ся:

  • све­дения о хозя­ине объ­екта (object owner), в нашем слу­чае это Local System (S-1-5-18);
  • дан­ные об основной груп­пе объ­екта (object primary group) — Local System;
  • спис­ки DACL и SACL.

Имен­но спи­сок DACL содер­жит перечень учет­ных записей (иден­тифика­торов), которым раз­решено (или зап­рещено) получать дос­туп к объ­екту. При этом ука­зыва­ется метод дос­тупа (мас­ки, опе­рации дос­тупа).

У нас есть субъ­ект дос­тупа, изъ­явив­ший желание получить дос­туп к защища­емо­му ресур­су (субъ­ект име­ет свой Access Token, содер­жащий све­дения об учет­ной записи поль­зовате­ля, ее членс­тве в груп­пах и при­виле­гиях), и объ­ект дос­тупа (то есть сам защища­емый ресурс), име­ющий Security Descriptor (све­дения о том, кому и какой дос­туп раз­решен). Теперь нам нужен незави­симый арбитр, который смо­жет на осно­ве этой информа­ции решить, пре­дос­тавлять ли дос­туп.

В качес­тве такого не­зави­симо­го арбитра выс­тупа­ет ком­понент исполни­тель­ной под­систе­мы — Security Reference Monitor (SRM). Этот ком­понент отве­чает за про­вер­ку того, может ли субъ­ект получить дос­туп к объ­екту по зап­рашива­емо­му методу дос­тупа на осно­ве сво­их внут­ренних алго­рит­мов.

Итак, подыто­жим:

  • субъ­ект дос­тупа — про­цесс Sysmon64.exe, запущен­ный от име­ни учет­ной записи Local System (S-1-5-18);
  • Sysmon64.exe чита­ет дан­ные, фор­миру­емые драй­вером SysmonDrv, с помощью ком­муника­цион­ного устрой­ства — \Device\SysmonDrv (объ­ект дос­тупа);
  • ус­трой­ство \Device\SysmonDrv име­ет свой Security Descriptor, который ата­кующий хочет модифи­циро­вать таким обра­зом, что­бы субъ­екту (про­цес­су Sysmon64.exe) было отка­зано в дос­тупе.

ОСЛЕПЛЯЕМ SYSMON

Ос­вежив зна­ния о под­систе­ме управле­ния дос­тупом, прис­тупим к нашей основной задаче — поп­робу­ем осле­пить Sysmon. В этом раз­деле мы изме­ним Security Descriptor таким обра­зом, что­бы про­цес­су Sysmon64.exe было отка­зано в пре­дос­тавле­нии дос­тупа к устрой­ству \Device\SysmonDrv.

Пос­мотрим на содер­жимое дес­крип­тора безопас­ности ком­муника­цион­ного устрой­ства. Для это­го нам пот­ребу­ется получить хендл на устрой­ство с помощью фун­кции CreateFile() и пос­леду­юще­го вызова GetSecurityInfo(). Давай под­робнее оста­новим­ся на этих фун­кци­ях. CreateFile() уме­ет получать опи­сате­ли для мно­жес­тва объ­ектов, в том чис­ле и для ком­муника­цион­ных устрой­ств:

HANDLE CreateFileW( [in] LPCWSTR lpFileName, [in] DWORD dwDesiredAccess, [in] DWORD dwShareMode, [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes, [in] DWORD dwCreationDisposition, [in] DWORD dwFlagsAndAttributes, [in, optional] HANDLE hTemplateFile );

Да­вай под­робнее раз­берем каж­дый из семи парамет­ров.

  1. lpFileName при­нима­ет имя объ­екта, в нашем слу­чае это \\.\SysmonDrv — сим­воличес­кая ссыл­ка на \Device\SysmonDrv.
  2. dwDesiredAccess — перечень фла­гов, опи­сыва­ющих зап­рашива­емый дос­туп (мас­ка дос­тупа). Под­систе­ма безопас­ности Windows устро­ена таком обра­зом, что перед тем, как выпол­нить опе­рацию над объ­ектом, надо ука­зать перечень необ­ходимых дос­тупов. Что­бы пос­мотреть зна­чения Owner, Group и спи­сок DACL, нуж­но ука­зать READ_CONTROL, а что­бы пос­мотреть или изме­нить спи­сок SACL — зна­чение ACCESS_SYSTEM_SECURITY (пос­ледний флаг тре­бует наличия у вызыва­юще­го про­цес­са вклю­чен­ных при­виле­гий SE_SECURITY_NAME, в про­тив­ном слу­чае получим ошиб­ку ERROR_ACCESS_DENIED).
  3. dwShareMode опре­деля­ет режим сов­мес­тно­го исполь­зования. В нашем слу­чае уста­нав­лива­ется 0.
  4. lpSecurityAttributes при­нима­ет ука­затель на дес­крип­тор безопас­ности, который будет ассо­цииро­ван с объ­ектом. Этот параметр име­ет зна­чение толь­ко в слу­чае соз­дания нового объ­екта.
  5. dwCreationDisposition опре­деля­ет дей­ствие для сущес­тву­ющих или несущес­тву­ющих фай­лов или устрой­ств, в нашем слу­чае его зна­чение будет рав­но OPEN_EXISTING.
  6. dwFlagsAndAttributes опре­деля­ет перечень фла­гов и атри­бутов, с которы­ми зап­рашива­ется дос­туп к объ­екту. Здесь мы ука­жем FILE_FLAG_BACKUP_SEMANTICS, что сооб­щит под­систе­ме безопас­ности о необ­ходимос­ти получить дос­туп в обход сущес­тву­юще­го спис­ка DACL (наличие дан­ной опции тре­бует у вызыва­юще­го про­цес­са вклю­чен­ных при­виле­гий SE_BACKUP_NAME и SE_RESTORE_NAME).
  7. hTemplateFile — исполь­зует­ся толь­ко при соз­дании новых объ­ектов.

Вот как будет выг­лядеть наш вызов CreateFile():

hDevice = CreateFile( lpDeviceName, READ_CONTROL | ACCESS_SYSTEM_SECURITY, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

Пос­ле получе­ния опи­сате­ля для устрой­ства \\.\SysmonDrv вос­поль­зуем­ся фун­кци­ей GetSecurityInfo(), которая поз­волит вытащить информа­цию из дес­крип­тора безопас­ности:

DWORD GetSecurityInfo( [in] HANDLE handle, [in] SE_OBJECT_TYPE ObjectType, [in] SECURITY_INFORMATION SecurityInfo, [out, optional] PSID *ppsidOwner, [out, optional] PSID *ppsidGroup, [out, optional] PACL *ppDacl, [out, optional] PACL *ppSacl, [out, optional] PSECURITY_DESCRIPTOR *ppSecurityDescriptor );

Пер­вый параметр (handle) при­нима­ет опи­сатель нашего объ­екта, который мы получи­ли с помощью CreateFile().

Да­лее нуж­но ука­зать тип объ­екта (ObjectType), дес­крип­тор безопас­ности которо­го мы хотим пос­мотреть. Ука­жем SE_UNKNOWN_OBJECT_TYPE.

В сле­дующем аргу­мен­те (SecurityInfo) мы ука­зыва­ем, какие имен­но по­ля дес­крип­тора безопас­ности мы хотим получить. В нашем слу­чае это вот такое объ­еди­нение:

OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION

Ос­тавши­еся парамет­ры ука­зыва­ют на струк­туры дан­ных, в которые будет помеще­на тре­буемая нам информа­ция.

В ито­ге вызов GetSecurityInfo() име­ет сле­дующий вид:

GetSecurityInfo( hObject, SE_UNKNOWN_OBJECT_TYPE, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, &pOwner, &pGroup, &pDacl, &pSacl, &pSecurityDescriptor);

Пос­мотрим на дес­крип­тор безопас­ности для \Device\SysmonDrv. С помощью команд show owner <Device> и show group <Device> мож­но узнать хозя­ина объ­екта и груп­пу, а коман­дой show sd <Device> получить пол­ное содер­жание SD в фор­мате SDDL.

Security Descriptor выг­лядит сле­дующим обра­зом:

O:SYG:SYD:(A;;0x1201bf;;;WD)(A;;FA;;;SY)(A;;FA;;;BA)(A;;0x1200a9;;;RC)S:AI

Мы оста­новим­ся лишь на одной его час­ти — спис­ке изби­ратель­ного кон­тро­ля дос­тупа (DACL). Он име­ет такой вид:

D:(A;;0x1201bf;;;WD)(A;;FA;;;SY)(A;;FA;;;BA)(A;;0x1200a9;;;RC)

Cпи­сок изби­ратель­ного кон­тро­ля дос­тупа (Discretionary Access Control List, DACL) сос­тоит из отдель­ных записей (Access Control Entries, ACE). Каж­дая ACE офор­мля­ется в отдель­ных круг­лых скоб­ках. Имен­но DACL хра­нит информа­цию о том, какому субъ­екту и какой имен­но дос­туп раз­решен, а какой зап­рещен. Его мы раз­берем под­робнее.

В гла­за сра­зу бро­сает­ся запись (A;;FA;;;SY), которая говорит о том, что учет­ной записи Local System (SY) воз­можно пре­дос­тавлять (A) пол­ный дос­туп (FA). Поп­робу­ем явно зап­ретить любой дос­туп для этой учет­ной записи. Для это­го сим­вол A заменим D — (D;;FA;;;SY). Перепи­сать Security Descriptor мож­но коман­дой set sddldacl <DACL>. Она реали­зова­на через вызов фун­кции SetSecurityInfo(), которая при­нима­ет парамет­ры, ана­логич­ные GetSecurityInfo(), поэто­му не будем раз­бирать его под­робно.

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

Ви­дим, что ничего не изме­нилось и у про­цес­са Sysmon64.exe оста­лось откры­тое устрой­ство \Device\SysmonDrv, но уже с дру­гим опи­сате­лем. Веро­ятно, мы чего‑то не учли! Вер­немся к дес­крип­тору безопас­ности.

Об­ратим вни­мание на пер­вую запись в спис­ке DACL — (A;;0x1201bf;;;WD), которая озна­чает, что для учет­ной записи Everyone (WD) пре­дос­тавлен (A) какой‑то доволь­но широкий дос­туп — 0x1201bf (при­сутс­тву­ют как минимум FILE_READ_DATA и FILE_WRITE_DATA). Убе­рем ее из спис­ка DACL и пов­торим опе­рацию по зак­рытию хен­дла на устрой­ство.

«Ура! Сра­бота­ло!» — ска­жет хакер и про­дол­жит свои гряз­ные делиш­ки в нашей сис­теме.

Ну а мы пос­мотрим в жур­нал Microsoft-Windows-Sysmon\Operational и убе­дим­ся, что наш Sysmon, к сожале­нию, боль­ше ничего не пишет.

Но не сто­ит отча­ивать­ся, мы как безопас­ники получи­ли «плюс один» детект для нашего SIEM:

Provider Name='Microsoft-Windows-Sysmon' and EventID='255' and Data Name. Description='Failed to access the driver - Last error: Неверный дескриптор'

С позиции же «спе­цов по про­ник­новению» здесь есть еще куда пос­мотреть, но, пожалуй, мы про­дол­жим это увле­катель­ное занятие в дру­гой раз.