【发布时间】:2015-07-13 15:08:08
【问题描述】:
现象是这样的。
我正在尝试实现 dll 注入。我的应用程序创建进程处于“暂停”状态,(使用带有 CREATE_SUSPENDED 的 CreateProcess),等待加载一个重要的 dll(当然是 kernel32.dll),然后执行注入。注入后使用 ResumeThread 恢复暂停的进程。
我正在使用挂起的进程创建,希望在除 dll 加载之外的任何其他执行之前注入 dll。但在执行此操作时,我发现了一些有趣的事情。
我已经使用 notepad.exe 简单地测试了这种注入,它工作得很好。但是当我将可执行文件复制为 notepad2.exe 时,我的注入会等待无限时间。在进程的主线程恢复之前,Kernel32.dll 永远不会加载。
似乎有某种“经过身份验证”的可执行文件会预先加载模块(或者我的计算机中安装的一些已经使用 dll 注入的安全解决方案可能会导致这种不同的执行)。
有谁知道模块是否以不同的方式加载? (坦白说,我还是不明白windows进程的生命周期……)
【问题讨论】:
-
根据我的经验,最初只映射了 ntdll.dll,当线程恢复时,APC 排队运行。这会调用
ntdll!LdrpInitializeProcess,它会初始化执行环境(例如语言支持、堆、线程本地存储、KnownDlls目录),加载 kernel32.dll 并获取BaseThreadInitThunk的地址,执行静态 DLL 导入,中断对于附加的调试器,并运行 init 例程。然后执行跳转到ntdll!RtlUserThreadStart,调用kernel32!BaseThreadInitThunk,调用EXE的入口点如WinMainCRTStartup。 -
我看到 DLL 加载在进程启动期间以看似随机的方式表现不同,即使对于同一个可执行文件也是如此。我怀疑 Windows 试图基于未记录的启发式优化进程启动 - 例如,它可能在每次特定可执行文件启动时“做笔记”,并使用该信息尝试在下次更快地启动它。不幸的是,底线可能是没有可靠的方法来预测 kernel32.dll(或任何其他系统 DLL)是否会在进程恢复之前或之后加载。 (但我猜你可以排队 APC?)
-
@HarryJohnston,有一些服务,例如 prefetch/superfetch 在内存管理器级别工作,以优化系统范围内加载哪些 DLL 和 EXE 页面以加速应用程序加载。但我认为,从
ntdll!LdrInitializeThunk开始排队的初始 APC 所做的工作多年来一直相当一致。我总是在以下调试会话中看到初始化步骤和 DLL 加载顺序:cdb -xe cpr -c "bp ntdll!LdrInitializeThunk; g" notepad。也就是说,NtCreateUserProcess有时可能会预映射 ntdll.dll 以外的 DLL。 -
我想我得到了一些提示。我电脑上安装的安全解决方案使用Detour注入和hook windows API。而且似乎 Windows Detour 使您能够注入具有 CreateProcess 挂起状态的 DLL。我猜当我创建进程时,经过几次之后,Detour 会加载安全解决方案 dll,然后在此之前加载“kernel32.dll”。虽然我对这个假设没有信心,但我测试过的几个在主线程恢复之前成功加载 kernel32.dll 的可执行文件都产生了从 DebugViewer 查看的 Detour Debug 输出(解决方案制造商留下了消息!)
-
@SihuSong,这听起来很合理。你为什么不把它写成答案呢?
标签: windows dll process code-injection