Привет, молодой "киберпенетратор" (или пожилой ^_^). Сегодня я расскажу тебе про сертификаты, но не про те, которые выдают за прививку от COVID-19 
Цель данной конкурсной статьи - рассмотреть один из механизмов безопасности ОС Windows, а именно цифровую подпись для приложений (далее - сертификат) и продемонстрировать возможности блокировки запуска приложений, которые подписаны этим сертификатом.
Я не буду тебе рассказывать о том, что такое сертификат (в подробностях), как его купить/получить или как подписать приложение сертификатом. Нас будет интересовать только механизм блокировки запуска приложений. Подразумевается, что ты уже взрослый мальчик и знаком с такими понятиями, как - PE-файл и его структура, WinAPI и всякие петоны.
СТАРТУЕМ!
Для начала нам понадобится подписанное сертификатом приложение, которое мы хотим заблокировать. Наличие сертификата можно проверить через меню "Свойства", нажав ПКМ по иконке приложения, в появившемся окне должна присутствовать вкладка "Цифровые подписи". Далее в статье я буду использовать продукт ESET NOD 32 Antivirus 15.0.23.0 (https://www.eset.com/ua-ru/home/nod32/download/#download-manually) для Windows 10 x64 (имя файла - eav_nt64.exe)
Сертификат обычно располагается "в конце" файла приложения (другими словами - overlay, учти - эти данные не загружаются в память, как например секции кода/данных/ресурсов). Не буду углубляться в структуру PE-файла, скажу только, что нас интересует заголовок IMAGE_OPTIONAL_HEADER.IMAGE_DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_SECURITY] - здесь хранятся данные о наличии сертификата. Нам нужны данные VirtualAddress и Size, но в отличии от других возможных таблиц этого заголовка (IMAGE_DATA_DIRECTORY), VirtualAddress будет содержать RAW-смещение (вместо RVA) от начала файла. Сам же сертификат имеет свою "структуру" и описывается в заголовочных файлах как WIN_CERTIFICATE:
Посмотри наглядно, как всё это выглядит (используются инструменты - CFF Explorer, WinHex):
Тут по RAW-смещению 0x041B5A00 располагается структура WIN_CERTIFICATE размером 0x000025D8 байт, причём WIN_CERTIFICATE.dwLength (байты расположены в обратном порядке) будет равно IMAGE_DIRECTORY_ENTRY_SECURITY.Size. Начиная со смещения 0x041B5A08 (смотрим состав структуры WIN_CERTIFICATE - DWORD + WORD + WORD = 8) хранится массив WIN_CERTIFICATE.bCertificate с данными сертификата.
WHAT'S NEXT?
А дальше - нужно этот сертификат извлечь, тут есть несколько вариантов:
1) Вручную, через меню "Свойства" файла, далее вкладка "Цифровые подписи" выбрать нужную в списке подписей и нажать "Сведения". В открывшемся окне нажать "Просмотр сертификата", в новом окне выбрать вкладку "Состав" и нажать "Копировать в файл...". Появится мастер экспорта сертификатов, тут нужно будет выбрать формат "в кодировке DER" и указать имя и место сохранения. Как результат мы получим файл "имя_файла.cer"
2) Включаем режим петон-кодера (используя гугл и модули pefile, asn1crypto)
Тут важный момент, что в приложение помимо основого сертификата, могут быть другие (корневые и т.п) сертификаты. Петон-скрипт извлечёт все сертификаты из указанного в source_file приложения. Конкретно нас будет интересовать сертификат с именем "ESET, spol. s r.o..cer" или ваш вариант с именем из первого варианта. Запомним этот момент и проследуем дальше.
MOVE, MOVE, MOVE!
Для управления сертификатами в системе есть инструмент "Хранилище сертификатов", запустить его можно командой "certmgr.msc" (для текущего пользователя) или "certlm.msc" (для всей системы). Выглядит всё это дело примерно так:
Для текущего пользователя возможностей меньше, чем для системы и естественно, изменения для системы будут учитываться для всех пользователей ОС, и да - для внесения изменений в системные настройки нужны "права админа" (или системные привилегии). Как их получить - неважно, не про это статья. Дальше обрати внимание на раздел "Сертификаты, к которым нет доверия". Да-да - это именно то, ради чего началась вся заварушка. Сюда мы и будем добавлять сертификат приложения, которое хотим заблокировать от дальнейшего запуска.
Как обычно есть несколько вариантов добавить сертификат в этот раздел:
1) Вручную - кликаем ПКМ на этом разделе и выбираем "Все задачи" -> "Импорт". Тут всё предельно просто, клац-клац-клац и выбираем файл сертификата.
2) Через утилиту "CertMgr" (certmgr.exe) из состава Visual Studio (https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/). Тут можно посмотреть все параметры, которые можно использовать с этой утилитой - https://docs.microsoft.com/en-us/dotnet/framework/tools/certmgr-exe-certificate-manager-tool. Конкретно нас будет интересовать следующая "конструкция":
3) Метод "ТыжПрограммист" - по всем канонам WinAPI и богоугодной сишечки:
С этим кодесом ты будешь тем самым сыном маминой подруги и вообще первым сеньор-кодером на районе, не благодари ^_^.
FINISH HIM!
В результате этих манипуляций у нас должна появиться запись в разделе "Сертификаты, к которым нет доверия" инструмента "Хранилище сертификатов":
А теперь следи за руками
Попробуй запустить файл "eav_nt64.exe". Результат следующий:
Поздравляю, цель достигнута - запуск приложения заблокирован самой ОС, а сертификат "в бане" и только его удаление разблокирует возможность запуска приложений, которые подписаны данным сертификатом.
p.s.: Стоит отметить, что у многих вендоров (производителей ПО) один и тот же сертификат, что позволяет массово блокировать запуск различных приложений одного вендора. Теперь ты чуть больше стал знать о сертификатах цифровой подписи приложений в ОС Windows, а вот тто ты будешь делать с этими знаниями я понятия не имею
Цель данной конкурсной статьи - рассмотреть один из механизмов безопасности ОС Windows, а именно цифровую подпись для приложений (далее - сертификат) и продемонстрировать возможности блокировки запуска приложений, которые подписаны этим сертификатом.
Я не буду тебе рассказывать о том, что такое сертификат (в подробностях), как его купить/получить или как подписать приложение сертификатом. Нас будет интересовать только механизм блокировки запуска приложений. Подразумевается, что ты уже взрослый мальчик и знаком с такими понятиями, как - PE-файл и его структура, WinAPI и всякие петоны.
СТАРТУЕМ!
Для начала нам понадобится подписанное сертификатом приложение, которое мы хотим заблокировать. Наличие сертификата можно проверить через меню "Свойства", нажав ПКМ по иконке приложения, в появившемся окне должна присутствовать вкладка "Цифровые подписи". Далее в статье я буду использовать продукт ESET NOD 32 Antivirus 15.0.23.0 (https://www.eset.com/ua-ru/home/nod32/download/#download-manually) для Windows 10 x64 (имя файла - eav_nt64.exe)
Сертификат обычно располагается "в конце" файла приложения (другими словами - overlay, учти - эти данные не загружаются в память, как например секции кода/данных/ресурсов). Не буду углубляться в структуру PE-файла, скажу только, что нас интересует заголовок IMAGE_OPTIONAL_HEADER.IMAGE_DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_SECURITY] - здесь хранятся данные о наличии сертификата. Нам нужны данные VirtualAddress и Size, но в отличии от других возможных таблиц этого заголовка (IMAGE_DATA_DIRECTORY), VirtualAddress будет содержать RAW-смещение (вместо RVA) от начала файла. Сам же сертификат имеет свою "структуру" и описывается в заголовочных файлах как WIN_CERTIFICATE:
Код:
typedef struct _WIN_CERTIFICATE {
DWORD dwLength;(
WORD wRevision;
WORD wCertificateType;
BYTE bCertificate[ANYSIZE_ARRAY];
} WIN_CERTIFICATE, *LPWIN_CERTIFICATE;
Посмотри наглядно, как всё это выглядит (используются инструменты - CFF Explorer, WinHex):
Тут по RAW-смещению 0x041B5A00 располагается структура WIN_CERTIFICATE размером 0x000025D8 байт, причём WIN_CERTIFICATE.dwLength (байты расположены в обратном порядке) будет равно IMAGE_DIRECTORY_ENTRY_SECURITY.Size. Начиная со смещения 0x041B5A08 (смотрим состав структуры WIN_CERTIFICATE - DWORD + WORD + WORD = 8) хранится массив WIN_CERTIFICATE.bCertificate с данными сертификата.
WHAT'S NEXT?
А дальше - нужно этот сертификат извлечь, тут есть несколько вариантов:
1) Вручную, через меню "Свойства" файла, далее вкладка "Цифровые подписи" выбрать нужную в списке подписей и нажать "Сведения". В открывшемся окне нажать "Просмотр сертификата", в новом окне выбрать вкладку "Состав" и нажать "Копировать в файл...". Появится мастер экспорта сертификатов, тут нужно будет выбрать формат "в кодировке DER" и указать имя и место сохранения. Как результат мы получим файл "имя_файла.cer"
2) Включаем режим петон-кодера (используя гугл и модули pefile, asn1crypto)
Python:
import pefile
from asn1crypto import cms, pem, x509
#путь и имя файла приложения с сертификатом
source_file = 'eav_nt64.exe'
#читаем содержимое как PE-файл и узнаём смещение и размер overlay с сертификатами
app = pefile.PE(source_file)
cert_offset = app.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]].VirtualAddress
cert_size = app.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]].Size
app.close()
#читаем данные сертификатов
with open(source_file, 'rb') as file_handle:
file_handle.seek(cert_offset)
thesig = file_handle.read(cert_size)
#формируем список сертификатов
cert_list = cms.ContentInfo.load(thesig[8:])
#парсим и сохраняем каждый сертификат в отдельный файл с расширением .cer
for cert in cert_list['content']['certificates']:
cert_dump = cert.dump()
if pem.detect(cert_dump):
_, _, cert_dump = pem.unarmor(cert_dump)
parsed_cert = x509.Certificate.load(cert_dump)
save_cert = open('{:s}.cer'.format(parsed_cert['tbs_certificate']['subject'].native['common_name']), 'wb')
save_cert.write(cert_dump)
save_cert.close
Тут важный момент, что в приложение помимо основого сертификата, могут быть другие (корневые и т.п) сертификаты. Петон-скрипт извлечёт все сертификаты из указанного в source_file приложения. Конкретно нас будет интересовать сертификат с именем "ESET, spol. s r.o..cer" или ваш вариант с именем из первого варианта. Запомним этот момент и проследуем дальше.
MOVE, MOVE, MOVE!
Для управления сертификатами в системе есть инструмент "Хранилище сертификатов", запустить его можно командой "certmgr.msc" (для текущего пользователя) или "certlm.msc" (для всей системы). Выглядит всё это дело примерно так:
Для текущего пользователя возможностей меньше, чем для системы и естественно, изменения для системы будут учитываться для всех пользователей ОС, и да - для внесения изменений в системные настройки нужны "права админа" (или системные привилегии). Как их получить - неважно, не про это статья. Дальше обрати внимание на раздел "Сертификаты, к которым нет доверия". Да-да - это именно то, ради чего началась вся заварушка. Сюда мы и будем добавлять сертификат приложения, которое хотим заблокировать от дальнейшего запуска.
Как обычно есть несколько вариантов добавить сертификат в этот раздел:
1) Вручную - кликаем ПКМ на этом разделе и выбираем "Все задачи" -> "Импорт". Тут всё предельно просто, клац-клац-клац и выбираем файл сертификата.
2) Через утилиту "CertMgr" (certmgr.exe) из состава Visual Studio (https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/). Тут можно посмотреть все параметры, которые можно использовать с этой утилитой - https://docs.microsoft.com/en-us/dotnet/framework/tools/certmgr-exe-certificate-manager-tool. Конкретно нас будет интересовать следующая "конструкция":
certmgr.exe /add "ESET, spol. s r.o..cer" /s /r currentUser Disallowed
3) Метод "ТыжПрограммист" - по всем канонам WinAPI и богоугодной сишечки:
C:
#pragma comment(linker, "/ENTRY:ExeMain") //потому что я тут главный
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "crypt32.lib")
#include <Windows.h>
#include <WinCrypt.h>
//имя файла сертификата, при желании можно указать полный путь, иначе оно должно находиться рядом с .exe
#define CER_PATH L"ESET, spol. s r.o..cer"
void ExeMain(){
HCERTSTORE hSysStore;
PCCERT_CONTEXT pCertContext;
HANDLE hCertFile;
BYTE *pCertData;
DWORD dwReadBytes;
DWORD dwCertSize;
//открываем файл сертификата
hCertFile = CreateFileW(CER_PATH, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hCertFile != INVALID_HANDLE_VALUE){
//узнаём размер файла
dwCertSize = GetFileSize(hCertFile, NULL);
if (dwCertSize != INVALID_FILE_SIZE){
//выделяем буфер и читаем данные сертификата
pCertData = LocalAlloc(LPTR, dwCertSize);
ReadFile(hCertFile, pCertData, dwCertSize, &dwReadBytes, NULL);
CloseHandle(hCertFile);
//открываем хранилище сертификатов, а конкретно тот самый раздел "Сертификаты, к которым нет доверия"
hSysStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, L"Disallowed");
if (hSysStore){
//формируем контекст для сохранения данных сертификата
pCertContext = CertCreateCertificateContext(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, pCertData, dwCertSize);
if (pCertContext){
CertAddCertificateContextToStore(hSysStore, pCertContext, CERT_STORE_ADD_USE_EXISTING, NULL);
CertFreeCertificateContext(pCertContext);
}
//закроем хранилище
CertCloseStore(hSysStore, 0);
}
//освободим буфер
LocalFree(pCertData);
}
}
//завершим наш процесс
ExitProcess(0);
}
С этим кодесом ты будешь тем самым сыном маминой подруги и вообще первым сеньор-кодером на районе, не благодари ^_^.
FINISH HIM!
В результате этих манипуляций у нас должна появиться запись в разделе "Сертификаты, к которым нет доверия" инструмента "Хранилище сертификатов":
А теперь следи за руками
Поздравляю, цель достигнута - запуск приложения заблокирован самой ОС, а сертификат "в бане" и только его удаление разблокирует возможность запуска приложений, которые подписаны данным сертификатом.
p.s.: Стоит отметить, что у многих вендоров (производителей ПО) один и тот же сертификат, что позволяет массово блокировать запуск различных приложений одного вендора. Теперь ты чуть больше стал знать о сертификатах цифровой подписи приложений в ОС Windows, а вот тто ты будешь делать с этими знаниями я понятия не имею
. Поделюсь наблюдениями. Протестил на AnyDesk, загнал в блок для системы целиком, после ребута все прекрасно стартануло, и сервис, и юзермодная часть, но при попытке ПКМ->Выход (по сути запуск AnyDesk.exe --stop-service) получаем красный алерт о невозможности запуска.