如何检查保存我使用的 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 ,那你已经来不及了。
我知道如何从这个问题中按位置检查可执行文件或 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 ,那你已经来不及了。