标题: 程序员的片段(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( ... ); ... }