• Meterpreter Window Enhanced


    前言

    • 上次是Metasploit框架的,这次是修改Metasploit所用到的依赖库,依赖库是Metasploit项目独立开发出来的一些特定功能去支持Metasploit框架本身的库,例如:Metasploit-payloadsrex-*等等,这些库会发布到rubygems,不会显得Metasploit很臃肿,而且这些库比较稳定修改频率很小。

    • 前段时间我写了一篇通过Railgun获取Teamviewer的控制ID和密码的模块,现在已经合并到Metasploit的最新版本了,这是PR,在写这个模块的时候发现railgun有很多功能实现不了,比如Railgun中EnumChildWindows有一个参数是要重载EnumChildProc方法的,Railgun定义不了这个中函数,所以就调用不了了。

    • 然后发现Meterpreter的extapi中有一个窗口枚举的功能,但是还是有点鸡肋,它获取不了编辑框里面的内容,对中文的支持也不好,没有窗口类名,所以就增强了这个插件的功能,现在可以支持Unicode,可以通过窗口类名过滤,可以获取编辑框里面的内容,甚至是密码编辑框的内容,已经合并到Meterpreter,这是PR

    Meterpreter

    开发环境搭建

    • 如果要开发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
    
    • 使用Visual Studio 2013打开extapi的解决方案

    TLV(Type-Length-Value)

    • 在Meterpreter的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);
    

    修改代码

    Meterpreter

    • 窗口枚举的代码在[c/meterpreter/source/extensions/extapi/window.c] 文件。
    • 下面这一段代码是把窗口信息发回给Metasploit的,先创建一个Packet类型指针然后往里面添加数据
    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);
    }
    
    • 因为我要添加一个返回窗口类名,字符串类型,Unicode支持请看这里,所以添加了一个参数packet_add_tlv_stringTLV_TYPE_EXT_WINDOW_ENUM_CLASSNAME是我在c/meterpreter/source/extensions/extapi/extapi.h和Metasploit中的lib/rex/post/meterpreter/extensions/extapi/tlv.rb两个文件定义好的用来接收窗口类名的。
    • 其他代码照着抄就可以了,很简单的。

    Metasploit

    • 改完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文件添加过滤和打印窗口类名就完了。

    测试

    • 编译生成的DLL文件放在你安装的库里,就是你修改里哪一个就替换哪一个,我安装metasploit-payloads的路径是/home/kali-team/.gem/ruby/2.7.0/gems/metasploit-payloads-1.3.86,切换到data里面的meterpreter目录下,把DLL替换掉。
    • 再回到Metasploit的开发目录打开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模块,也就是我们开发修改后编译的模块。

    调试

    • 看官方的Wiki这里,在你想调试的的模块上添加#define DEBUGTRACE 1,再在你想调试的地方添加一行代码dprintf([format string]),下载debugView ,管理员权限打开后设置捕捉全局win32调试信息,运行程序然后在Metasploit调用模块就可以在DebugView上面看到调试信息了。

    代码

    • Teamviewer和枚举窗口的PR
    • Meterpreter枚举窗口(顺便改了进程支持Unicode)的PR
  • 相关阅读:
    嵌入式
    c语言
    c++的内存分配
    免费的Skype没有打败固定电话,而付费的移动电话却战胜了固定电话,免费看来并不是关键。在蓝光还没有彻底取代DVD的时候,在线视频出现了,同时颠覆了DVD和蓝光光盘,无论你的光盘容量变得如何大,都不能代表未来,只有在线才是未来。
    直到有了3G,用户才第一次体验到了永远在线的感觉,如果用手机上网也许比找个电源插座还简单,这就是在线的普及趋势。而3G只是个开始,4G、5G会让在线的速度更快更流畅。
    50多万年前的关键字是光明与黑暗,50多年前的关键字是数位和模拟,而今天的关键字是在线与离线。
    “大数据”这个名字叫错了,今天数据的意义并不在于有多“大”,真正有意思的是数据变得在线了。
    云计算是关于信任的生意,有人说他要做三年赚200亿美元的互联网项目,但他要依靠别人的云计算服务,没有这个勇气,是不可能创新的。
    做APP是别人的花园里弄盆栽,因为苹果和安卓已经圈了一个花园,你种点花草是没有问题的,但是想做点有生命力的东西,还是有挑战性的。
    私有云根本就称不上是云,云计算的本质是服务,如果不能够将计算资源规模化、大范围地进行共享,就根本算不上是云计算,传统IT巨头所谓的“私有云”就换汤不换药的升级版IT解决方案。
  • 原文地址:https://www.cnblogs.com/Kali-Team/p/12682598.html
Copyright © 2020-2023  润新知