Notepad++ plugin local exploit

前段时间,在用 npp 分析一个 html 文件时,准备把其中的混合在一起的 js 分离出来,在 js 前后换行时 npp 崩溃了,感觉是哪里 bug 了,重试了几次都能很稳定的重现。本着张银奎老师的精神,上调试器。用 windbg 附加到 npp 进程,重现这个 crash 后,停到调试器内,看了下栈。

很明显栈溢出了,返回地址都是文本中的字符,溢出发生在 NotepadSharp.dll 也就是 Notepad# 插件中。Npp 上的插件基本都是开源的,那就把代码搞下来,用 VS 编译了个 debug 版,放进去再次触发崩溃,发现 PluginDefinition.cpp 的 void Newline() 函数中

char line[9999];

::SendMessage(curScintilla, SCI_GETLINE, line_number – 1 , (LPARAM)line);

将当前光标上一行的文本内容拷贝到 char line[9999] 这个 buffer 中,所以很自然,当文本行内容很长,就栈溢出了。

既然溢出在栈上,通过覆盖返回地址和栈指针,在 XP 上应该可以轻松控制程序执行流。不过这个插件的 release 版是在 VS2010 上编译的,打开了 /GS 参数,所以在函数中有 security cookie 检查,而且 security cookie 是随机值。

试图覆盖返回地址时,也会将 security cookie 覆盖,所以导致函数返回之前就出错。

在 Yuki 的指点下,加长文本行的内容,向后继续覆盖,试图覆盖到 exception handler。再次触发后,eip的确变成了覆盖的内容,不过并非覆盖了 exception handler ,而是覆盖了某个窗口消息循环中的回调函数指针。

这是原始的 0x000da8dc 开始的内容,后面会看到 0x000da8dc 存储的是 edi,0x000da8f4 存储的则是回调函数指针,原始的内容是 User32.dll 的 CallWindowProcW 函数指针。经测试,这里应该是 Explorer 插件的回调函数,其实没有Explorer 插件也可以在附近的位置覆盖到其它窗口回调。当按回车后,::SendMessage 不仅拷贝了字符串,还触发了多个插件注册的回调函数。所以在 NotepadSharp 的 Newline 函数还未返回前,其他插件,例如 Explorer 之前注册的窗口回调就被调用了。于是通过很长的溢出,覆盖了其他的栈空间,避开了 security cookie 检查,从而能控制 eip。通过覆盖,在 html 文件对应位置填写 0x7E47B533,也就是 Windows XP SP3 en 上的 jmp edi 指令。

并且在 0x000da8dc 填上 EB1C,短跳转 1C 个字节。之所以要跳转是因为 edi 在之前覆盖的函数指针前方,如果需要执行更多的代码,空间似乎有点不太够,通过跳转来到指针位置的后方。在跳转目标地址填上 int 3 也就是 CC。触发漏洞后,成功的停在 windbg里面。后面就可以用 shellcode 弹个计算器什么的了,不过查看寄存器,发现 ebp 指向的地址不可写,就把 esp 的值赋给 ebp,当作新的栈。最终,贴上一段 metasploit 的 shellcode,成功的在 npp 中按一下回车,导致 npp 崩溃,并弹出了计算器。

这个问题已经报告给 npp 的插件管理者,也报告给了 Notepad# 的作者,不过似乎该插件作者已经很久不更新该插件,也没有留下有效的联系地址,似乎一直对该问题没有响应。如果已经安装了 Notepad# 插件,最好将其卸载,虽然被攻击的可能性不大,但是崩溃什么的也不好。

加入对话

3条评论

  1. JSToolNpp 中能增加一个选项,让var多定义时在format时候不分行吗?
    var a=1,b=1,c=1…..不分行。
    感谢你的作品。

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据