galgame求助吧 关注:985贴子:11,600

“应用程序无法正常启动”问题排查记录

只看楼主收藏回复

前情提要:有没有大佬知道这是什么情况
这种一看就很难办,需要具体问题具体分析
本文也只是做个参考,并不代表所有此类问题均可用该方法解决。
其实主要还是靠经验解决的,更详细具体的原因不知道(


IP属地:山东来自Android客户端1楼2025-05-30 22:44回复
    丸山纯梅、酒酒_1999、ganatpnl67. . . 被楼主禁言,将不能再进行回复
    二楼自占,原始文档同样上传于此处Galgame运行学——基于Win的G... 二楼链接


    IP属地:山东来自Android客户端2楼2025-05-30 22:46
    回复
      2025-07-29 21:26:31
      广告
      不感兴趣
      开通SVIP免广告
      前言
      本文主要适用知识共享-署名-非商业性使用-相同方式共享 4.0 授权协议(CC BY-NC-SA)
      对于本文的使用需遵守上述协议
      因笔者能力有限,文中可能存在诸多纰漏,欢迎大佬们批评指正。


      IP属地:山东3楼2025-05-30 23:23
      收起回复
        问题描述
        求助者为Windows 11 24H2系统,在远程协助中发现是从23H2升级上来的。
        汉化程序运行后报错“应用程序无法正常启动(0xc0000005)”,实际还有0xc000007b的报错。0x开头代表为十六进制数值。

        使用DIE进行分析(这里只截取了其中一个程序的),提示【打包工具:Sections like Enigma】,因为Enigma Protector也是这提示,所以实际使用EnigmaVBUnpacker尝试解包并成功,确定为Enigma Virtual Box打包。
        先尝试按常规方法寻找程序崩溃时产生的内存转储文件(DUMP,扩展名为.dmp),位置默认在
        C:\用户\你的用户名\AppData\Local\CrashDumps
        用户名根据自己的实际情况修改。或者Win+R调出运行窗口,输入
        %localappdata%\CrashDumps
        后按下回车键(Enter),便可打开对应位置:

        因为笔者修改了默认的位置,所以下图地址栏中的路径仅供参考:

        不过求助者电脑的对应位置并没有游戏名字的dmp(其实这里默认生成的是最小的内存转储,存储的信息比较少)
        虽然多了笔者也不一定能看出来啥)
        所以先继续尝试常规方法。实际上从Windows 11的23H2 (22621.1992) 版本开始,系统的任务管理器自带了生成实时内存转储的功能,
        不过当时笔者忘了(此处手动删除线
        但有可能会失败,所以后面还是打算远程看一下。
        因为有molebox打包的通过关闭VBS(基于虚拟化的安全)和内存完整性解决的案例,故先尝试这些方法,并未成功(成功了就没这篇文章了)。
        然后尝试更改为全英文路径、安装常用运行库(DirectX和Visual C++)等常规方法,自然也没有成功。
        后面就是通过远程控制进行更深入的分析了。
        通过任务管理器创建内存转储文件:



        IP属地:山东4楼2025-05-30 23:30
        回复
          故障排除
          为保护求助者的隐私,以下均为当时的情况复现(还好能复现)
          使用传统搜索引擎和AI
          首先是确认问题是否依旧存在:

          可以看到依旧报错0xc0000005。实际上也可以通过搜索引擎来查找可能的解决方案,这里使用必应:
          (实际上笔者当时根本就没搜)

          前面这是AI总结,经过笔者后续考证,这里所述的“尝试访问不可访问的内存位置”确实有其依据,这里先不揭晓答案。

          后面也有一些方法,根据后续的情况来看,也是无效的。
          另一个程序还有0xc000007b的报错,搜索结果如下:

          其中一篇文章:

          当然也没啥用,不过这个报错的含义倒是很接近问题的根本答案了,虽然笔者当时不知道是什么意思(
          以下是DeepSeek的回答(受限于篇幅,只截取部分),也还是差点意思:
          Prompt: Windows应用程序无法正常启动0xc0000005该如何解决或分析?



          后面就是通过远程控制工具实际操作进行分析了。
          当时只分析了smee社Making Lovers的汉化程序,因为笔者认为应该是通病,结果也确实如此。


          IP属地:山东5楼2025-05-30 23:39
          回复
            通过WinDbg进行分析
            WinDbg是微软公司发布的 Windows 操作系统多用途调试工具,可用于分析故障转储、调试实时用户模式和内核模式代码(程序),以及检查 CPU 寄存器和内存。
            笔者主要用它来调试实时运行的用户程序,并创建程序故障时的内存转储,以供进一步的分析。
            首先是下载和安装,在微软应用商店(Microsoft Store)就可以找到:

            点【获取】,等它显示为【打开】,点击就可以。

            然后就会打开如上的窗口,大多数人应该都看不懂,实际上笔者也只是姑且会一点(
            这里点击左上方的【文件】,会打开如下的窗口:

            然后点击【Launch executable】,也就是启动可执行文件,即通常所说的exe文件,打开如下的窗口:

            选择目标程序,这里为MakingLoversGBK.exe,选中后点击打开按钮:

            启动时,下方的蓝色条中会显示加载一些内容,这是在联网下载所需的文件,务必确保网络畅通。不再加载后就会显示如上的界面。
            可以看到,有
            (23ec.10c): Access violation - code c0000005 (first chance)
            First chance exceptions are reported before any exception handling.
            This exception may be expected and handled.
            eax=00010000 ebx=0000014a ecx=0000014c edx=00227ffe esi=00000000 edi=00010128
            eip=776e6881 esp=007ff9f4 ebp=007ffa14 iopl=0 nv up ei pl nz na po nc
            cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
            ntdll!LdrRelocateImageWithBias+0x98:
            776e6881 8b4a04 mov ecx,dword ptr [edx+4] ds:002b:00228002=????????
            的输出,其中Access violation - code c0000005 (first chance)便是提示访问违规,错误代码(code)为c0000005,与之前的窗口提示的一致。
            下面两行英文的意思是,这个异常(exception)可以被处理(handled),实际上有些错误挂上调试器后确实可以被跳过,虽然我不知道原因是啥()总之笔者试过了,这里是没法跳过的,还是得继续看。
            再下面有等号的那三行是程序当时在寄存器中存储的值。看不懂没关系,反正也是进一步分析的时候才会用到(
            最后的ntdll!LdrRelocateImageWithBias+0x98:便是出错时所执行的函数(方法),是ntdll模块的LdrRelocateImageWithBias函数,偏移量为0x98。此偏移量处的反汇编代码为mov ecx,dword ptr [edx+4] ds:002b:00228002=,笔者认为,单看这行代码也看不出什么,还是需要先看这个函数具体是干什么的。从名字来看,它应该是根据(With)基址偏移(Bias)来加载(Loader)并重定位(Relocate)映像(Image)。
            笔者原本想找下官方文档的解释,但好像没有,于是就去请教了一下D指导:


            IP属地:山东6楼2025-05-30 23:50
            回复
              又有大作了


              IP属地:山西来自Android客户端7楼2025-05-31 00:13
              收起回复
                可以看到,这个函数确实是用来处理PE文件的基址重定位的。到这里读者可能要问了(或许早就该问了),什么是PE文件?这里引用韩国的逆向工程师李承远所著《逆向工程核心原理》一书中的解释:

                可执行文件(exe)就是一种PE文件,dll库文件也是。那基址重定位又是指什么呢?首先需要知道映像(Image)的概念:

                一般来说,PE文件都需要从本地硬盘加载到内存中才能运行,加载到内存中的部分就被称为映像(Image)。
                最后就是重定位的概念了,这个就比较难解释了,姑且也引用一部分:

                笔者也尝试解释一下,每个程序在被执行时都会分配独立的虚拟内存空间,在这个内存空间里,程序(exe)本身,默认是以0x00400000作为基址进行加载,dll则是0x10000000。
                如果要进行重定位的话,需要用到被称为ASLR(Address Space Layout Randomization,地址空间布局随机化)的技术,这是微软从NT6.0内核(对应Windows Vista系统)开始加入的一项技术。在之前版本的系统中没有该技术,也就不会生效。

                并且还需要程序在编译时启用了/DYNAMICBASE选项,编译出的程序才会使用此技术,如下图所示(这里使用VisualStudio 2022进行示范):

                还有固定基址和数据执行保护(DEP,在某些疑难杂症的解决方法中经常被提及)的选项,这里就不赘述了。
                总之,我们知道了,或许要从【基址重定位】的具体执行过程中,也就是
                LdrRelocateImageWithBias
                函数执行时发生了什么来分析,那怎么分析呢?其实笔者也不知道(
                不过笔者在之前翻找Windows 11的系统设置中,发现在Windows 安全中心(原Windows Defender)的【应用和浏览器控制】→【攻击防护】中有:

                细心的读者应该就发现了,这里不就有个前文中提到的ASLR选项吗?对比笔者自己的之后可知,原来应该是【使用默认值(关闭)】,这里成了默认打开。关掉之后会显示要重启才能生效,重启电脑之后,游戏就可以正常打开了。

                实际上,笔者当时还发现【控制流保护(CFG)】选项是关着的,应该是开启的,就顺手改回去了,不知道会不会有影响。
                这里还有DEP的选项(控制面板里有一个),右边还有【程序设置】,可以为对应的程序特定选项,在一些情况下或有奇效。
                总之,这两个报错都随着【强制映像随机化(强制ASLR)】选项的关闭而解决了,可喜可贺(


                IP属地:山东8楼2025-05-31 00:26
                回复
                  2025-07-29 21:20:31
                  广告
                  不感兴趣
                  开通SVIP免广告
                  后记
                  内存转储获取与分析
                  其实笔者当时是先进行的内存转储,然后把文件传到自己的电脑上查看的,方法如下:

                  在箭头所指的红框处输入 .dump /ma D:\crash.dmp 后按下回车键,内存转储文件就会保存为D盘的crash.dmp。
                  关于该命令,可参考微软官方说明:.dump(创建转储文件)|Microsoft Learn
                  摘取部分如下:
                  .dump 命令创建用户模式或内核模式故障转储文件。
                  /m[MiniOptions]
                  创建小型内存转储(在内核模式)或小型转储(在用户模式下)有关详细信息,请参阅用户模式转储文件。 如果 /f 或 /m 均未指定,则默认为/m。
                  在用户模式下,/m 后可跟其他 MiniOptions,指定要包含在转储中的额外数据。 如果未包含 MiniOptions,转储将包括模块、线程和堆栈信息,但不包含额外数据。可以添加以下任一MiniOptions 来更改转储文件的内容;它们区分大小写。
                  MiniOption 效果
                  a 创建包含所有可选添加的小型转储。 /ma 选项等同于/mfFhut,它会在小型转储中添加完整内存数据、处理数据、未加载模块信息、基本内存信息和线程时间信息。任何读取内存的失败都会导致小型转储生成终止。
                  A mA 选项等同于 /ma,但它会忽略读取不可访问内存的任何失败,并继续生成小型转储。
                  f 将完整内存数据添加到小型转储。目标应用程序拥有的所有可访问提交页面都将包括在内。
                  然后将保存的文件通过远程控制软件的文件传输功能发送到本机。如果文件体积较大,可以先使用压缩软件进行压缩,实际上也建议先压缩一下。

                  本机安装有WinDbg的话,就可以直接双击打开了。会出现如下的窗口:

                  可以看到很多信息:
                  Loading Dump File [Z:\dump\crash.dmp]
                  User Mini Dump File with Full Memory: Only application data is available
                  这是说明加载的是【只包含有对应程序所有内存空间的小型转储文件】,听起来很别扭,实际上微软自己也是这么觉得:

                  总之,此时的转储文件信息就算是比较全面了,虽然笔者没法完全利用起来(
                  后面就是程序运行环境的信息:
                  Executable search path is:
                  Windows 10 Version 26100 MP (4 procs) Free x86 compatible
                  Product: WinNt, suite: SingleUserTS Personal
                  Edition build lab: 26100.1.amd64fre.ge_release.240331-1435
                  Debug session time: Fri May 30 18:45:15.000 2025 (UTC + 8:00)
                  System Uptime: 0 days 2:03:38.354
                  Process Uptime: 0 days 0:44:24.000
                  这里显示为Windows 10,通过具体的26100版本号可知,实际为Windows 11 24H2版本。还有产品(Product),内部版本号(Edition build lab),调试器启动的时间(Debug session time,UTC + 8:00即为中国北京时区),系统运行时长(System Uptime)和进程运行时长(Process Uptime)。
                  图里还有两个可以点击的选项,分别是!analyze -v和.ecxr。
                  官方解释如下:
                  !analyze命令显示有关当前异常或错误检查的信息。-v[0..99]显示详细输出。可以通过指定一个介于 0 到 99 的数字来显示更多信息。如果未指定数字,则默认值为 1。还可以指定“非常详细”(-vv) 以显示所有可用信息。对于用户模式,-v6 显示全局和每个线程上已发现的内容。—————————
                  在用户模式下,!analyze 显示有关当前异常的信息。在内核模式下,!analyze 显示有关最新错误检查的信息。如果发生错误检查,则会自动生成 !analyze 显示。可以使用!analyze -v 显示其他信息。如果只想查看基本错误检查参数,可以使用 .bugcheck(显示错误检查数据)命令。
                  —————————————————————————————
                  .ecxr命令查找当前异常的上下文信息,并显示指定上下文记录的重要寄存器。此命令还指示调试器使用与当前异常关联的上下文记录作为寄存器上下文。运行 .ecxr 后,调试器可以访问此线程最重要的寄存器和堆栈跟踪。此寄存器上下文一直存在,直到你允许目标执行、更改当前进程或线程,或使用另一个寄存器上下文命令 (.cxr 或 .ecxr) 。有关注册上下文的详细信息,请参阅注册上下文。.excr 命令是同义词命令,具有相同的功能。
                  总之,可以都点一下,然后把结果CTRL+A全选,CTRL+C复制后|扔给DeepSeek等大语言模型(LLM)(手动删除线
                  Prompt: 请分析以下windbg分析dump结果,并给出进一步操作的建议:

                  可以看出,DeepSeek也指出了ASLR的兼容性问题,不过怎么找到问题所在就是另一回事了,也不知道微软什么时候搞出来的这个【攻击防护】功能(


                  IP属地:山东9楼2025-05-31 00:36
                  回复
                    探究具体原因的尝试
                    其实笔者作出上述判断的基础是该程序并未启用ASLR功能,不过后续通过PE文件信息查看软件发现:


                    可以看到,【文件基址】一栏,无论是打包后的汉化程序,还是游戏原程序,均为启用【动态基址】的状态,这下尴尬了(
                    过笔者在搜索LdrRelocateImageWithBias函数时,发现了一篇文章:
                    好吧,作者禁止转载,这里就只放链接吧。总之,这位大佬是在手动脱壳的时候遇到了问题,是把重定位表的IMAGE_BASE_RELOCATION标志填充为八个字节的0后,运行程序提示0xC0000005错误,正好为本文分析的报错之一。考虑到保护器(壳)和打包器的工作原理有相似之处,或许为打包器自己解包时受到强制重定位的干扰,读取到了非法地址。——不过这都是笔者瞎猜的
                    关于报错的具体含义,笔者也找到了微软官方的参考手册:[MS-ERREF]

                    红框标识处可以下载单独的该本手册(PDF或DOCX格式),或者点击蓝框的链接下载全部的Windows Protocols。
                    总之,查询该手册:


                    0xC0000005错误是内存访问冲突,0xC000007B是映像格式无效,是比较符合实际情况的。不过含义都太广泛了,还是需要进一步的分析。
                    总之,因为笔者的能力有限,就只能做到这里了。如果有大佬愿意进一步分析,笔者不盛感激。


                    IP属地:山东10楼2025-05-31 00:41
                    回复
                      大佬,太强了


                      IP属地:广东来自Android客户端11楼2025-05-31 09:45
                      收起回复
                        奇怪的是寄宿之恋我在去年7月就推完了,后来突然报0xc000007b,明明我都没有动过ASLR


                        IP属地:广东来自Android客户端12楼2025-05-31 10:58
                        收起回复



                          IP属地:山东来自Android客户端13楼2025-05-31 12:12
                          回复
                            后排支持一下


                            IP属地:江苏来自Android客户端14楼2025-05-31 12:31
                            收起回复
                              2025-07-29 21:14:31
                              广告
                              不感兴趣
                              开通SVIP免广告
                              爱你


                              IP属地:上海来自Android客户端15楼2025-05-31 16:43
                              回复