Как я могу проверить, что 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, значит, вы уже опоздали.

Другие вопросы по тегам