反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

admin 2024年6月3日18:43:14评论22 views字数 10520阅读35分4秒阅读模式

总结

这项研究由三部分组成,涵盖不同的领域,即开发自定义 RPC 客户端、逆向工程和一些加密技术。

当这项研究开始时,目标实际上是找到一种利用旧 CVE 的新方法,然而深入研究产品后出现了一个新的兔子洞,从而导致了一个新的漏洞。

本部分研究解释了 Windows 环境中远程过程调用 (RPC) 的复杂部分以及如何开发自定义客户端。

CVE:

https://nvd.nist.gov/vuln/detail/CVE-2024-36036

https://nvd.nist.gov/vuln/detail/CVE-2024-36037

背景

ManageEngine 是一家拥有约 50 种不同产品的公司,产品范围从完整的 SIEM 解决方案到移动设备管理系统,在全球拥有 280,000 多家客户。本文将深入介绍 ADAudit Plus,这是一款用于实时监控 Active Directory、Windows 文件服务器和 Windows 配置更改审计的产品。

ADAudit 可以使用 Windows 中提供的标准远程交互工具远程访问事件日志和其他统计信息。但是,为了在目标机器上实现全面的可视性和专门的功能,必须在受审计的 Windows 系统上安装代理,特别是 ADAuditPlusAgent。

当这项研究开始时,目标实际上是找到一种利用旧 CVE 的新方法,然而深入研究产品后出现了一个新的兔子洞,从而导致了一个新的漏洞。

由于旧的 CVE 已修复,因此研究必须在旧版本的 ADAudit 上进行,更准确地说是2021 年 12 月发布的 7050 版本

ManageEngine 倾向于使用 Java 在 Tomcat 上构建应用程序,这使得它成为练习源代码分析和逆向工程的良好目标。让我们开始挖掘吧。

方法

对于那些不熟悉 Java 和反编译的人来说,这里是 Shelltrail 的方法:

找到您要评估的所有 .jar 文件并将其下载到您的 Unix 主机。jar 文件很可能存储在正在评估的产品的安装目录中。

user@adpen1:~/adaudit/7$ ls -latotal 8036drwxr-xr-x 2 user user    4096 Dec  1 08:36 .drwxr-xr-x 5 user user    4096 Dec  1 08:35 ..-rw-r--r-- 1 user user  997934 Dec  1 08:36 AdventNetADAPClient.jar-rw-r--r-- 1 user user   12040 Dec  1 08:36 AdventnetADAPFilter.jar-rw-r--r-- 1 user user  139792 Dec  1 08:36 AdventNetADAPJspClient.jar-rw-r--r-- 1 user user 4534195 Dec  1 08:36 AdventnetADAPServer.jar-rw-r--r-- 1 user user   15735 Dec  1 08:36 AdventnetADAPService.jar-rw-r--r-- 1 user user   68066 Dec  1 08:36 AdventnetADAPStartUp.jar-rw-r--r-- 1 user user  686147 Dec  1 08:36 AdventNetClientComponents.jar-rw-r--r-- 1 user user  290027 Dec  1 08:36 AdventNetClientFramework.jar-rw-r--r-- 1 user user   65094 Dec  1 08:36 AdventNetIdiomsGallery.jar-rw-r--r-- 1 user user  294662 Dec  1 08:36 AdventNetNPrevalent.jar-rw-r--r-- 1 user user  104252 Dec  1 08:36 AdventNetRssLibrary.jar-rw-r--r-- 1 user user  157667 Dec  1 08:36 AdventNetTableComponents.jar-rw-r--r-- 1 user user  781984 Dec  1 08:36 AdventNetUpdateManagerInstaller.jar-rw-r--r-- 1 user user   22935 Dec  1 08:36 AdventNetWebClientCore.jar-rw-r--r-- 1 user user   13413 Dec  1 08:36 AdventNetWebClientRangeNavigator.jar-rw-r--r-- 1 user user   13809 Dec  1 08:36 AdventNetWebClientTree.jar

Jar 文件是 Java Archive 的缩写。它是一种基于流行的 ZIP 文件格式的文件格式,用于将多个文件归档为一个文件。

是的,可以使用 zip 工具提取 jar 文件并检索内容:

user@adpen1:~/adaudit/7$ 7z l AdventNetADAPClient.jar

[...]2021-12-30 21:37:22 D....            0            0  com/adventnet/sym/adsm/common/webclient/tracker2021-12-30 21:37:22 D....            0            0  com/adventnet/sym/adsm/common/webclient/tree2021-12-30 21:37:22 D....            0            0  com/adventnet/sym/adsm/common/webclient/util2021-12-30 21:37:22 .....         3836         1804  com/adventnet/sym/adsm/auditing/webclient/compliance/ComplianceDEReportHandler.class2021-12-30 21:37:22 .....        43842        17323  com/adventnet/sym/adsm/auditing/webclient/compliance/ComplianceReportHandler.class2021-12-30 21:37:22 .....         1857          764  com/adventnet/sym/adsm/auditing/webclient/ember/api/ADAPAPIServlet.class2021-12-30 21:37:22 .....         1884          774  com/adventnet/sym/adsm/auditing/webclient/ember/api/ADAPAgentAPIServlet.class[...]

这将为您提供存储在 Jar 中的类文件,但是类文件是编译成 Java 字节码的 Java 代码,由 Java 虚拟机 (JVM) 解释,因此无法被人类阅读。

jd-gui是一个很好的工具,可以将单个 Jar 文件反编译为人类可读的格式以供分析,但是当您有许多文件时,它的扩展性不佳。

为了自动化此过程, 可以使用jd-cli来解压和反编译 Jar 文件 - 使其可搜索和查看。

user@adpen1:~/adaudit/7$ jd-cli *.jar 09:51:11.097 INFO  com.github.kwart.jd.cli.Main - Decompiling AdventNetADAPClient.jar09:51:11.107 INFO  com.github.kwart.jd.output.ZipOutput - ZIP file output will be initialized - AdventNetADAPClient.src.jar09:51:14.930 INFO  com.github.kwart.jd.output.ZipOutput - Finished with 129 class file(s) and 1 resource file(s) written.[...]

user@adpen1:~/adaudit/7$ mkdir srcuser@adpen1:~/adaudit/7$ cd srcuser@adpen1:~/adaudit/7/src$ find ../ -name '*src.jar' -exec unzip -o {} ;Archive:  ../AdventNetUpdateManagerInstaller.src.jar  inflating: META-INF/MANIFEST.MF      inflating: com/adventnet/tools/update/installer/images/context_help.png    inflating: com/adventnet/tools/update/installer/images/context_install.png    inflating: com/adventnet/tools/update/installer/images/error.png    inflating: com/adventnet/tools/update/installer/images/help_icon.png    inflating: com/adventnet/tools/update/installer/images/import.png    inflating: com/adventnet/tools/update/installer/images/info.png [...]

从这一点开始,就可以开始对源代码的分析了。

发现

将焦点从最初目标转移的原因是,人们开始对与ADAuditPlusAgent 安装了 的 Windows 计算机交互并获取信息的功能感兴趣。ADAuditPlusAgentADAudit 服务器有许多功能可以激活,其中之一就是所谓的 SessionMonitoring功能。此功能启动一个进程,以设定的时间间隔截取屏幕截图,并将其发送到中央服务器。这允许服务器创建配置状态更改的视频并将它们与事件联系起来。例如,代理计算机中的低权限用户可以获得管理员删除关键配置文件的视频会话。

听起来这是一个有趣的功能,不是吗?

当从 ADAudit 服务器启用该SessionMonitoring功能并使用 wireshark 分析发送到代理的所有流量时,发现通过命名管道进行 RPC 交互。

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

嗯,很有趣!让我们首先深入了解 DCE RPC 的历史。

DCE RPC/MSRPC

DCE RPC 或分布式计算环境远程过程调用是客户端与服务器交互中使用的协议,是计算机科学中的通用术语,而不仅仅是 Windows 系统上可用的术语。

然而,微软想要自己的风格,并在 1993 年首次发布的 Windows NT 中开发了 MSRPC(微软远程过程调用)。RPC 是一种古老的协议,但它是 Windows 环境中计算机间通信工作方式的基础。

因此,RPC 的工作原理基本上是定义一个接口定义语言 (IDL),向客户端公开程序。IDL 还定义了客户端应如何与 UUID、版本和可选句柄等参数进行交互。

[    uuid(7a98c250-6808-11cf-b73b-00aa00b677a7),    version(1.0),    implicit_handle(handle_t ImplicitHandle)]

interface hello{    void HelloProc([in, string] unsigned char * pszString);    void Shutdown(void);}

第一部分称为 IDL 标头。此标头应包含 UUID(以免与其他 RPC 接口冲突)、版本号,并且可以使用三种不同的句柄:显式、隐式和自动。

第二部分,也称为 IDL 主体,说明了客户端可以与之交互的过程。

连接到服务器时,必须初始化与 RPC 接口的绑定。这可以是ncacn_ip_tcpncalrpcncacn_np

ncacn_ip_tcp使用纯 TCP 通信与服务器交互。要使此绑定起作用,必须为 RPC 服务器配置一个可访问的静态 TCP 端口。这不需要身份验证即可建立与 RPC 的连接,将所有身份验证责任留给服务器上公开的过程。与 RPC 的初始连接是通过 TCP/135 完成的。

例子:ncacn_ip_tcp:100.64.5.212[49670]

ncalrpc用于不应通过网络暴露的本地 RPC 交互。

例子:ncalrpc:[LRPC-dfdb2238aff756a07c]

ncacn_np让客户端和服务器协商 TCP 端口以进行交互,协商通过 SMB 进行。这意味着,如果未启用匿名会话,则这种类型的绑定需要用户名和密码才能连接到 SMB。

例子:ncacn_np:100.64.5.212[pipehello]

开发

到目前为止,我们所知道的实际上只是 ADAudit 服务器正在使用 RPC 通过命名管道与代理进行交互,ADAPAgentRpcPipe如 wirehark 屏幕截图中所示。

我们现在需要做的是:

  • 创建有效的 IDL 结构

  • 煮一大罐咖啡

  • 构建 RPC 客户端

  • 猜了很多

  • 创建输入数据,这些数据将被编组为服务器 RPC 接口将对其执行操作的有效存根。

让我们从 IDL 结构开始。RpcView拥有完成此步骤所需的一切,因为该工具可以从 RPC 接口反编译 IDL 结构。此工具应在公开 RPC 接口的服务器上执行:

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

从https://visualstudio.microsoft.com/downloads/获取 Visual Studio 2022 安装程序

选择安装使用 C++ 的桌面开发

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

确保选择了 Windows SDK,因为此包包含制作 RPC 客户端所需的组件:

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

启动 Visual Studio 2022 并启动 C++ 控制台应用程序项目。

首先将项目构建选项更改为Release,x64以便在构建机器之外运行已编译的二进制文件时不需要调试运行时库。

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

在 Visual Studio 中的源文件ADAPAgentRpcPipe.idl结构中创建一个名为的文件:

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

将RpcView导出的反编译的IDL结构复制到新创建的文件中。

[  uuid(7a98c250-6808-11cf-b73b-00aa00b677a7),    version(1.0),]interface DefaultIfName{  void Proc0(    [in]long arg_0,    [in][out]long* arg_1);

  void Proc1(    [in]long arg_0,    [in][string] wchar_t* arg_1,    [in][out]long* arg_2);

  void Proc2(    [in][out]long* arg_0,    [in][out]long* arg_1);}

在 Visual Studio 中右键单击该文件并选择编译- Visual Studio 将使用midl.exeIDL 文件编译为 C 代码,以处理适当的编组操作。

编组是将数据对象和参数转换为可通过网络传输的状态的过程。这在传输复杂数据结构时至关重要。

实际上,在将命令推送到 ManageEngine ADAudit Agent 时发送到 RPC 服务器的数据可以在部分中的 DCERPC 请求中查看Stub data。此可见性的一个例外是,如果服务器默认为 SMB3,则该Stub data部分会被加密。在下图中,服务器正在使用 SMB2:

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

回到项目;编译 IDL 结构后,Visual Studio 项目文件夹中应该有三个新文件:

  • ADAPAgentRpcPipe_c.c: _c 代表客户端

  • ADAPAgentRpcPipe_h.h: _h 为标题

  • ADAPAgentRpcPipe_s.c: _s 代表服务器

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

  • 创建有效的 IDL 结构。完成。

接下来是coffee:

IDL 结构完成并且咖啡准备就绪后,下一步就是构建 RPC 客户端。Microsoft 提供了示例代码,指定如何构建 RPC 客户端和服务器应用程序。公共代码将用作我们的 ADAuditRPC 客户端的骨架,因此将其复制到 Visual Studio 中名为“源文件”adauditrpc-client.cpp的 文件中(使用任何现有的主 cpp 文件或创建一个新文件)

示例代码:

/* file: helloc.c */#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include "hello.h" #include <windows.h>

void main(){    RPC_STATUS status;    unsigned char * pszUuid             = NULL;    unsigned char * pszProtocolSequence = "ncacn_np";    unsigned char * pszNetworkAddress   = NULL;    unsigned char * pszEndpoint         = "\pipe\hello";    unsigned char * pszOptions          = NULL;    unsigned char * pszStringBinding    = NULL;    unsigned char * pszString           = "hello, world";    unsigned long ulCode;

    status = RpcStringBindingCompose(pszUuid,                                     pszProtocolSequence,                                     pszNetworkAddress,                                     pszEndpoint,                                     pszOptions,                                     &pszStringBinding);    if (status) exit(status);

    status = RpcBindingFromStringBinding(pszStringBinding, &hello_ClientIfHandle);

    if (status) exit(status);

    RpcTryExcept      {        HelloProc(pszString);        Shutdown();    }    RpcExcept(1)     {        ulCode = RpcExceptionCode();        printf("Runtime reported exception 0x%lx = %ldn", ulCode, ulCode);    }    RpcEndExcept

    status = RpcStringFree(&pszStringBinding); 

    if (status) exit(status);

    status = RpcBindingFree(&hello_IfHandle);

    if (status) exit(status);

    exit(0);}

/******************************************************//*         MIDL allocate and free                     *//******************************************************/

void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len){    return(malloc(len));}

void __RPC_USER midl_user_free(void __RPC_FAR * ptr){    free(ptr);}

我们需要做的第一个修改是将第 1 行和第 5 行的文件名替换#include "hello.h"为, #include "ADAPAgentRpcPipe_h.h"因为我们已经编译了通过 IDL 文件创建的自己的头文件。此外,我们添加了一行以便#pragma comment(lib, rpcrt4.lib")能够创建 RPC 绑定。

结果:

- /* file: helloc.c */  #include <stdlib.h>  #include <stdio.h>  #include <ctype.h>- #include "hello.h"   #include <windows.h>

+ /* file: adauditrpc-client.cpp */  #include <stdlib.h>  #include <stdio.h>  #include <ctype.h>+ #include "ADAPAgentRpcPipe_h.h"   #include <windows.h>+ #pragma comment(lib, "rpcrt4.lib")下一步是替换一些数据类型并初始化用于 RPC 绑定的变量。这些可以在第 12-19 行找到。

     RPC_STATUS status;-    unsigned char * pszUuid             = NULL;-    unsigned char * pszProtocolSequence = "ncacn_np";-    unsigned char * pszNetworkAddress   = NULL;-    unsigned char * pszEndpoint         = "\pipe\hello";-    unsigned char * pszOptions          = NULL;-    unsigned char * pszStringBinding    = NULL;-    unsigned char * pszString           = "hello, world";     unsigned long ulCode;

     RPC_STATUS status;+    RPC_WSTR pszUuid = NULL;+    RPC_WSTR pszProtocolSequence = (RPC_WSTR)L"ncacn_np";+    RPC_WSTR pszNetworkAddress = (RPC_WSTR)L"100.64.5.212"; // Target ADAudit agent+    RPC_WSTR pszEndpoint = (RPC_WSTR)L"\pipe\ADAPAgentRpcPipe";+    RPC_WSTR pszOptions = NULL;+    RPC_WSTR pszStringBinding = NULL;+    //unsigned char * pszString           = "hello, world";     unsigned long ulCode;

在第 29 行我们替换:

- status = RpcBindingFromStringBinding(pszStringBinding, &hello_ClientIfHandle);+ status = RpcBindingFromStringBinding(pszStringBinding, &DefaultIfName_v1_0_c_ifspec);

第 49 行:

- status = RpcBindingFree(&hello_IfHandle);+ status = RpcBindingFree(&DefaultIfName_v1_0_c_ifspec);

&DefaultIfName_v1_0_c_ifspec参数在我们的 IDL 编译的头文件中定义,就像我们命名我们的 RPC 接口一样DefaultIfName (ADAPAgentRpcPipe.idl 中的第 5 行)。

最后一步是调用 IDL 中所述的正确程序:Proc0Proc1Proc2。目前,我们不知道当这些程序在代理端触发时会做什么,但我们的目标是找出答案。
在第 34 行和第 35 行,Microsoft 的示例代码调用示例程序 HelloProc()Shutdown()。我们将继续用替换它们Proc0并提供有效参数来测试我们的第一个 ADAuditAgentRpcPipe 程序。
通过检查我们的 IDL 结构,Proc0我们还知道该过程接受两个参数:

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

arg_0数据类型long为整型,arg_1数据类型long*为指向长整型的指针。arg_1定义的[in][out]含义是,这可以从应用程序中输出。

由于我们的 IDL 标头结构缺少隐式句柄,因此我们需要为 提供句柄&DefaultIfName_v1_0_c_ifspecProc0,我们还将实例化arg_0和 的变量arg_1

-    RpcTryExcept-    {-        HelloProc(pszString);-        Shutdown();-    }

+    long arg_0 = 0;+    long arg1_pointer;+    long* arg_1 = &arg1_pointer;+    RpcTryExcept+    {+        Proc0(DefaultIfName_v1_0_c_ifspec, arg_0, arg_1);+    }

为了让 Visual Studio 引用DefaultIfName_v1_0_c_ifspec,我们需要将该 ADAPAgentRpcPipe_c.c文件包含在我们的源文件列表中:

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

还添加Header FilesADAPAgentRpcPipe_h.h下的文件。

Visual Studio 中的最终项目结构现在应如下所示:

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

如果每一步都正确执行,项目现在应该可以构建了。瞧…

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

但它真的有效吗?

从命令行运行二进制文件不会打印任何输出,除非抛出异常,但如果使用 Wireshark 分析网络流量,我们可以看到与 ADAudit Web 应用程序触发 RPC 交互时的流量类似的流量。

反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

天哪,它似乎有效!

概括

在本部分研究中,我们成功创建了一个可运行的 RPC 客户端,用于与 ADAudit 代理进行交互。但我们仍然不知道Proc0或 Proc1的Proc2作用。在第 2 部分中,我们将深入研究代理软件的逆向工程,以期找出我们新创建的客户端实际上可以做什么。

关注我们的 LinkedIn 页面来支持我们,并在发布新研究时收到通知:https://www.linkedin.com/company/shelltrail

点击此 URL 阅读第 2 部分:https://www.shelltrail.com/research/manageengine-adaudit-reverse-engineering-windows-rpc-to-find-cve-2024-36036-and-cve-2024-36037-part2/

ManageEngine ADAudit - Reverse engineering Windows RPC to find CVEs - part 1 / RPChttps://www.shelltrail.com/research/manageengine-adaudit-reverse-engineering-windows-rpc-to-find-cve-2024-36036-and-cve-2024-36037-part1/

原文始发于微信公众号(Ots安全):反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月3日18:43:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   反转 Windows RPC 以查找 CVE(CVE-2024-36036、CVE-2024-36037)https://cn-sec.com/archives/2804594.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息