Как я могу проверить, что dll, содержащая используемую мной библиотеку ActiveX, подписана моим сертификатом?
Я знаю, как проверить подпись исполняемого файла или DLL по местоположению из этого вопроса: программная проверка цифровой подписи из Delphi
Как я могу узнать, что используемая мной библиотека ActiveX подписана моим сертификатом?
Исполняемый файл может проверить dll, если он знает свое местоположение, но я хочу быть очень уверен, что это тот, который исполняемый файл использует в данный момент. Я знаю, что могу использовать реестр, чтобы найти местоположение библиотеки DLL (из идентификаторов объектов или идентификаторов библиотек), но это кажется слабым местом, уязвимым для подмены.
Фон:
Я создал библиотеку ActiveX с объектом автоматизации. Я подписываю библиотеку dll и приложение-потребитель тем же сертификатом. Я уже могу проверить потребительское приложение из библиотеки следующим образом
TSomeAutomationObj = class(TAutoObject, ISomeAutomationObj)
public
procedure Initialize; override;
end;
procedure TSomeAutomationObj.Initialize;
const
BufferSize = 2048;
var
LProcessPath: PChar;
begin
LProcessPath := StrAlloc(BufferSize);
try
GetModuleFileName(0, LProcessPath, BufferSize);
//Check signature of LProcessPath Executable as described here https://stackru.com/questions/5993877/checking-digital-signature-programmatically-from-delphi
finally
StrDispose(LProcessPath);
end;
end;
initialization
TAutoObjectFactory.Create(ComServer, TSomeAutomationObj, Class_SomeAutomationObj,
ciMultiInstance, tmApartment);
То, что остается сейчас, это проверка в другом направлении (выполнимо для dll).
Объекты автоматизации будут зарегистрированы, и я буду использовать объект автоматизации следующим образом
uses
LibraryThatHoldsAutomationObject_TLB;
TObjectWithApplicationLifetime = class
private
FSomeAutoObj : ISomeAutomationObj;
public
Constructor Create;
end;
Constructor TObjectWithApplicationLifetime.Create;
begin
FSomeAutoObj := CoSomeAutomationObj.Create;
// Check that the source library of this object is signed with my certificate
// If so, then use FSomeAutoObj else set it to nil, set a flag or prevent usage other ways
end;
1 ответ
Аналогичная проблема была рассмотрена в другом вопросе в прошлом году. Техника включает выбор адреса VMT интерфейса (или vtable), а затем запрос ОС, какому модулю принадлежит эта память.
Ссылка на интерфейс - это указатель на некоторые данные для объекта. Первые байты этих данных, в свою очередь, являются указателями на VMT для интерфейса.
var
VMT: Pointer;
Information: TMemoryBasicInformation;
DLL: HModule;
VMT := PPointer(FSomeAutoObj)^;
Win32Check(VirtualQueryEx(GetCurrentProcess, VMT, Information, SizeOf(Information)) = SizeOf(Information));
DLL := HModule(Information.AllocationBase);
Когда этот код закончен, DLL
должен содержать дескриптор библиотеки DLL, которая содержит объект, реализующий интерфейс. Вызов GetModuleFileName
на это как в вопросе.
Есть несколько предположений, необходимых для его работы:
Это должен быть внутрипроцессный COM-объект; для объекта вне процесса VMT будет прокси-сервером, а не реальным объектом.
Объект не должен находиться за каким-либо другим прокси-сервером, например, вставленным компилятором. (Я не думаю, что Delphi делает это, но я не уверен. Просто убедитесь, что указатель интерфейса у вас был предоставлен DLL, а не RTL.)
VMT интерфейса должен быть статическим. Это будет иметь место для большинства интерфейсов, реализованных в Delphi или C++, но интерфейсы, реализованные другими способами, например с языками сценариев, могут иметь таблицы методов, выделенные в куче. В этом случае
DLL
Переменная выше не будет содержать дескриптор модуля.
Другое предположение состоит в том, что даже если DLL не подписана требуемым сертификатом, она все равно достаточно надежна для загрузки в память. Вы проверяете библиотеку DLL только после того, как загрузили ее в свое пространство процесса и начали выполнять ее код. (Загрузка DLL вызывает его DllMain
функция. Создание объекта COM включает в себя вызов DLL DllGetClassObject
функция плюс все остальное, что решит сделать конструктор COM-объекта.) Если вы не можете доверять неправильно подписанным DLL, значит, вы уже опоздали.