每次调用静态 link 函数都会在 windows 8/10 而不是 7 崩溃
Call of statically link function crash everytimes on windows 8/10 but not 7
问题:
我已经构建了 https://github.com/reorg/pg_repack 生成二进制文件的项目。此二进制文件与 postgres 9.6 可再发行版链接(我使用由 EntrepriseDb 提供的那些)。
在 windows 7 上一切正常。我在构建期间或运行期间没有遇到任何问题。但是在 windows 8 或 10 上,应用程序总是崩溃并出现以下序列。
二进制文件是从 visual studio 2013 的 C 源代码生成的,在 windows 7 上(我尝试过在 windows 10 上生成的版本,但它没有改变任何东西),在 x64 系统上,对于 x64 应用程序,优化被禁用,它使用动态基础。
为确保我使用正确的二进制文件,我已将所有可再分发的二进制文件复制到我的应用程序的文件夹中。
windows7(工作案例)的组装细节:
main 之后的几行,应用程序调用函数 set_pglocale_pgservice
set_pglocale_pgservice(argv[0], "pgscripts");
00007FF6E4B39C85 mov eax,8
00007FF6E4B39C8A imul rax,rax,0
00007FF6E4B39C8E lea rdx,[default_options+120h (07FF6E4B43B10h)]
00007FF6E4B39C95 mov rcx,qword ptr [argv]
00007FF6E4B39C9A mov rcx,qword ptr [rcx+rax]
00007FF6E4B39C9E call qword ptr [__imp_set_pglocale_pgservice (07FF6E4B40520h)]
内存在 07FF6E4B40520h
0x00007FF6E4B40520 00000001403e1da0 .>@....
0x00007FF6E4B40528 0000000000000000 ........
0x00007FF6E4B40530 0000000000000000 ........
0x00007FF6E4B40538 00007ff6e4b35348 HS.äö...
(注意:从 0x7FF6E4B40000 到 0x00007FF6E4B40560 内存包含函数地址,映射文件说:0002:00000520 __imp_set_pglocale_pgservice postgres:postgres.exe [postgres 可再分发,动态链接])
然后调用qword ptr后[__imp_set_pglocale_pgservice(07FF6E4B40520h)]
00000001403E1DA0 mov qword ptr [rsp+18h],rbx
00000001403E1DA5 push rdi
00000001403E1DA6 sub rsp,0C40h
00000001403E1DAD mov rax,qword ptr [1405F8C60h]
00000001403E1DB4 xor rax,rsp
00000001403E1DB7 mov qword ptr [rsp+0C30h],rax
00000001403E1DBF mov rbx,rdx
00000001403E1DC2 mov rdi,rcx
00000001403E1DC5 lea rdx,[140430540h]
00000001403E1DCC mov rcx,rbx
00000001403E1DCF call 00000001403F67FA
然后调用00000001403F67FA后
00000001403F67FA jmp qword ptr [1403F8998h]
1403F8998h 处的内存
0x00000001403F8998 00007ffe87a5cc60 `Ì¥.þ...
0x00000001403F89A0 00007ffe87a47060 `p¤.þ...
0x00000001403F89A8 00007ffe87a5f8a4 ¤ø¥.þ...
(注意:从 0x00000001403F8000 到 0x00000001403F8F08 内存包含函数地址,映射文件说:0002:00000998 ??_C@_04FHBLDJDJ@?1bin?$AA@ libpgport:path.obj [postgres 可再分发,是静态链接])
然后跳转到00007ffe87a5cc60后
00007FFE87A5CC60 sub rdx,rcx
00007FFE87A5CC63 test cl,7
00007FFE87A5CC66 je 00007FFE87A5CC7C
...
一切正常
windows10 的组装细节(不是工作案例):
main 之后的几行,应用程序调用函数 set_pglocale_pgservice
set_pglocale_pgservice(argv[0], "pgscripts");
00007FF7E9879C85 mov eax,8
00007FF7E9879C8A imul rax,rax,0
00007FF7E9879C8E lea rdx,[default_options+120h (07FF7E9883B10h)]
00007FF7E9879C95 mov rcx,qword ptr [argv]
00007FF7E9879C9A mov rcx,qword ptr [rcx+rax]
00007FF7E9879C9E call qword ptr [__imp_set_pglocale_pgservice (07FF7E9880520h)]
内存在 07FF7E9880520h
0x00007FF7E9880520 00000001403e1da0 .>@....
0x00007FF7E9880528 0000000000000000 ........
0x00007FF7E9880530 0000000000000000 ........
0x00007FF7E9880538 00007ff7e9875348 HS.é÷...
(注意:从 0x00007FF7E9880000 到 0x00007FF7E9880560 内存包含函数地址,映射文件说:0002:00000520 __imp_set_pglocale_pgservice postgres:postgres.exe [postgres 可再分发,动态链接])
然后调用qword ptr后 [__imp_set_pglocale_pgservice (07FF7E9880520h)]
00000001403E1DA0 mov qword ptr [rsp+18h],rbx
00000001403E1DA5 push rdi
00000001403E1DA6 sub rsp,0C40h
00000001403E1DAD mov rax,qword ptr [1405F8C60h]
00000001403E1DB4 xor rax,rsp
00000001403E1DB7 mov qword ptr [rsp+0C30h],rax
00000001403E1DBF mov rbx,rdx
00000001403E1DC2 mov rdi,rcx
00000001403E1DC5 lea rdx,[140430540h]
00000001403E1DCC mov rcx,rbx
00000001403E1DCF call 00000001403F67FA
然后调用00000001403F67FA后
00000001403F67FA jmp qword ptr [1403F8998h] (should call C@_04FHBLDJDJ@?1bin?$AA@ libpgport:path.obj [postgres redistributable, which is linked statically]))
Memory at 1403F8998h (这里的应用程序不同于windows 7)
0x00000001403F8998 000000000059e6a2 ¢æY.....
0x00000001403F89A0 000000000059e6ac ¾Y.....
0x00000001403F89A8 000000000059e6b6 ¶æY.....
(注意:0x00000001403F8998是函数中间的操作码地址,不是函数地址)
00000001403F8998 mov byte ptr [AC000000000059E6h],al
00000001403F89A1 out 59h,al
00000001403F89A3 add byte ptr [rax],al
...
内存在 000000000059e6a2h
000000000059E69F ?? ??
000000000059E6A0 ?? ??
000000000059E6A1 ?? ??
然后跳转到000000000059e6a2之后
=>崩溃
关于 windows 7 的进程监视器详细信息,用于加载库(此处 libpq.dll):
[...]
"16:48:40,2946466","pg_repack.exe","7216","Load Image","C:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Image Base: 0x180000000, Image Size: 0x30000"
[...]
关于 windows 10 的进程监视器详细信息(这里是 libpq.dll)(除了加载库外,其他都与 windows 7 非常相似)
[...]
"11:52:20,6264717","pg_repack.exe","12464","QueryOpen","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","CreationTime: 21/08/2017 11:38:04, LastAccessTime: 21/08/2017 12:06:56, LastWriteTime: 09/05/2017 06:45:07, ChangeTime: 21/08/2017 18:04:09, AllocationSize: 184 320, EndOfFile: 183 296, FileAttributes: A"
"11:52:20,6265789","pg_repack.exe","12464","CreateFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Desired Access: Read Data/List Directory, Execute/Traverse, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened"
"11:52:20,6266332","pg_repack.exe","12464","QuerySecurityFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Information: 0x20"
"11:52:20,6266513","pg_repack.exe","12464","CreateFileMapping","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","FILE LOCKED WITH ONLY READERS","SyncType: SyncTypeCreateSection, PageProtection: PAGE_EXECUTE"
"11:52:20,6266921","pg_repack.exe","12464","CreateFileMapping","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","SyncType: SyncTypeOther"
"11:52:20,6267619","pg_repack.exe","12464","Load Image","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Image Base: 0x180000000, Image Size: 0x30000"
"11:52:20,6274889","pg_repack.exe","12464","CreateFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened"
"11:52:20,6275293","pg_repack.exe","12464","QuerySecurityFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Information: 0x20"
"11:52:20,6275471","pg_repack.exe","12464","QueryBasicInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","CreationTime: 21/08/2017 11:38:04, LastAccessTime: 21/08/2017 12:06:56, LastWriteTime: 09/05/2017 06:45:07, ChangeTime: 21/08/2017 18:04:09, FileAttributes: A"
"11:52:20,6276255","pg_repack.exe","12464","CloseFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS",""
"11:52:20,6291170","pg_repack.exe","12464","CloseFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS",""
[...]
"11:52:20,6539022","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF"
"11:52:20,6539202","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF"
"11:52:20,6539363","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF"
"11:52:20,6539512","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF"
"11:52:20,6539664","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF"
"11:52:20,6603867","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll"
"11:52:20,6604319","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll"
"11:52:20,6604778","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll"
"11:52:20,6605211","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll"
"11:52:20,6605635","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll"
[...]
注意:我期待类似于 windows 7 或至少类似的东西:
"11:52:20,6539022","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Length: 63".
所以我不知道为什么这个应用程序在 windows 8 或 10 上有如此奇怪的行为。如果有人能提供一些解释或想法来修复崩溃,我将非常高兴。如果需要,请不要犹豫,询问一些细节。
我查看了你的二进制包,发现你执行了 pg_repack.exe
,它是从 postgres.exe
静态导入的。问题的根源 - 是从 exe 文件导入。更确切地说,来自 PE 文件,该文件没有在 IMAGE_FILE_HEADER
.Characteristics
中标记 IMAGE_FILE_DLL
,因为正式扩展名 ( exe、dll等不起作用)。简而言之,我将在 exe 下表示 PE 文件没有 IMAGE_FILE_DLL
Characteristics
,但不是正式的文件扩展名
第一次加载 exe 因为 dll 不正确 - 当 exe 以这种方式加载时 -它没有调用入口点。并且不能被调用,因为它没有被设计为回调,接收DLL_PROCESS_*
通知,最后调用ExitProcess
。当模块的入口点没有被调用时——通常它没有被初始化。假设你从 exe 调用了一些导出函数,但是如果这个导出函数使用了一些通常在 exe 入口点初始化的数据怎么办?所以结论 - 我们只能从 exe 加载的 dll 调用导出函数 exe 进程。并且在每个进程中必须只有一个 exe(作为可执行代码)。
在第二个特定的 postgres.exe
没有重定位(IMAGE_FILE_HEADER.Characteristics
中的 IMAGE_FILE_RELOCS_STRIPPED
标志)- 结果这个 PE 只能在硬编码地址。这对 exe 来说不是问题,它总是首先映射到进程,而几乎所有地址 space 都是空闲的。但是当 PE 加载为 DLL 时,这通常是个问题 - 不是第一个进程 - 硬编码图像库可能已经很忙。所以结论 - 你不能安全地使用任何 exe 没有重定位的 DLL
但是 windows10 上的崩溃根源 - 因为 windows10 无法解析 PE ("exe") 如果这个 pe 有导入没有标志 IMAGE_FILE_DLL
。换句话说,它像 LoadLibraryEx
with flag DONT_RESOLVE_DLL_REFERENCES
- does not load additional executable modules that are referenced by the specified module and nor resolve imports. as result this PE not initialized and will crash at first import function call (in your case this is strcmp
一样处理这个 PE。
这只发生在 win10 上。在 win 8.1(内部版本 9600)和 win 7 上导入 exe 文件(加载为 dll)已解决。 (你说在你的 win 8.1 上它崩溃了 - 可能你使用了更多的新版本或一些更新?或者更好地检查)
从测试 exe MatchToken
函数调用此行为的最简单测试,该函数从 Netsh.exe
导出。代码可以是下一个:
#include <Netsh.h>
#pragma comment(linker, "/defaultlib:Netsh.lib")
MatchToken(L"*", L"*");// crash here on win 10
在 win10 上崩溃,因为 MatchToken
内部尝试从 msvcrt.dll
调用 _wcsnicmp
,但在 win10 中此导入未解决。但在 win8.1、win7、win xp 上 - 此代码运行良好。
稍微复杂一点的例子:
if (HMODULE hmod = LoadLibraryW(L"wshelper.dll"))
{
DWORD (WINAPI * InitHelperDll)(_In_ DWORD dwNetshVersion, PVOID pReserved);
if (*(void**)&InitHelperDll = GetProcAddress(hmod, "InitHelperDll"))
{
InitHelperDll(1, 0);// crash here on win10 only
}
FreeLibrary(hmod);
}
这里我们加载标准 windows NetShell helper dll - "wshelper.dll" 并调用 InitHelperDll
callback function. internally InitHelperDll
call the RegisterHelper
function from Netsh.exe. but again, because Netsh.exe not initialized (import not resolved) when it loades as DLL in win 10 - it crashed inside RegisterHelper
问题:
我已经构建了 https://github.com/reorg/pg_repack 生成二进制文件的项目。此二进制文件与 postgres 9.6 可再发行版链接(我使用由 EntrepriseDb 提供的那些)。 在 windows 7 上一切正常。我在构建期间或运行期间没有遇到任何问题。但是在 windows 8 或 10 上,应用程序总是崩溃并出现以下序列。 二进制文件是从 visual studio 2013 的 C 源代码生成的,在 windows 7 上(我尝试过在 windows 10 上生成的版本,但它没有改变任何东西),在 x64 系统上,对于 x64 应用程序,优化被禁用,它使用动态基础。 为确保我使用正确的二进制文件,我已将所有可再分发的二进制文件复制到我的应用程序的文件夹中。
windows7(工作案例)的组装细节:
main 之后的几行,应用程序调用函数 set_pglocale_pgservice
set_pglocale_pgservice(argv[0], "pgscripts");
00007FF6E4B39C85 mov eax,8
00007FF6E4B39C8A imul rax,rax,0
00007FF6E4B39C8E lea rdx,[default_options+120h (07FF6E4B43B10h)]
00007FF6E4B39C95 mov rcx,qword ptr [argv]
00007FF6E4B39C9A mov rcx,qword ptr [rcx+rax]
00007FF6E4B39C9E call qword ptr [__imp_set_pglocale_pgservice (07FF6E4B40520h)]
内存在 07FF6E4B40520h
0x00007FF6E4B40520 00000001403e1da0 .>@....
0x00007FF6E4B40528 0000000000000000 ........
0x00007FF6E4B40530 0000000000000000 ........
0x00007FF6E4B40538 00007ff6e4b35348 HS.äö...
(注意:从 0x7FF6E4B40000 到 0x00007FF6E4B40560 内存包含函数地址,映射文件说:0002:00000520 __imp_set_pglocale_pgservice postgres:postgres.exe [postgres 可再分发,动态链接])
然后调用qword ptr后[__imp_set_pglocale_pgservice(07FF6E4B40520h)]
00000001403E1DA0 mov qword ptr [rsp+18h],rbx
00000001403E1DA5 push rdi
00000001403E1DA6 sub rsp,0C40h
00000001403E1DAD mov rax,qword ptr [1405F8C60h]
00000001403E1DB4 xor rax,rsp
00000001403E1DB7 mov qword ptr [rsp+0C30h],rax
00000001403E1DBF mov rbx,rdx
00000001403E1DC2 mov rdi,rcx
00000001403E1DC5 lea rdx,[140430540h]
00000001403E1DCC mov rcx,rbx
00000001403E1DCF call 00000001403F67FA
然后调用00000001403F67FA后
00000001403F67FA jmp qword ptr [1403F8998h]
1403F8998h 处的内存
0x00000001403F8998 00007ffe87a5cc60 `Ì¥.þ...
0x00000001403F89A0 00007ffe87a47060 `p¤.þ...
0x00000001403F89A8 00007ffe87a5f8a4 ¤ø¥.þ...
(注意:从 0x00000001403F8000 到 0x00000001403F8F08 内存包含函数地址,映射文件说:0002:00000998 ??_C@_04FHBLDJDJ@?1bin?$AA@ libpgport:path.obj [postgres 可再分发,是静态链接])
然后跳转到00007ffe87a5cc60后
00007FFE87A5CC60 sub rdx,rcx
00007FFE87A5CC63 test cl,7
00007FFE87A5CC66 je 00007FFE87A5CC7C
... 一切正常
windows10 的组装细节(不是工作案例):
main 之后的几行,应用程序调用函数 set_pglocale_pgservice
set_pglocale_pgservice(argv[0], "pgscripts");
00007FF7E9879C85 mov eax,8
00007FF7E9879C8A imul rax,rax,0
00007FF7E9879C8E lea rdx,[default_options+120h (07FF7E9883B10h)]
00007FF7E9879C95 mov rcx,qword ptr [argv]
00007FF7E9879C9A mov rcx,qword ptr [rcx+rax]
00007FF7E9879C9E call qword ptr [__imp_set_pglocale_pgservice (07FF7E9880520h)]
内存在 07FF7E9880520h
0x00007FF7E9880520 00000001403e1da0 .>@....
0x00007FF7E9880528 0000000000000000 ........
0x00007FF7E9880530 0000000000000000 ........
0x00007FF7E9880538 00007ff7e9875348 HS.é÷...
(注意:从 0x00007FF7E9880000 到 0x00007FF7E9880560 内存包含函数地址,映射文件说:0002:00000520 __imp_set_pglocale_pgservice postgres:postgres.exe [postgres 可再分发,动态链接])
然后调用qword ptr后 [__imp_set_pglocale_pgservice (07FF7E9880520h)]
00000001403E1DA0 mov qword ptr [rsp+18h],rbx
00000001403E1DA5 push rdi
00000001403E1DA6 sub rsp,0C40h
00000001403E1DAD mov rax,qword ptr [1405F8C60h]
00000001403E1DB4 xor rax,rsp
00000001403E1DB7 mov qword ptr [rsp+0C30h],rax
00000001403E1DBF mov rbx,rdx
00000001403E1DC2 mov rdi,rcx
00000001403E1DC5 lea rdx,[140430540h]
00000001403E1DCC mov rcx,rbx
00000001403E1DCF call 00000001403F67FA
然后调用00000001403F67FA后
00000001403F67FA jmp qword ptr [1403F8998h] (should call C@_04FHBLDJDJ@?1bin?$AA@ libpgport:path.obj [postgres redistributable, which is linked statically]))
Memory at 1403F8998h (这里的应用程序不同于windows 7)
0x00000001403F8998 000000000059e6a2 ¢æY.....
0x00000001403F89A0 000000000059e6ac ¾Y.....
0x00000001403F89A8 000000000059e6b6 ¶æY.....
(注意:0x00000001403F8998是函数中间的操作码地址,不是函数地址)
00000001403F8998 mov byte ptr [AC000000000059E6h],al
00000001403F89A1 out 59h,al
00000001403F89A3 add byte ptr [rax],al
...
内存在 000000000059e6a2h
000000000059E69F ?? ??
000000000059E6A0 ?? ??
000000000059E6A1 ?? ??
然后跳转到000000000059e6a2之后 =>崩溃
关于 windows 7 的进程监视器详细信息,用于加载库(此处 libpq.dll):
[...]
"16:48:40,2946466","pg_repack.exe","7216","Load Image","C:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Image Base: 0x180000000, Image Size: 0x30000"
[...]
关于 windows 10 的进程监视器详细信息(这里是 libpq.dll)(除了加载库外,其他都与 windows 7 非常相似)
[...]
"11:52:20,6264717","pg_repack.exe","12464","QueryOpen","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","CreationTime: 21/08/2017 11:38:04, LastAccessTime: 21/08/2017 12:06:56, LastWriteTime: 09/05/2017 06:45:07, ChangeTime: 21/08/2017 18:04:09, AllocationSize: 184 320, EndOfFile: 183 296, FileAttributes: A"
"11:52:20,6265789","pg_repack.exe","12464","CreateFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Desired Access: Read Data/List Directory, Execute/Traverse, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened"
"11:52:20,6266332","pg_repack.exe","12464","QuerySecurityFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Information: 0x20"
"11:52:20,6266513","pg_repack.exe","12464","CreateFileMapping","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","FILE LOCKED WITH ONLY READERS","SyncType: SyncTypeCreateSection, PageProtection: PAGE_EXECUTE"
"11:52:20,6266921","pg_repack.exe","12464","CreateFileMapping","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","SyncType: SyncTypeOther"
"11:52:20,6267619","pg_repack.exe","12464","Load Image","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Image Base: 0x180000000, Image Size: 0x30000"
"11:52:20,6274889","pg_repack.exe","12464","CreateFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened"
"11:52:20,6275293","pg_repack.exe","12464","QuerySecurityFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Information: 0x20"
"11:52:20,6275471","pg_repack.exe","12464","QueryBasicInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","CreationTime: 21/08/2017 11:38:04, LastAccessTime: 21/08/2017 12:06:56, LastWriteTime: 09/05/2017 06:45:07, ChangeTime: 21/08/2017 18:04:09, FileAttributes: A"
"11:52:20,6276255","pg_repack.exe","12464","CloseFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS",""
"11:52:20,6291170","pg_repack.exe","12464","CloseFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS",""
[...]
"11:52:20,6539022","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF"
"11:52:20,6539202","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF"
"11:52:20,6539363","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF"
"11:52:20,6539512","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF"
"11:52:20,6539664","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Name: \testF"
"11:52:20,6603867","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll"
"11:52:20,6604319","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll"
"11:52:20,6604778","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll"
"11:52:20,6605211","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll"
"11:52:20,6605635","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","SUCCESS","Name: \testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll"
[...]
注意:我期待类似于 windows 7 或至少类似的东西:
"11:52:20,6539022","pg_repack.exe","12464","QueryNameInformationFile","B:\testFolder\pg_repack-master\msvc\bin\x64\Debug\libpq.dll","BUFFER OVERFLOW","Length: 63".
所以我不知道为什么这个应用程序在 windows 8 或 10 上有如此奇怪的行为。如果有人能提供一些解释或想法来修复崩溃,我将非常高兴。如果需要,请不要犹豫,询问一些细节。
我查看了你的二进制包,发现你执行了 pg_repack.exe
,它是从 postgres.exe
静态导入的。问题的根源 - 是从 exe 文件导入。更确切地说,来自 PE 文件,该文件没有在 IMAGE_FILE_HEADER
.Characteristics
中标记 IMAGE_FILE_DLL
,因为正式扩展名 ( exe、dll等不起作用)。简而言之,我将在 exe 下表示 PE 文件没有 IMAGE_FILE_DLL
Characteristics
,但不是正式的文件扩展名
第一次加载 exe 因为 dll 不正确 - 当 exe 以这种方式加载时 -它没有调用入口点。并且不能被调用,因为它没有被设计为回调,接收DLL_PROCESS_*
通知,最后调用ExitProcess
。当模块的入口点没有被调用时——通常它没有被初始化。假设你从 exe 调用了一些导出函数,但是如果这个导出函数使用了一些通常在 exe 入口点初始化的数据怎么办?所以结论 - 我们只能从 exe 加载的 dll 调用导出函数 exe 进程。并且在每个进程中必须只有一个 exe(作为可执行代码)。
在第二个特定的 postgres.exe
没有重定位(IMAGE_FILE_HEADER.Characteristics
中的 IMAGE_FILE_RELOCS_STRIPPED
标志)- 结果这个 PE 只能在硬编码地址。这对 exe 来说不是问题,它总是首先映射到进程,而几乎所有地址 space 都是空闲的。但是当 PE 加载为 DLL 时,这通常是个问题 - 不是第一个进程 - 硬编码图像库可能已经很忙。所以结论 - 你不能安全地使用任何 exe 没有重定位的 DLL
但是 windows10 上的崩溃根源 - 因为 windows10 无法解析 PE ("exe") 如果这个 pe 有导入没有标志 IMAGE_FILE_DLL
。换句话说,它像 LoadLibraryEx
with flag DONT_RESOLVE_DLL_REFERENCES
- does not load additional executable modules that are referenced by the specified module and nor resolve imports. as result this PE not initialized and will crash at first import function call (in your case this is strcmp
一样处理这个 PE。
这只发生在 win10 上。在 win 8.1(内部版本 9600)和 win 7 上导入 exe 文件(加载为 dll)已解决。 (你说在你的 win 8.1 上它崩溃了 - 可能你使用了更多的新版本或一些更新?或者更好地检查)
从测试 exe MatchToken
函数调用此行为的最简单测试,该函数从 Netsh.exe
导出。代码可以是下一个:
#include <Netsh.h>
#pragma comment(linker, "/defaultlib:Netsh.lib")
MatchToken(L"*", L"*");// crash here on win 10
在 win10 上崩溃,因为 MatchToken
内部尝试从 msvcrt.dll
调用 _wcsnicmp
,但在 win10 中此导入未解决。但在 win8.1、win7、win xp 上 - 此代码运行良好。
稍微复杂一点的例子:
if (HMODULE hmod = LoadLibraryW(L"wshelper.dll"))
{
DWORD (WINAPI * InitHelperDll)(_In_ DWORD dwNetshVersion, PVOID pReserved);
if (*(void**)&InitHelperDll = GetProcAddress(hmod, "InitHelperDll"))
{
InitHelperDll(1, 0);// crash here on win10 only
}
FreeLibrary(hmod);
}
这里我们加载标准 windows NetShell helper dll - "wshelper.dll" 并调用 InitHelperDll
callback function. internally InitHelperDll
call the RegisterHelper
function from Netsh.exe. but again, because Netsh.exe not initialized (import not resolved) when it loades as DLL in win 10 - it crashed inside RegisterHelper