验证可执行文件的 Authenticode 签名时内存泄漏?
我正在使用 WinVerifyTrust 来验证具有以下函数的某些 Windows 可执行文件的有效性,从 _tmain 循环调用:
int signature_is_valid(const wchar_t *filepath) {
GUID guid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_FILE_INFO file_info = { 0 };
WINTRUST_DATA wd;
file_info.cbStruct = sizeof(file_info);
file_info.pcwszFilePath = filepath;
file_info.hFile = NULL;
file_info.pgKnownSubject = NULL;
ZeroMemory(&wd, sizeof(wd));
wd.cbStruct = sizeof(wd);
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_REVOCATION_CHECK_NONE;
wd.dwUnionChoice = WTD_CHOICE_FILE;
wd.dwStateAction = 0;
wd.pFile = &file_info;
wd.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT | WTD_CACHE_ONLY_URL_RETRIEVAL;
return 0 == WinVerifyTrust(NULL, &guid, &wd);
}
但是,随着每个循环,内存不断增长,这是内存泄漏的明确迹象。
我对 API 的理解是否有问题,或者 WinVerifyTrust 函数实际上是否存在泄漏?我正在 Windows XP Professional SP3
系统上对此进行测试。
编辑:
这是umdh
的一些输出:
+ 16812 ( 16992 - 180) 472 allocs BackTraceAD1
+ 467 ( 472 - 5) BackTraceAD1 allocations
ntdll!RtlDebugAllocateHeap+000000E1
ntdll!RtlAllocateHeapSlowly+00000044
ntdll!RtlAllocateHeap+00000E64
kernel32!LocalAlloc+00000058
CRYPT32!operator new+00000011
CRYPT32!I_CryptCreateLruEntry+00000011
CRYPT32!CreateAuthRootAutoUpdateMatchCaches+00000107
CRYPT32!CCertChainEngine::FindAuthRootAutoUpdateMatchingCtlEntries+0000004D
CRYPT32!CChainPathObject::GetAuthRootAutoUpdateUrlStore+000000C9
CRYPT32!CChainPathObject::CChainPathObject+0000030E
CRYPT32!ChainCreatePathObject+00000050
CRYPT32!CCertIssuerList::AddIssuer+0000006A
CRYPT32!CChainPathObject::FindAndAddIssuersFromStoreByMatchType+00000182
CRYPT32!CChainPathObject::FindAndAddIssuersByMatchType+00000096
CRYPT32!CChainPathObject::FindAndAddIssuers+00000023
CRYPT32!CChainPathObject::CChainPathObject+000001F9
CRYPT32!ChainCreatePathObject+00000050
CRYPT32!CCertIssuerList::AddIssuer+0000006A
CRYPT32!CChainPathObject::FindAndAddIssuersFromCacheByMatchType+00000084
CRYPT32!CChainPathObject::FindAndAddIssuersByMatchType+00000023
CRYPT32!CChainPathObject::FindAndAddIssuers+00000063
CRYPT32!CChainPathObject::CChainPathObject+000001F9
CRYPT32!ChainCreatePathObject+00000050
CRYPT32!CCertChainEngine::CreateChainContextFromPathGraph+0000019E
CRYPT32!CCertChainEngine::GetChainContext+00000044
CRYPT32!CertGetCertificateChain+00000060
WINTRUST!_WalkChain+0000019C
WINTRUST!WintrustCertificateTrust+000000B7
WINTRUST!_VerifyTrust+00000144
WINTRUST!WinVerifyTrust+0000004E
SigTest!signature_is_valid+000000DD
+ 10984 ( 10984 - 0) 2 allocs BackTraceBB3
+ 2 ( 2 - 0) BackTraceBB3 allocations
ntdll!RtlDebugAllocateHeap+000000E1
ntdll!RtlAllocateHeapSlowly+00000044
ntdll!RtlAllocateHeap+00000E64
kernel32!LocalAlloc+00000058
CRYPT32!PkiDefaultCryptAlloc+00000011
CRYPT32!CertFindCertificateInCRL+00000051
cryptnet!MicrosoftCertDllVerifyRevocation+00000250
CRYPT32!I_CryptRemainingMilliseconds+0000021B
CRYPT32!CertVerifyRevocation+000000B7
CRYPT32!CChainPathObject::CalculateRevocationStatus+000001F2
CRYPT32!CChainPathObject::CalculateAdditionalStatus+00000147
CRYPT32!CCertChainEngine::CreateChainContextFromPathGraph+00000227
CRYPT32!CCertChainEngine::GetChainContext+00000044
CRYPT32!CertGetCertificateChain+00000060
WINTRUST!_WalkChain+0000019C
WINTRUST!WintrustCertificateTrust+000000B7
WINTRUST!_VerifyTrust+00000144
WINTRUST!WinVerifyTrust+0000004E
SigTest!signature_is_valid+000000DD
SigTest!wmain+00000073
SigTest!__tmainCRTStartup+000001A8
SigTest!wmainCRTStartup+0000000F
kernel32!BaseProcessStart+00000023
在我看来,CRYPT32
函数是泄漏的......或者我丢失了某物。
EDIT2
这是数千个循环的内存演变:
I am using WinVerifyTrust to verify the validity of some Windows executables with the following function, called in a loop from _tmain
:
int signature_is_valid(const wchar_t *filepath) {
GUID guid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_FILE_INFO file_info = { 0 };
WINTRUST_DATA wd;
file_info.cbStruct = sizeof(file_info);
file_info.pcwszFilePath = filepath;
file_info.hFile = NULL;
file_info.pgKnownSubject = NULL;
ZeroMemory(&wd, sizeof(wd));
wd.cbStruct = sizeof(wd);
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_REVOCATION_CHECK_NONE;
wd.dwUnionChoice = WTD_CHOICE_FILE;
wd.dwStateAction = 0;
wd.pFile = &file_info;
wd.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT | WTD_CACHE_ONLY_URL_RETRIEVAL;
return 0 == WinVerifyTrust(NULL, &guid, &wd);
}
However, with every loop the memory keeps growing, a sure sign of a memory leak.
Is there a problem with my understanding of the API
or is the WinVerifyTrust
function actually leaking? I am testing this on a Windows XP Professional SP3
system.
EDIT:
Here is some output from umdh
:
+ 16812 ( 16992 - 180) 472 allocs BackTraceAD1
+ 467 ( 472 - 5) BackTraceAD1 allocations
ntdll!RtlDebugAllocateHeap+000000E1
ntdll!RtlAllocateHeapSlowly+00000044
ntdll!RtlAllocateHeap+00000E64
kernel32!LocalAlloc+00000058
CRYPT32!operator new+00000011
CRYPT32!I_CryptCreateLruEntry+00000011
CRYPT32!CreateAuthRootAutoUpdateMatchCaches+00000107
CRYPT32!CCertChainEngine::FindAuthRootAutoUpdateMatchingCtlEntries+0000004D
CRYPT32!CChainPathObject::GetAuthRootAutoUpdateUrlStore+000000C9
CRYPT32!CChainPathObject::CChainPathObject+0000030E
CRYPT32!ChainCreatePathObject+00000050
CRYPT32!CCertIssuerList::AddIssuer+0000006A
CRYPT32!CChainPathObject::FindAndAddIssuersFromStoreByMatchType+00000182
CRYPT32!CChainPathObject::FindAndAddIssuersByMatchType+00000096
CRYPT32!CChainPathObject::FindAndAddIssuers+00000023
CRYPT32!CChainPathObject::CChainPathObject+000001F9
CRYPT32!ChainCreatePathObject+00000050
CRYPT32!CCertIssuerList::AddIssuer+0000006A
CRYPT32!CChainPathObject::FindAndAddIssuersFromCacheByMatchType+00000084
CRYPT32!CChainPathObject::FindAndAddIssuersByMatchType+00000023
CRYPT32!CChainPathObject::FindAndAddIssuers+00000063
CRYPT32!CChainPathObject::CChainPathObject+000001F9
CRYPT32!ChainCreatePathObject+00000050
CRYPT32!CCertChainEngine::CreateChainContextFromPathGraph+0000019E
CRYPT32!CCertChainEngine::GetChainContext+00000044
CRYPT32!CertGetCertificateChain+00000060
WINTRUST!_WalkChain+0000019C
WINTRUST!WintrustCertificateTrust+000000B7
WINTRUST!_VerifyTrust+00000144
WINTRUST!WinVerifyTrust+0000004E
SigTest!signature_is_valid+000000DD
+ 10984 ( 10984 - 0) 2 allocs BackTraceBB3
+ 2 ( 2 - 0) BackTraceBB3 allocations
ntdll!RtlDebugAllocateHeap+000000E1
ntdll!RtlAllocateHeapSlowly+00000044
ntdll!RtlAllocateHeap+00000E64
kernel32!LocalAlloc+00000058
CRYPT32!PkiDefaultCryptAlloc+00000011
CRYPT32!CertFindCertificateInCRL+00000051
cryptnet!MicrosoftCertDllVerifyRevocation+00000250
CRYPT32!I_CryptRemainingMilliseconds+0000021B
CRYPT32!CertVerifyRevocation+000000B7
CRYPT32!CChainPathObject::CalculateRevocationStatus+000001F2
CRYPT32!CChainPathObject::CalculateAdditionalStatus+00000147
CRYPT32!CCertChainEngine::CreateChainContextFromPathGraph+00000227
CRYPT32!CCertChainEngine::GetChainContext+00000044
CRYPT32!CertGetCertificateChain+00000060
WINTRUST!_WalkChain+0000019C
WINTRUST!WintrustCertificateTrust+000000B7
WINTRUST!_VerifyTrust+00000144
WINTRUST!WinVerifyTrust+0000004E
SigTest!signature_is_valid+000000DD
SigTest!wmain+00000073
SigTest!__tmainCRTStartup+000001A8
SigTest!wmainCRTStartup+0000000F
kernel32!BaseProcessStart+00000023
It seems to me that the CRYPT32
functions are the ones leaking... or I'm missing something.
EDIT2
Here is the memory evolution for some thousand loops:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我没有看到这个 API 泄露的任何信息。也许这只是过程中的堆碎片?
您可以使用 umdh 在时间 X 和 X+delta 拍摄进程快照来验证这一点,然后分析那些时间的对比堆使用情况。确保所有符号都可用,这样才能最有帮助。
I don't see any info that this API leaks. perhaps it's just heap fragmentation in the process?
You can verify this for sure using umdh to take snapshots of your process at time X and X+delta, then analyze the comparative heap usage at those times. Make sure all symbols are available for this to be most helpful.
(编辑:看看新的图表,我错了。)
根据调用堆栈中的“I_CryptCreateLruEntry”,我的猜测是这不是内存泄漏;而是内存泄漏。它只是 API 以有界的方式缓存数据。即它不会无限期地增长。
LRU 这个名字表明它将获得的证书存储在最近最少使用的缓存中以加快可能涉及同一证书的后续操作。
如果您在循环中运行代码,发现它使用了几兆字节,并且在多次迭代后仍在增长,那么可能存在泄漏,或者配置非常糟糕的缓存算法,但否则我会说您可能没有什么可担心的。
(Edit: Looking at the new graphs, I was wrong.)
Based on "I_CryptCreateLruEntry" in the callstack, my guess is that this is not a memory leak; it is just the API caching data in a bounded way. i.e. It will not grow indefinitely.
LRU in that name suggests it is storing the certificate it obtained in a Least Recently Used cache in order to speed up subsequent operations that may involve the same certificate.
If you run the code in a loop and find it is using several megabytes and still growing after many iterations then maybe there is a leak, or a very poorly configured caching algorithm, but otherwise I'd say you probably have nothing to worry about.
根据 WINTRUST_DATA 的 MSDN 文档< /a>,Windows XP 或 Windows 2000 不支持 WTD_CACHE_ONLY_URL_RETRIEVAL。我怀疑这与明显的泄漏有什么关系,但认为可能值得指出。
According to MSDN documenation of WINTRUST_DATA, WTD_CACHE_ONLY_URL_RETRIEVAL is not supported on Windows XP or Windows 2000. I doubt that has anything to do with the apparent leakage, but thought it might be worth pointing out.
是的。如果您的 crypt32.dll 文件版本足够低,则会出现非常烦人的内存泄漏。
看
http://social.technet .microsoft.com/Forums/en-US/itproxpsp/thread/c11530e8-56e2-4bb3-a887-f7809e644861
并安装修补程序 KB2641690 进行修复
YES. If you have a low enough version of the crypt32.dll file there is a very annoying memory leak.
see
http://social.technet.microsoft.com/Forums/en-US/itproxpsp/thread/c11530e8-56e2-4bb3-a887-f7809e644861
and install hotfix KB2641690 for fix