在 Windows 8/10 上调用静态链接函数每次都会崩溃,但在 Windows 7 上则不然

2024-04-20

问题 :

我已经建立了https://github.com/reorg/pg_repack 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 应用程序,优化已禁用,它使用动态底座。 为了确保我使用正确的二进制文件,我已将所有可再发行的二进制文件复制到我的应用程序的文件夹中。

Windows 7 上的组装详细信息(工作案例):

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 内存包含函数地址,mapfile 说: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 内存包含函数地址,mapfile 说:0002:00000998 ??_C@_04FHBLDJDJ@?1bin?$AA@ libpgport:path.obj [postgres 可再发行,静态链接])

然后跳转到00007ffe87a5cc60之后

00007FFE87A5CC60  sub         rdx,rcx  
00007FFE87A5CC63  test        cl,7  
00007FFE87A5CC66  je          00007FFE87A5CC7C 

... 一切正常

Windows 10 上的程序集详细信息(不工作的情况):

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 内存包含函数地址,mapfile 说: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]))

内存位于 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_DLL in IMAGE_FILE_HEADER https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313(v=vs.85).aspx.Characteristics,因为正式扩展(exe, dll等不起作用)。简而言之,我将在下一篇中exe mean PE文件没有IMAGE_FILE_DLL in Characteristics,但不是正式的文件扩展名

第一次加载时exe as dll不正确 - 当exe以这种方式加载 - 未调用它的入口点。并且不能被调用,因为它没有被设计为回调,接收DLL_PROCESS_*通知并致电ExitProcess在最后。当模块的入口点未被调用时 - 通常它不会被初始化。假设您调用一些导出函数exe,但是如果这个导出函数使用一些通常在以下位置初始化的数据怎么办?exe入口点 ?所以结论 - 我们可以调用导出函数exe仅从dll加载到这个exe过程。并且在每个过程中必须只有一个exe(作为可执行代码)。

在第二个具体postgres.exe没有搬迁的(IMAGE_FILE_RELOCS_STRIPPED标记在IMAGE_FILE_HEADER.Characteristics) - 结果是这样PE只能在硬编码地址加载。这不是问题exe,当几乎所有地址空间都是空闲时,它总是首先映射到进程。但这通常是一个问题PE加载为DLL- 不是第一个进程 - 硬编码图像库可能已经很忙。所以结论-你不能安全地使用任何exe没有搬迁的情况下DLL

然而 Windows 10 上崩溃的根源 - 因为 Windows 10 无法解决PE("exe") 如果此 PE 没有标志则导入IMAGE_FILE_DLL。换句话说,它处理这个PE like LoadLibraryEx https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx有旗帜DONT_RESOLVE_DLL_REFERENCES- 不加载指定模块引用的其他可执行模块,也不解析导入。结果这个PE未初始化,并且会在第一次导入函数调用时崩溃(在您的情况下,这是strcmp https://doxygen.postgresql.org/common_2exec_8c_source.html#l00559).

而且这种情况只发生在win10上。在 win 8.1 (build 9600) 和 win 7 上导入exe文件(加载为dll) 解决。 (你说你的 win 8.1 上崩溃了 - 可能是你使用了更多新版本或一些更新?或更好地检查)

此行为的最简单测试来自测试调用exe MatchToken https://msdn.microsoft.com/en-us/library/windows/desktop/ms708331(v=vs.85).aspx,函数,导出自Netsh.exe。代码可以是下一个:

#include <Netsh.h>
#pragma comment(linker, "/defaultlib:Netsh.lib")

MatchToken(L"*", L"*");// crash here on win 10

win10崩溃是因为MatchToken https://msdn.microsoft.com/en-us/library/windows/desktop/ms708331(v=vs.85).aspx内部尝试调用_wcsnicmp from msvcrt.dll,但是在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 https://msdn.microsoft.com/en-us/library/windows/desktop/ms708327(v=vs.85).aspx回调函数。内部InitHelperDll https://msdn.microsoft.com/en-us/library/windows/desktop/ms708327(v=vs.85).aspx打电话给RegisterHelper https://msdn.microsoft.com/en-us/library/windows/desktop/ms708465(v=vs.85).aspx#函数来自网络工具。但话又说回来,因为网络工具当它在 win 10 中作为 DLL 加载时未初始化(导入未解析) - 它在内部崩溃RegisterHelper https://msdn.microsoft.com/en-us/library/windows/desktop/ms708465(v=vs.85).aspx#

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Windows 8/10 上调用静态链接函数每次都会崩溃,但在 Windows 7 上则不然 的相关文章

  • 如何防止用户杀死C#应用程序[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果您使用 ESET Smart S
  • 转储 $mft 文件的内容

    对于一些商业的我正在做的项目我需要能够读取 mft 文件中存储的实际数据 我找到了一个gpl lib http www codeproject com KB files NTFSParseLib aspx artkw ntfs这可能会有所帮
  • 无法在 XAMPP 和 Windows XP 上安装 Xdebug

    我知道 这个问题已经被问过好几次了 但答案并没有解决我的问题 我在 Windows XP SP3 上运行 XAMPP 1 8 2 并且在安装 XDebug 时遇到困难 我从网站下载了XDebug 不幸的是 安装向导对我不起作用 我的 PHP
  • 在 Mercurial 中配置 eol 扩展时出现问题

    我正在尝试将 UNIX 托管的 Mercurial 存储库克隆到 Windows 计算机 我希望使用eol扩展名 以便我在服务器上以 LF 结尾的文本文件在克隆到 Windows 计算机时具有 CRLF 以前我用过win32文本扩展效果很好
  • 窗口的打开事件和窗口句柄

    如何从刚刚打开的 Outlook 窗口获取窗口句柄 IntPtr OutLook Items items oFolder Items foreach OutLook MailItem mail in items mail Display I
  • Ruby on Rails 安装问题 (Windows)

    我从 RuyInstaller 安装了 Ruby 2 0 0 和 DevKit 创建新项目时出现错误消息 rails new testtest d mysql a lot of output here Installing mysql2 0
  • 尝试从 Polar H10 获取心率变异性 [蓝牙低功耗示例 UWP]

    我正在与 Polar H10 合作 从中获取心率变异性 我在跑步蓝牙低功耗示例 https github com Microsoft Windows universal samples tree master Samples Bluetoo
  • 我需要为我的应用程序制作和加载多大尺寸的 ImageList 图标(考虑更高的 DPI)?

    我有一个CListCtrl http msdn microsoft com en us library hfshke78 aspx控制 或ListView http msdn microsoft com en us library wind
  • 编写 AMD64 SysV 程序集时使用哪些寄存器作为临时寄存器?

    我正在使用实现一个功能cpuid根据 AMD64 SysV ABI 进行组装 我需要在函数本身中使用 2 个临时寄存器 第一个用于累积返回值 第二个用作计数器 我的功能目前如下所示 zero argument function some c
  • Windows 服务和 Windows 进程有什么区别?

    是什么不同之处窗户之间service和一个窗户process 服务是真正的 Windows 进程 没有区别 服务的唯一特殊之处在于它由操作系统启动并在单独的会话中运行 一种独立的方式 可防止其干扰桌面会话 传统上命名为daemon http
  • Windows Unicode C++ 流输出失败

    我目前正在编写一个应用程序 它要求我在任意窗口上调用 GetWindowText 并将该数据存储到文件中以供以后处理 长话短说 我注意到我的工具在 战地 3 上失败了 我将问题范围缩小到窗口标题中的以下字符 http www filefor
  • 使用 php 运行 ipconfig 命令

    我使用这段代码来了解访问者 客户 的一些信息 它一直在我的 Xampp 虚拟服务器上运行 但我无法在我的主服务器 主机 上运行 我只看到一个空白页 info system ipconfig all echo info 这可能对你有帮助 服务
  • 在 Windows 上使用 Python 打开设备句柄

    我正在尝试使用 Giveio sys 驱动程序 该驱动程序需要先打开一个 文件 然后才能访问受保护的内存 我正在查看 WinAVR AVRdude 中的 C 示例 它使用以下语法 define DRIVERNAME giveio HANDL
  • 每次加载解决方案时,所有项目引用都有黄色三角形

    我的所有项目 来自同一解决方案 引用都标有黄色三角形 这些项目都设置为相同的 NET 版本 4 5 1 错误日志说 无法引用项目 CommonLibrary 暂时解决该问题的方法是 删除并重新添加引用 右键单击并选择 添加服务引用 并立即取
  • x86-64 上这个语句有什么问题?

    该函数的目的是获取堆栈的起始地址 unsigned long find start void asm movq rsp eax 当我编译它时 出现错误 Error suffix or operands invalid for movq mo
  • Shell 执行将窗口置于前面

    我正在使用此函数从我的 MSI 调用可执行文件 然而 可执行文件的窗口隐藏在我的 MSI 窗口后面 有什么办法可以把它带到前面吗 我尝试在调用之前最小化所有窗口ShellExecute但这仍然没有将可执行窗口带到前面 extern C UI
  • AVX512 掩码寄存器(k1...k7)的 GNU C 内联 asm 输入约束?

    AVX512 为其算术命令引入了 opmask 功能 一个简单的例子 上帝螺栓 org https godbolt org z P7xWD8 include
  • 无法加载 php_curl

    我已经在WindowsXp上安装了php5 2 13 apache2 2 15 将C php添加到PATH ssystem变量中 我无法启用卷曲扩展 我配置了extension dir并删除了 在 php ini 中形成 php curl
  • 如何让c代码执行hex机器代码?

    我想要一个简单的 C 方法能够在 Linux 64 位机器上运行十六进制字节码 这是我的 C 程序 char code x48 x31 xc0 include
  • 带有 Angular2 和 Typescript 的 Visual Studio 2013

    我在用着angular2 快速入门 https angular io docs ts latest quickstart html我遇到了 Visual Studio 无法识别的问题Angular2 with 打字稿导入模块 其余一切都很好

随机推荐