从exe入口点返回不会终止Windows 10上的进程

莫里斯·凯瑟(Maurice Kayser)

我的尝试

通过指定/GS-编译器标志和/NoDefaultLib链接器标志,并命名main函数,我使用Microsoft Visual Studio创建了一个最小的,无CRT,依赖关系耗尽的可执行文件mainCRTStartup该应用程序不会创建其他线程,并且会mainCRTStartup在<5秒后返回,但是终止该过程总共需要30秒。

问题描述

根据我的经验,如果在Windows 10上执行的应用程序仅依赖于默认情况下加载到每个Windows进程中的动态库,则命名为ntdll.dllKernelBase.dll并且kernel32.dll当主线程从该mainCRTStartup函数返回时,该进程会正常退出

如果以静态或动态方式(通过调用LoadLibraryW加载了其他库,则从main函数返回将使该进程保持活动状态:正常运行30秒,在调试器下无限期运行。

语境

在创建进程时,Windows 10进程加载器会创建其他线程以更快地加载动态库,请参阅:

Cylance在Windows 10并行加载细分中提到

工作线程空闲超时设置为30秒。在30秒以内执行的程序由于ntdll!TppWorkerThreadwaiting进程终止前的空闲超时而似乎挂起

Microsoft在终止过程中提到:终止过程

请注意,如果进程的主线程返回,则C运行时库(CRT)的某些实现将调用ExitProcess。

另一方面,Microsoft在ExitProcess

请注意,从应用程序的主要功能返回会导致对的调用ExitProcess

测试码

这是我使用过的最低限度的测试代码kernel32!CloseHandleuser32!CloseWindow作为示例,对它们的调用实际上没有执行任何操作:

#include <cstdint>

namespace windows {
    typedef const intptr_t Handle;
    typedef const void *   Module;

    constexpr Handle InvalidHandleValue = -1;

    namespace kernel32 {
        extern "C" uint32_t __stdcall CloseHandle(Handle);
        extern "C" uint32_t __stdcall FreeLibrary(Module);
        extern "C" Module   __stdcall LoadLibraryW(const wchar_t *);
    }

    namespace user32 {
        extern "C" uint32_t __stdcall CloseWindow(Handle);
    }
}

int mainCRTStartup() {
    // 0 seconds
    // windows::kernel32::CloseHandle(windows::InvalidHandleValue);

    // 30 seconds
    // windows::user32::CloseWindow(windows::InvalidHandleValue);

    // 0 seconds
    // windows::kernel32::FreeLibrary(windows::kernel32::LoadLibraryW(L"kernel32.dll"));

    // 30 seconds
    // windows::kernel32::FreeLibrary(windows::kernel32::LoadLibraryW(L"user32.dll"));

    // 0 seconds
    // windows::kernel32::FreeLibrary(windows::kernel32::LoadLibraryW(L""));

    return 0;
}

调试

mainCRTStartup函数中注释WinAPI的用法将导致上述WinAPI调用的执行时间。

这是在伪C ++的调试器跟踪的程序的执行流程

ntdll.RtlUserThreadStart() {
    kernel32.BaseThreadInitThunk() {
        const auto return_code = test.mainCRTStartup();

        ntdll.RtlExitUserThread(return_code) {
            if (ntdll.NtQueryInformationThread(CURRENT_THREAD, ThreadAmILastThread) != STATUS_SUCCESS || !AmILastThread) {
                // Bad path - for `30 seconds`.

                ntdll.LdrShutdownThread();
                ntdll.TpCheckTerminateWorker(0);
                ntdll.NtTerminateThread(0, return_code);

                // The thread execution does not return from `NtTerminateThread`, but the process still runs.
            } else {
                // Good path - for `0 seconds`.

                ntdll.RtlExitUserProcess(return_code) {
                    ntdll.EtwpShutdownPrivateLoggers();
                    ntdll.LdrpDrainWorkQueue(0);
                    ntdll.LdrpAcquireLoaderLock();
                    ntdll.RtlEnterCriticalSection(ntdll.FastPebLock);
                    ntdll.RtlLockHeap(peb.ProcessHeap);
                    ntdll.NtTerminateProcess(0, return_code);
                    ntdll.RtlUnlockProcessHeapOnProcessTerminate();
                    ntdll.RtlLeaveCriticalSection(ntdll.FastPebLock);
                    ntdll.RtlReportSilentProcessExit(CURRENT_PROCESS, return_code);
                    ntdll.LdrShutdownProcess();
                    ntdll.NtTerminateProcess(CURRENT_PROCESS, return_code);

                    // The thread execution does not return from `NtTerminateProcess` and the process is terminated.
                }
            }
        }
    }
}

预期成绩

我希望该过程如果不创建其他线程并从主函数返回,则将终止。

ExitProcess即使调用WinAPI导致在30秒之前执行,在main函数末尾的调用也会终止该过程。不一定总是可以使用此API,因为有问题的应用程序可能不是我的,而是像这样的第三方应用程序(来自Microsoft):为什么进程会在RtlExitUserProcess / LdrpDrainWorkQueue中挂起?

在我看来,即使Microsoft进程的行为也不正常,Windows 10进程加载器也已损坏。

  1. 有没有解决此问题的解决方案?
  2. 如果最后一个用户创建的线程退出,则需要哪些加载器线程?AFAIK目前无法加载任何其他库。
RbMm

我希望该过程如果不创建其他线程并从主函数返回,则将终止。

进程可以隐式创建其他线程。例如装载机。需要了解什么意思

函数返回

这里是指从标准CRTmainCRTStartup功能调用的功能。在这个mainCRTStartup电话之后ExitProcess因此,不是任何exe入口真正的入口点函数,而是从入口点调用的某些子函数。但是入口点调用ExitProcess比。

如果我们不使用CRT,则需要给ExitProcess自己打电话如果我们只是从入口点返回-将是RtlExitUserThread哪个未调用,ExitProcess除了这是进程(AmILastThread)中的最后一个线程(如果在并行调用中有2个或更多线程,在这里也可以是竞速ExitThread

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Windows 10上的64bit进程上的32bit进程上的GetModuleFileNameEx

如何在Windows 10 / IIS 10上附加到IIS进程(w3wp.exe)?

无法在 Windows 10 上运行任何虚拟化进程

Windows 10上特定进程崩溃时禁用WerFault.exe

如何查看Windows 10上的Docker Daemon VM上运行的所有进程

Windows 10 上的 Ubuntu 具有 100% CPU 使用率和“init”进程

启动太多进程时,如何加快Windows 10上的窗口切换速度?

Windows 8 / 8.1上的Modern IE10 / 11是否使用多进程体系结构?

在没有打开终端的情况下在Windows 10上运行bash后台进程

无法关闭Windows 10上的所有Google Chrome进程,并且无法运行浏览器

从本地用户在 Windows 10 上启动的进程获取域用户凭据的句柄

如何从 Windows 10 上的任务管理器导出进程选项卡?

在Windows 10上检测.NET(VB / C#)中的进程最小化状态

Windows 10上的Perfmon-没有“进程计数器”

Windows 10上除进程外还使用RAM的原因是什么?

在 Windows 10 上创建新进程,然后稍后发送命令

如何终止 SIGPIPE 上的进程?

不可阻挡的进程-Windows 10

Windows 10上的python 2.7.6线程:该进程无法访问该文件,因为该文件正在被另一个进程使用

UnobservedTaskException不会终止进程

进程在 Windows 服务器上的 SSH 注销后终止

在Windows上终止SSH会话后如何保持进程运行?

在Windows上从Go启动进程

在Windows上获取进程内存

Windows 10 1809上的任务管理器未显示正确的每进程CPU使用率

如何在Windows 10上从提升的管理员上下文启动非提升的管理员进程?

终止在端口80上运行的进程

在Windows上运行程序时“找不到入口点”

在Windows 10上,许多进程(例如git和node)的运行速度都慢了10倍,但在安全模式下却运行得很快