标题: 程序员的片段(6)--消逝的BreakOnDllLoad 创建: 2017-12-08 16:59 链接: https://scz.617.cn/windows/201712081659.txt 在windbg的"sxe ld"登场前,Windows有过另一个古老的拦截DLL加载的调试机制。 大家都知道IFEO(Image File Execution Options)中的Debugger键值,这是针对EXE 的。与之对应,另有一个BreakOnDllLoad键值,针对DLL。顾名思义,加载DLL时断在 某处。 这个机制,Win7尚且支持,Win10不再支持,所以标题是"消逝的BreakOnDllLoad"。 由于Win7即将退出历史舞台,本文类似"Old News",不再具有现实意义。 -------------------------------------------------------------------------- Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\VERSION.dll] "BreakOnDllLoad"=dword:00000001 -------------------------------------------------------------------------- reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\VERSION.dll" /v "BreakOnDllLoad" /t REG_DWORD /d 1 /f reg delete "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\VERSION.dll" /f 假设VERSION.dll的BreakOnDllLoad置1,Win7的mspaint.exe会加载VERSION.dll。现 在用cdb启动mspaint: "C:\Program Files\Windows Kits\10\Debuggers\x64\cdb.exe" -noinh -snul -hd -g -G -o "C:\Windows\System32\mspaint.exe" 这将断在ntdll!LdrpRunInitializeRoutines()中某处。我把附近的代码用伪C代码写 出来: -------------------------------------------------------------------------- /* * Win10已经没有这个函数 */ LdrpRunInitializeRoutines () { ... if ( LdrpDebugFlags & 5 ) { /* * ldrsnap.c */ LdrpLogDbgPrint( ... ) } /* * 要求目标进程正在被调试,否则不会检查BreakOnDllLoad键值 */ if ( NtCurrentTeb()->ProcessEnvironmentBlock->BeingDebugged || NtCurrentTeb()->ProcessEnvironmentBlock->ReadImageFileExecOptions ) { Status = LdrQueryImageFileExecutionOptions ( &LdrDataTableEntry->BaseDllName, /* * Win10已经没有这个Unicode字符串 */ "BreakOnDllLoad", REG_DWORD, &BreakOnDllLoad, sizeof( BreakOnDllLoad ), NULL ); if ( !NT_SUCCESS( Status ) ) { BreakOnDllLoad = 0; } } if ( BreakOnDllLoad ) { /* * cdb断在在处 */ DbgBreakPoint(); } RtlActivateActivationContextUnsafeFast( ... ); if ( LdrDataTableEntry->TlsIndex && Context ) { /* * DLL的TLS在此得到处理 */ LdrpCallTlsInitializers( LdrDataTableEntry->DllBase, DLL_PROCESS_ATTACH ); } /* * 这是个宏,实际调用InitRoutine(),即目标DLL总入口 */ InitStatus = LdrpCallInitRoutine ( InitRoutine, LdrDataTableEntry->DllBase, DLL_PROCESS_ATTACH, Context ); RtlDeactivateActivationContextUnsafeFast( ... ); ... } --------------------------------------------------------------------------