如何检查保存我使用的 ActiveX 库的 dll 是否使用我的证书签名?

How can I check that the dll that holds the ActiveX library that I use is signed with my certificate?

我知道如何从这个问题中按位置检查可执行文件或 dll 的签名:Checking digital signature programmatically from Delphi

我怎么知道我正在使用的 ActiveX 库是用我的证书签名的?

如果可执行文件知道它的位置,它可以检查 dll,但我想非常确定它是可执行文件当时正在使用的那个。我知道我可以使用注册表找到库 dll 位置(从对象 ID 或库 ID),但这似乎是一个容易受到欺骗的弱点。

背景:

我创建了一个带有自动化对象的 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 
  finally
    StrDispose(LProcessPath);
  end;

end;

initialization
  TAutoObjectFactory.Create(ComServer, TSomeAutomationObj, Class_SomeAutomationObj,
ciMultiInstance, tmApartment);

现在剩下的就是反方向的检查(Executable to 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; 

another question last year 中涵盖了类似的问题。该技术涉及获取接口的 VMT(或 vtable)的地址,然后询问 OS 哪个模块拥有该内存。

接口引用是指向对象某些数据的指针。该数据的第一个字节又是指向接口的 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 将是代理的 VMT,而不是真实对象。

  • 对象不得位于任何其他类型的代理之后,例如编译器插入的代理。 (我不 认为 Delphi 这样做,但我不确定。只需确保您拥有的接口指针是由 DLL 而不是 RTL 提供的。 )

  • 接口的VMT需要静态化。大多数以 Delphi 或 C++ 实现的接口都是这种情况,但以其他方式(例如脚本语言)实现的接口可能会在堆上分配方法表。在这种情况下,上面的 DLL 变量不会真正包含模块句柄。

另一个假设是,即使 DLL 没有由您所需的证书签名,它仍然足够可信,可以首先加载到内存中。在将 DLL 加载到您的进程 space 并开始执行其代码后,您只是在测试 DLL 。 (加载 DLL 调用其 DllMain 函数。实例化 COM 对象涉及调用 DLL 的 DllGetClassObject 函数以及 COM 对象的构造函数决定执行的任何其他操作。)如果您不能信任未正确签名的 DLL ,那你已经来不及了。