上次是Metasploit框架的,这次是修改Metasploit所用到的依赖库,依赖库是Metasploit项目独立开发出来的一些特定功能去支持Metasploit框架本身的库,例如:Metasploit-payloads
,rex-*
等等,这些库会发布到rubygems,不会显得Metasploit很臃肿,而且这些库比较稳定修改频率很小。
前段时间我写了一篇通过Railgun获取Teamviewer的控制ID和密码的模块,现在已经合并到Metasploit的最新版本了,这是PR,在写这个模块的时候发现railgun有很多功能实现不了,比如Railgun中EnumChildWindows有一个参数是要重载EnumChildProc方法的,Railgun定义不了这个中函数,所以就调用不了了。
然后发现Meterpreter的extapi中有一个窗口枚举的功能,但是还是有点鸡肋,它获取不了编辑框里面的内容,对中文的支持也不好,没有窗口类名,所以就增强了这个插件的功能,现在可以支持Unicode,可以通过窗口类名过滤,可以获取编辑框里面的内容,甚至是密码编辑框的内容,已经合并到Meterpreter,这是PR。
如果要开发Windows上的meterpreter官方好像要指定开发环境为Visual Studio 2013,不知道2013以上的可不可以,反正我就是用2013。
拉取代码到本地,安装依赖,同步子模块
git clone https://github.com/cn-kali-team/metasploit-payloads
cd metasploit-payloads/c/meterpreter
git submodule init && git submodule update
c/meterpreter/source/common/core.h
文件里/*! @brief Meta TLV argument type representing a null value. */
#define TLV_META_TYPE_NONE (0 << 0)
/*! @brief Meta TLV argument type representing a string value. */
#define TLV_META_TYPE_STRING (1 << 16)
/*! @brief Meta TLV argument type representing a unsigned integer value. */
#define TLV_META_TYPE_UINT (1 << 17)
/*! @brief Meta TLV argument type representing a raw data value. */
#define TLV_META_TYPE_RAW (1 << 18)
/*! @brief Meta TLV argument type representing a boolean value. */
#define TLV_META_TYPE_BOOL (1 << 19)
/*! @brief Meta TLV argument type representing a quad-word value. */
#define TLV_META_TYPE_QWORD (1 << 20)
/*! @brief Meta TLV argument type representing a compressed data value. */
#define TLV_META_TYPE_COMPRESSED (1 << 29)
/*! @brief Meta TLV argument type representing a group value. */
#define TLV_META_TYPE_GROUP (1 << 30)
/*! @brief Meta TLV argument type representing a nested/complex value. */
#define TLV_META_TYPE_COMPLEX (1 << 31)
/*! @brief Meta TLV argument type representing a flag set/mask value. */
#define TLV_META_TYPE_MASK(x) ((x) & 0xffff0000)
...
LINKAGE DWORD packet_add_group(Packet* packet, TlvType type, Packet* groupPacket);
LINKAGE DWORD packet_add_tlv_string(Packet *packet, TlvType type, LPCSTR str);
LINKAGE DWORD packet_add_tlv_wstring(Packet *packet, TlvType type, LPCWSTR str);
LINKAGE DWORD packet_add_tlv_wstring_len(Packet *packet, TlvType type, LPCWSTR str, size_t strLength);
LINKAGE DWORD packet_add_tlv_uint(Packet *packet, TlvType type, UINT val);
LINKAGE DWORD packet_add_tlv_qword(Packet *packet, TlvType type, QWORD val );
LINKAGE DWORD packet_add_tlv_bool(Packet *packet, TlvType type, BOOL val);
LINKAGE DWORD packet_add_tlv_group(Packet *packet, TlvType type, Tlv *entries, DWORD numEntries);
LINKAGE DWORD packet_add_tlvs(Packet *packet, Tlv *entries, DWORD numEntries);
LINKAGE DWORD packet_add_tlv_raw(Packet *packet, TlvType type, LPVOID buf, DWORD length);
函数 | 类型 |
---|---|
packet_add_tlv_raw | 原始,任意数据 |
packet_add_tlv_string | 字符串 |
packet_add_tlv_uint | 无符号整数 |
packet_add_tlv_wstring_len | 宽字符长度 |
packet_add_tlv_qword | QWORD |
packet_add_tlv_group | 一组信息 |
packet_add_tlv_raw_compressed | 压缩过的raw |
packet_add_tlv_bool | 布尔型 |
packet_add_tlv_wstring | Unicode |
lib/rex/post/meterpreter/packet.rb
里的类型TLV_META_TYPE_NONE = 0
TLV_META_TYPE_STRING = (1 << 16)
TLV_META_TYPE_UINT = (1 << 17)
TLV_META_TYPE_RAW = (1 << 18)
TLV_META_TYPE_BOOL = (1 << 19)
TLV_META_TYPE_QWORD = (1 << 20)
TLV_META_TYPE_COMPRESSED = (1 << 29)
TLV_META_TYPE_GROUP = (1 << 30)
TLV_META_TYPE_COMPLEX = (1 << 31)
LINKAGE TlvMetaType packet_get_tlv_meta(Packet *packet, Tlv *tlv);
LINKAGE DWORD packet_get_tlv_string(Packet *packet, TlvType type, Tlv *tlv);
LINKAGE DWORD packet_get_tlv_group_entry(Packet *packet, Tlv *group, TlvType type,Tlv *entry);
LINKAGE PCHAR packet_get_tlv_value_string(Packet *packet, TlvType type);
LINKAGE wchar_t* packet_get_tlv_value_wstring(Packet* packet, TlvType type);
LINKAGE UINT packet_get_tlv_value_uint(Packet *packet, TlvType type);
LINKAGE BYTE * packet_get_tlv_value_raw( Packet * packet, TlvType type );
LINKAGE QWORD packet_get_tlv_value_qword(Packet *packet, TlvType type);
LINKAGE BOOL packet_get_tlv_value_bool(Packet *packet, TlvType type);
TLV_TYPE_EXT_WINDOW_ENUM_HANDLE
是在Metasploit和Meterpreter两边定义的命令标示吧。parentWindow = packet_get_tlv_value_qword(packet, TLV_TYPE_EXT_WINDOW_ENUM_HANDLE);
[c/meterpreter/source/extensions/extapi/window.c]
文件。VOID add_enumerated_window(Packet *pResponse, QWORD qwHandle, const wchar_t* cpWindowTitle, const wchar_t* cpClassName, DWORD dwProcessId)
{
Packet* pGroup = packet_create_group();
packet_add_tlv_uint(pGroup, TLV_TYPE_EXT_WINDOW_ENUM_PID, dwProcessId);
packet_add_tlv_qword(pGroup, TLV_TYPE_EXT_WINDOW_ENUM_HANDLE, qwHandle);
packet_add_tlv_string(pGroup, TLV_TYPE_EXT_WINDOW_ENUM_TITLE, wchar_to_utf8(cpWindowTitle));
packet_add_tlv_string(pGroup, TLV_TYPE_EXT_WINDOW_ENUM_CLASSNAME, wchar_to_utf8(cpClassName));
packet_add_group(pResponse, TLV_TYPE_EXT_WINDOW_ENUM_GROUP, pGroup);
}
packet_add_tlv_string
,TLV_TYPE_EXT_WINDOW_ENUM_CLASSNAME
是我在c/meterpreter/source/extensions/extapi/extapi.h
和Metasploit中的lib/rex/post/meterpreter/extensions/extapi/tlv.rb
两个文件定义好的用来接收窗口类名的。改完Meterpreter的代码还要修改Metasploit框架里的代码
在文件lib/rex/post/meterpreter/extensions/extapi/tlv.rb
添加上面Meterpreter定义好的TLV_TYPE_EXT_WINDOW_ENUM_CLASSNAME
TLV_TYPE_EXT_WINDOW_ENUM_CLASSNAME = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_EXTAPI + TLV_EXTENSIONS + 6)
lib/rex/post/meterpreter/extensions/extapi/window/window.rb
添加接受窗口类名的函数response = client.send_request(request)
windows = []
response.each(TLV_TYPE_EXT_WINDOW_ENUM_GROUP) do |w|
windows << {
pid: w.get_tlv_value(TLV_TYPE_EXT_WINDOW_ENUM_PID),
handle: w.get_tlv_value(TLV_TYPE_EXT_WINDOW_ENUM_HANDLE),
title: w.get_tlv_value(TLV_TYPE_EXT_WINDOW_ENUM_TITLE),
class_name: w.get_tlv_value(TLV_TYPE_EXT_WINDOW_ENUM_CLASSNAME)
}
lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/window.rb
文件添加过滤和打印窗口类名就完了。metasploit-payloads
的路径是/home/kali-team/.gem/ruby/2.7.0/gems/metasploit-payloads-1.3.86
,切换到data里面的meterpreter目录下,把DLL替换掉。Gemfilew
文件在最后面添加下面这行配置,版本和路径一定别写错。gem ‘metasploit-payloads‘, ‘1.3.86‘, :path => ‘/home/kali-team/.gem/ruby/2.7.0/gems/metasploit-payloads-1.3.86‘
metsrv
的代码的话,现在启动Metasploit重新生成一次后门程序,重新加载模块就会以上面修改Gemfilew
文件里的配置里的路径加载DLL模块,也就是我们开发修改后编译的模块。#define DEBUGTRACE 1
,再在你想调试的地方添加一行代码dprintf([format string])
,下载debugView ,管理员权限打开后设置捕捉全局win32调试信息,运行程序然后在Metasploit调用模块就可以在DebugView上面看到调试信息了。原文:https://www.cnblogs.com/Kali-Team/p/12682598.html