Windows 为什么进程在不同阶段加载模块(DLL)?

Windows 为什么进程在不同阶段加载模块(DLL)?,windows,dll,process,code-injection,Windows,Dll,Process,Code Injection,这种现象是这样的 我正在尝试实现dll注入。我的应用程序在“挂起”状态下创建进程(使用CreateProcess和create_suspended),等待加载一个重要的dll(当然是kernel32.dll),然后执行注入。注入后,使用ResumeThread恢复挂起的进程 我使用挂起的进程创建,希望dll在除dll加载之外的任何其他执行之前被注入。但在执行这个过程中,我发现了一些有趣的东西 我只是用notepad.exe测试了这个注入,效果很好。但是,当我将可执行文件复制为notepad2.e

这种现象是这样的

我正在尝试实现dll注入。我的应用程序在“挂起”状态下创建进程(使用CreateProcess和create_suspended),等待加载一个重要的dll(当然是kernel32.dll),然后执行注入。注入后,使用ResumeThread恢复挂起的进程

我使用挂起的进程创建,希望dll在除dll加载之外的任何其他执行之前被注入。但在执行这个过程中,我发现了一些有趣的东西

我只是用notepad.exe测试了这个注入,效果很好。但是,当我将可执行文件复制为notepad2.exe时,我的注入将等待无限长的时间。直到进程的主线程恢复,Kernel32.dll才会加载

似乎存在某种预先加载模块的“已验证”可执行文件(或者可能是安装在我的计算机中的某些已使用dll注入的安全解决方案可能会导致这种不同的执行)


有人知道模块是以不同的方式加载的吗?(坦白地说,我仍然不理解windows进程的生命周期…

我想我已经找到了答案。答案是,尽管进程处于挂起状态,因此主线程停止,但当进程中的某个线程尝试访问某个模块时,就会加载所需的模块(这意味着windows应用程序似乎是“延迟加载”需要模块)

在评论中,我说我的电脑上安装的某些安全解决方案保护的进程使用迂回来注入DLL,因此在进程处于挂起状态时加载某些进程中的模块。 但这不是一个具体的迂回案例,而是每个过程中的一般性问题

我很愚蠢,我使用的注入技术是,列出目标进程中加载的所有模块,查找kernel32.dll,计算LoadLibraryW的偏移量,并使用远程线程调用该函数。在这种技术中,注入器在调用LoadLibrary函数之前枚举所有模块,因此LazyLoading从未发生,因此我无法看到进程上加载的kernel32.dll

当我使用从当前进程使用GetProcAddress、获取LoadLibrary函数的地址并远程调用该进程的简单技术时,kernel32.dll成功加载,注入成功

对于通过“使用迂回的安全解决方案”保护的几个应用程序,即使我暂停了进程,注入尝试也会发生,这就是为什么kernel32.dll加载到notepad.exe(在安全解决方案列表中),但没有加载到notepad2.exe(由于图像名称不同,它不在列表中)

我只是很愚蠢,试图使用更复杂的方法进行dll注入,这就是导致所有这些问题的原因


非常感谢您的评论。

根据我的经验,最初只映射了ntdll.dll,当线程恢复时,APC将排队运行。这将调用
ntdll!LdrpInitializeProcess
,它初始化执行环境(例如语言支持、堆、线程本地存储、
KnownDlls
目录),加载kernel32.dll并获取
BaseThreadInitThunk
的地址,进行静态dll导入,断开连接的调试器,并运行初始化例程。然后执行跳转到
ntdll!RtlUserThreadStart
,它调用
内核32!BaseThreadInitThunk
,它调用EXE的入口点,如
WinMainCRTStartup
。我见过DLL加载在进程启动过程中以看似随机的方式表现出不同的行为,即使对于同一个可执行文件也是如此。我怀疑Windows试图基于未记录的启发式方法优化进程启动,例如,每次启动特定的可执行文件时,它可能都会“记笔记”,并利用这些信息尝试在下次更快地启动它。不幸的是,底线可能是没有可靠的方法来预测在进程恢复之前或之后是否会加载kernel32.dll(或任何其他系统dll)。(但我想你可以将APC排队?@HarryJohnston,有一些服务,如预取/超取,在内存管理器级别工作,以优化系统范围内加载哪些DLL和EXE页面,以加速应用程序加载。但是我认为最初的APC队列所做的工作是从
ntdll开始的!LdriInitializeThunk
多年来一直相当稳定。我总是在以下调试会话中看到初始化步骤和DLL加载顺序:
cdb-xe cpr-c“bp ntdll!LdrInitializeThunk;g”记事本
。也就是说,
NtCreateUserProcess
有时会预映射除ntdll.dll之外的dll。我想我得到了一些提示。安装在我的计算机上的安全解决方案使用迂回来注入和钩住windows API。而且,windows迂回似乎使您能够使用CreateProcess挂起状态注入DLL。我猜当我创建进程时,经过几段时间后,Detour加载了安全解决方案dll,在此之前,加载了“kernel32.dll”。虽然我对这个假设没有信心,但我测试过的几个在主线程恢复前成功加载kernel32.dll的可执行文件都产生了DebugViewer(解决方案制造商留下了消息!)@SihuSong的迂回调试输出视图,这听起来很有道理。你为什么不把它写下来作为答案呢?