Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

Проверка цифровой подписи PE файла - подводные камни


Eraser ©   (10.04.17 20:57

Есть ПО, состоящее из двух исполняемых файлов. Возникла необходимость проверить цифровую подпись одного из них другим. С самой проверкой проблемы быть не должно, в сети полно примеров, например, https://msdn.microsoft.com/en-us/library/aa382384

Вопрос, собственно, о подводных камнях, к тем кто сталкивался с такими проверками в реальной жизни. Может ли возникнуть такая ситуация, что, по какой-то причине, валидная подпись будет определяться не валидной? Т.е. какова надежность данного механизма проверки (через WinVerifyTrust)? Не поломается ли оно на каких-то машинах с определенными настройками ОС?


Rouse_ ©   (10.04.17 21:09[1]


> Вопрос, собственно, о подводных камнях, к тем кто сталкивался
> с такими проверками в реальной жизни. Может ли возникнуть
> такая ситуация, что, по какой-то причине, валидная подпись
> будет определяться не валидной?

Есть конечно, если каталог с подписями снесен - все родные файлы (в особенности дрова) ОС будут без подписи ибо она не помещена у них в тело PE файла.
А так вроде бы других ошибок за последние 10 лет (или когда мы там цифровую то повесили, запямятовал уже) не встречал.


Rouse_ ©   (10.04.17 21:12[2]

Кстати в твоем примере самый простейший вариант и на системных файлах не отработает, нужно каталоги подключать. примерно так:

const
 WTD_CHOICE_FILE = 1;
 WTD_CHOICE_CATALOG = 2;
 WTD_STATEACTION_IGNORE = 0;
 WTD_STATEACTION_VERIFY = 1;
 WTD_UI_NONE = 2;
 WTD_REVOKE_NONE = 0;
 WTD_SAFER_FLAG = 256;
 WINTRUST_ACTION_GENERIC_VERIFY_V2: TGUID = '{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}';
 WINTRUST_ACTION_GENERIC_VERIFY_V7: TGUID = '{F750E6C3-38EE-11D1-85E5-00C04FC295EE}';

type
 CATALOG_INFO = record
   cbStruct: DWORD; // = sizeof(WINTRUST_CATALOG_INFO)
   sCatalogFile: array[0..MAX_PATH] of WCHAR;
 end;
 PCATALOG_INFO = ^CATALOG_INFO;

 WINTRUST_CATALOG_INFO = record
   cbStruct: DWORD; // = sizeof(WINTRUST_CATALOG_INFO)
   dwCatalogVersion: DWORD;
   pcwszCatalogFilePath: LPCWSTR;
   pcwszMemberTag: LPCWSTR;
   pcwszMemberFilePath: LPCWSTR;
   hMemberFile: THANDLE;
 end;
 PWINTRUST_CATALOG_INFO = ^WINTRUST_CATALOG_INFO;

 WINTRUST_FILE_INFO = record
   cbStruct: DWORD; // = sizeof(WINTRUST_FILE_INFO)
   pcwszFilePath: LPCWSTR;
   pgKnownSubject: PGUID;
   hFile: THANDLE;
 end;
 PWINTRUST_FILE_INFO = ^WINTRUST_FILE_INFO;

 WINTRUST_DATA = packed record
   cbStruct: DWORD; // = sizeof(WINTRUST_DATA)
   pPolicyCallbackData: pointer;
   pSIPClientData: pointer;
   dwUIChoice: DWORD;
   fdwRevocationChecks: DWORD;
   dwUnionChoice: DWORD;
   pWTDINFO: pointer;
   pFake: pointer;
   pFake1: pointer;
   pFake2: pointer;
   pFake3: pointer;
   dwStateAction: DWORD;
   hWVTStateData: THANDLE;
   pwszURLReference: PWChar;
   dwProvFlags: DWORD;
   dwUIContext: DWORD;
 end;
 PWINTRUST_DATA = ^WINTRUST_DATA;
 HCatAdmin = THANDLE;
 PHCatAdmin = ^HCatAdmin;

var
 hLibWintrust: THandle;
 CryptCATAdminAcquireContext : function(PHCatAdmin: PHCatAdmin; pgSubsystem: PGUID; dwFlags: DWORD): BOOL; stdcall;
 CryptCATAdminReleaseContext : function(HCatAdmin: HCatAdmin; dwFlags: DWORD): BOOL; stdcall;
 CryptCATAdminCalcHashFromFileHandle: function(hFile: THANDLE; pHashSize: PDWORD; pbHash: PByteArray; dwFlags: DWORD): BOOL; stdcall;
 CryptCATAdminEnumCatalogFromHash: function(HCatAdmin: HCatAdmin; pbHash: PByteArray; pHashSize: DWORD; dwFlags: DWORD; phPrevCatInfo: PHandle): THANDLE; stdcall;
 CryptCATCatalogInfoFromContext: function(hCatInfo: THANDLE; psCatInfo: PCATALOG_INFO; dwFlags: DWORD): BOOL; stdcall;
 CryptCATAdminReleaseCatalogContext: function(HCatAdmin: HCatAdmin; hCatInfo: THANDLE; dwFlags: DWORD): BOOL; stdcall;
 WinVerifyTrust : function(hwnd: THANDLE; pgActionID: PGUID; pWintrustData: PWINTRUST_DATA): Longint; stdcall;

function CheckFileTrust(const sFilename: string): Boolean;
var
 aByteHash : array[0..255] of Byte;
 iByteCount : Integer;
 hCatAdminContext : HCatAdmin;
 WTrustData : WINTRUST_DATA;
 WTDCatalogInfo : WINTRUST_CATALOG_INFO;
 WTDFileInfo : WINTRUST_FILE_INFO;
 CatalogInfo : CATALOG_INFO;
 hFile : THANDLE;
 hCatalogContext : THANDLE;
 swFilename : WideString;
 swMemberTag : WideString;
 x : Integer;
begin
 Result := False;
 if not FileExists(sFilename) then Exit;
 swFilename := sFilename;
 ZeroMemory(@CatalogInfo, SizeOf(CatalogInfo));
 ZeroMemory(@WTDFileInfo, SizeOf(WTDFileInfo));
 ZeroMemory(@WTDCatalogInfo, SizeOf(WTDCatalogInfo));
 ZeroMemory(@WTrustData, SizeOf(WTrustData));
 if CryptCATAdminAcquireContext(@hCatAdminContext, nil, 0) = False then Exit;
 hFile := CreateFile(PChar(string(sFilename)), GENERIC_READ,
   FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
 if hFile = INVALID_HANDLE_VALUE then Exit;
 iByteCount := SizeOf(aByteHash);
 CryptCATAdminCalcHashFromFileHandle(hFile, @iByteCount, @aByteHash, 0);
 for x := 0 to iByteCount - 1 do
   swMemberTag := swMemberTag + IntToHex(aByteHash[x], 2);
 CloseHandle(hFile);
 hCatalogContext := CryptCATAdminEnumCatalogFromHash(hCatAdminContext, @aByteHash, iByteCount, 0, nil);
 if hCatalogContext = 0 then
 begin
   WTDFileInfo.cbStruct := SizeOf(WTDFileInfo);
   WTDFileInfo.pcwszFilePath := PWideChar(swFilename);
   WTDFileInfo.pgKnownSubject := nil;
   WTDFileInfo.hFile := 0;
   WTrustData.cbStruct := SizeOf(WTrustData);
   WTrustData.dwUnionChoice := WTD_CHOICE_FILE;
   WTrustData.pWTDINFO := @WTDFileInfo;
   WTrustData.dwUIChoice := WTD_UI_NONE;
   WTrustData.fdwRevocationChecks := WTD_REVOKE_NONE;
   WTrustData.dwStateAction := WTD_STATEACTION_IGNORE;
   WTrustData.dwProvFlags := WTD_SAFER_FLAG;
   WTrustData.hWVTStateData := 0;
   WTrustData.pwszURLReference := nil;
 end
 else
 begin
   CryptCATCatalogInfoFromContext(hCatalogContext, @CatalogInfo, 0);
   WTDCatalogInfo.cbStruct := SizeOf(WTDCatalogInfo);
   WTDCatalogInfo.pcwszCatalogFilePath := CatalogInfo.sCatalogFile;
   WTDCatalogInfo.pcwszMemberFilePath := PWideChar(swFilename);
   WTDCatalogInfo.pcwszMemberTag := PWideChar(swMemberTag);
   WTrustData.cbStruct := SizeOf(WTrustData);
   WTrustData.dwUnionChoice := WTD_CHOICE_CATALOG;
   WTrustData.pWTDINFO := @WTDCatalogInfo;
   WTrustData.dwUIChoice := WTD_UI_NONE;
   WTrustData.fdwRevocationChecks := WTD_REVOKE_NONE;
   WTrustData.pPolicyCallbackData := nil;
   WTrustData.pSIPClientData := nil;
   WTrustData.dwStateAction := WTD_STATEACTION_VERIFY;
   WTrustData.dwProvFlags := 0;
   WTrustData.hWVTStateData := 0;
   WTrustData.pwszURLReference := nil;
 end;
 Result := WinVerifyTrust(INVALID_HANDLE_VALUE, @WINTRUST_ACTION_GENERIC_VERIFY_V2, @WTrustData) = 0;
 if not Result then
   Result := WinVerifyTrust(INVALID_HANDLE_VALUE, @WINTRUST_ACTION_GENERIC_VERIFY_V7, @WTrustData) = 0;
 CryptCATAdminReleaseCatalogContext(hCatAdminContext, hCatalogContext, 0);
 CryptCATAdminReleaseContext(hCatAdminContext, 0);
end;


Eraser ©   (10.04.17 22:55[3]


> Rouse_ ©   (10.04.17 21:09) [1]


> Есть конечно, если каталог с подписями снесен - все родные
> файлы (в особенности дрова) ОС будут без подписи ибо она
> не помещена у них в тело PE файла.

требуется проверять только свои файлы.

> А так вроде бы других ошибок за последние 10 лет (или когда
> мы там цифровую то повесили, запямятовал уже) не встречал.
>

это радует. будет пробовать внедрять проверку.


> Кстати в твоем примере самый простейший вариант и на системных
> файлах не отработает, нужно каталоги подключать. примерно
> так:

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


DVM ©   (19.04.17 14:02[4]


> Eraser ©   (10.04.17 20:57) 


> Вопрос, собственно, о подводных камнях, к тем кто сталкивался
> с такими проверками в реальной жизни. Может ли возникнуть
> такая ситуация, что, по какой-то причине, валидная подпись
> будет определяться не валидной? Т.е. какова надежность данного
> механизма проверки (через WinVerifyTrust)? Не поломается
> ли оно на каких-то машинах с определенными настройками ОС?
>

Может. Если в системе есть зловреды, подменившие корневые сертификаты.


Eraser ©   (19.04.17 15:32[5]

еще выяснился такой момент, что без интернета и апдейтов современные sha256 сертификаты работают из коробки только начиная с 7, но в принципе, этого достаточно.


Rouse_ ©   (19.04.17 20:18[6]

Да вроде нет такого, как проверял?
Линк ка экзешник дай, проверю на тестовой вм


Eraser ©   (20.04.17 04:42[7]


> Rouse_ ©   (19.04.17 20:18) [6]

_remoteutilities.com/download/agent.exe

на висте sp0 не работает.
Нет доверия к этому корневому сертификату центра сертификации, поскольку он не найден в хранилище доверенных корневых сертификатов центров сертификации.

ну с xp все понятно, там его вообще поврежденным считают.


Eraser ©   (20.04.17 04:55[8]


> Eraser ©   (19.04.17 15:32) [5]
> еще выяснился такой момент

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


DVM ©   (20.04.17 08:01[9]

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


Eraser ©   (20.04.17 13:03[10]


> DVM ©   (20.04.17 08:01) [9]

ну если зловред подменит корневые, значит так тому и быть.
у меня основная задача, чтобы "сборщики" не использовали наше ПО в качестве вредоносного, не внося каких-либо изменений в код или ОС. патчи, лоадеры и прочие дропперы, оставляем пока на совести антивирусов. они довольно не плохо справляются.


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо