windbg jsprovider.dll的一个BUG

这是微软提供的一个windbg JavaScript插件例子:


function FindTitleWithLINQ ()
{
var isMainFrame = function ( frame ) { return frame.toString().includes( "__mainCRTStartup" ); };
var isMainThread = function ( thread ) { return thread.Stack.Frames.Any( isMainFrame ); };
var curProcess = host.currentProcess;
var mainThread = curProcess.Threads.Where( isMainThread ).First();
var mainFrame = mainThread.Stack.Frames.Where( isMainFrame ).First();
var locals = mainFrame.LocalVariables;

return host.memory.readWideString( locals.StartupInfo.lpTitle );
}

启动notepad.exe,cdb附加之,如果一切正常的话,应该这样测试插件:


> .load jsprovider.dll
> .scriptload TitleFinder.js
> dx Debugger.State.Scripts.TitleFinder.Contents.FindTitleWithLINQ()

说说这个插件的原始意图。针对所有线程查看调用栈回溯:


> ~*kcn

0 Id: 14e4.ff8 Suspend: 1 Teb: 000000a1`b7544000 Unfrozen
# Call Site
00 win32u!NtUserGetMessage
01 USER32!GetMessageW
02 notepad!WinMain
03 notepad!__mainCRTStartup
04 KERNEL32!BaseThreadInitThunk
05 ntdll!RtlUserThreadStart

# 1 Id: 14e4.1500 Suspend: 1 Teb: 000000a1`b7556000 Unfrozen
# Call Site
00 ntdll!DbgBreakPoint
01 ntdll!DbgUiRemoteBreakin
02 KERNEL32!BaseThreadInitThunk
03 ntdll!RtlUserThreadStart

在调用栈回溯信息中寻找”__mainCRTStartup”,定位相应线程的相应栈帧,在该栈帧上查看局部变量:


> ~0s
> .frame /c 3
> dv

它假设notepad.exe的PDB文件保留了局部变量,比如StartupInfo;实际上这些信息只可能出现在私有PDB中,上面的dv不会显示任何内容。


> dt *!*STARTUPINFO
combase!LPSTARTUPINFO
combase!STARTUPINFO
urlmon!LPSTARTUPINFO
urlmon!STARTUPINFO
uxtheme!LPSTARTUPINFO
uxtheme!STARTUPINFO
wintypes!LPSTARTUPINFO
wintypes!STARTUPINFO

> dt combase!STARTUPINFO lpTitle
+0x018 lpTitle : Ptr64 Wchar

如果有StartupInfo,会从中析取lpTitle成员。


STARTUPINFO structure
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx

lpTitle

For console processes, this is the title displayed in the title bar if
a new console window is created. If NULL, the name of the executable
file is used as the window title instead. This parameter must be NULL
for GUI or console processes that do not create a new console window.

从MSDN的描述看,对于notepad.exe,析出来的lpTitle应该是可执行文件名。微软演示插件效果时,确实看到”C:\Windows\System32\notepad.exe”。微软写文档的人应该使用了私有PDB,否则只会得到报错:

> dx Debugger.State.Scripts.TitleFinder.Contents.FindTitleWithLINQ()
Error: Unable to get property ‘lpTitle’ of undefined or null reference

关于无法获取notepad.exe局部变量,另有方案交叉印证:


> dx Debugger.Sessions.First().Processes.First().Threads

[0xff8] : notepad!WinMainCRTStartup (00007ff7`782393e0)
[0x1500] : ntdll!DbgUiRemoteBreakin (00007ffa`c8190160)

> dx Debugger.Sessions.First().Processes.First().Threads.First().Stack.Frames

[0x0] : win32u!NtUserGetMessage + 0x14
[0x1] : USER32!GetMessageW + 0x26
[0x2] : notepad!WinMain + 0x291
[0x3] : notepad!__mainCRTStartup + 0x19f
[0x4] : KERNEL32!BaseThreadInitThunk + 0x14
[0x5] : ntdll!RtlUserThreadStart + 0x21

> dx Debugger.Sessions.First().Processes.First().Threads.First().Stack.Frames[3].LocalVariables

没有任何输出。

插件关于”__mainCRTStartup”的假设并不总是成立,比如Win7中的notepad.exe,入口函数并不是它。

测试该插件时发现一个引擎BUG:


> dx Debugger.State.Scripts.TitleFinder.Contents.FindTitleWithLINQ()
Error: Unable to get property 'lpTitle' of undefined or null reference
> .scriptunload TitleFinder.js
JavaScript script unloaded from 'TitleFinder.js'
> dx Debugger.State.Scripts
TitleFinder
> .scriptlist
Command Loaded Scripts:

“dx Debugger.State.Scripts”表明插件未被成功卸载,”.scriptlist”已经啥都看不到了。

重新加载插件,有异常现象:


> .scriptload TitleFinder.js
JavaScript script successfully loaded from 'TitleFinder.js'
> dx Debugger.State.Scripts
TitleFinder
TitleFinder_1
> .scriptlist
Command Loaded Scripts:
JavaScript script from 'TitleFinder.js'

“dx Debugger.State.Scripts”显示多出一个”TitleFinder_1″,且只能用它:


> dx Debugger.State.Scripts.TitleFinder.Contents.FindTitle()
Error: Unable to bind name 'FindTitle'
> dx Debugger.State.Scripts.TitleFinder_1.Contents.FindTitle()
Error: Unable to get property 'lpTitle' of undefined or null reference

要想彻底恢复正常,只能:


> .scriptunload TitleFinder.js
> .unload jsprovider.dll
> .load jsprovider.dll
> .scriptload TitleFinder.js

测试对象是10.0.15063.468版x64 windbg。

Spread the word. Share this post!

Meet The Author

C/ASM程序员

Leave Comment