r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能

渗透技巧 1年前 (2023) admin
871 0 0

排版有点乱,轻喷。内容更重要

1摘要  

r77 Rootkit 是一个无文件的 ring 3 rootkit。它的主要目的是隐藏文件、目录、进程、服务、注册表项等。

         

此外,rootkit 附带一个在操作系统上保留 r77 的安装程序。安装是完全无文件的,这意味着没有文件写入磁盘。 r77 完全依赖内存操作,并始终保留在系统内存中。安装程序的持久性机制允许它在 Windows 重新启动后继续运

于 r77 的部署,只需要一个只需要执一次的可执文件。

2用户手册  

本章解释:

如何安装和卸载 rootkit

如何在影响整个系统的情况下在单个进程上测试 rootkit rootkit 的一般功能 如何配置 rootkit

         

2.1安装.exe  

Install.exe 将 r77 注入到每个正在运的进程中,并将 rootkit 持久保存在系统上。从这一点开始,新进程在运它们自己的任何指令之前被注入。

这是通过挂钩进程创建来实现的。安装后,r77 被设置为在重启后启动,并在第一个用户登录之前注入所有进程。

         

Install.exe 已经捆绑了所有需要的文件,因此没有必要部署 DLL 的连同它。这是单个文件部署。

在安装 r77 后执 Install.exe 时,r77 服务进程将终止并重新创建。这是支持的为,也是将 r77 升级到当前版本的正确方法。已经注入的进程将会分离并重新注入当前版本的 rootkit DLL。为此,请在执 Install.exe 之前执 Uninstall.exe。

         

2.2卸载.exe  

要从系统中完全删除 r77,请运 Uninstall.exe。它将卸载 r77,从所有正在运的进程中分离 rootkit,并从注册表中删除 r77 配置。需要重新启动。

         

2.3测试控制台  

TestConsole.exe 是一个用于测试 r77 功能的工具。它可用于在安装 rootkit 的情况下将 r77 注入或从单个进程中分离 r77。但是,某些功能只有在完全安装 rootkit 后才能使用

测试控制台是用 C# 编写的。以下文件是测试控制台的依赖项, rootkit 的一部分:BytecodeApi*.dll、Helper32.exe、Helper64.exe、 r77x86.dll、r77x64.dll。

2.4示例.exe  


r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能      

$77Example.exe 可用于测试任务管器和文件查看器。要对进程隐藏执快速测试,请启动此可执文件,然后使用测试控制台向任务管器注入 r77。该进程在注入的任务管器中再可见。要隐藏该文件,请使用测试控制台注入资源管器。  


此可执文件实现除 MessageBox 以外的任何东西。任何可执文件都可以用于测试目的,方法是将其文件名重命名为以前缀 $77 开头。

         

要模拟 CPU 使用率,请“CPU 使用率”组合框中的值。如果此进程隐藏在任务管器中,则  CPU  使用率将添加到系统空闲进程中。此外, 处器使用图将得到 *。

         

* 请查看第 5.4 节中有关处器使用率图表的问题。

         

2.5隐藏实体  

以下实体通过前缀、特定条件或配置系统被隐藏。

“前缀”是指名字开头的$77(文件名/注册表键名/等)

         

实体

隐藏 字首

按条件

通过配置

文件

是的

                 

隐藏路径

目录

是的

                 

隐藏路径

命名管道

是的

                 

隐藏路径

计划任务

是的

                 

                 

过程

是的

                 

隐藏的 PID

隐藏进程名称

CPU使用率

                 

隐藏进程的           CPU           使用率          

                 

注册表项

是的

                 

                 

注册表值

是的

                 

                 

服务

是的

                 

隐藏的服务名称

TCP 连接

                 

隐藏TCP           连接           流程

隐藏的本地 TCP 端口隐藏的远程 TCP 端口

UDP 连接

                 

隐藏UDP           连接           流程

隐藏的UDP 端口

         

         

2.5.1文件系统  

在文件系统    




r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能      

中,所有带前缀的目录和文件都是隐藏的。  


这还包括:

         

文件和目录连接

命名管道

计划任务(带有前缀的 .job文件被隐藏;计划任务被隐藏,当 r77 被注入到枚举计划任务的服务中时,而 mmc.exe)

         

此外,配置系统可以隐藏单个文件、目录和命名管道。为此,需要将完整径写入配置系统:

r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能

2.5.2进程  

r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能


隐藏文件名以前缀开头的可执文件的进程。  

         

此外,可以将各个进程 ID 写入配置系统以按 ID 隐藏进程。对于磁盘上的文件,首选的方式是通过前缀隐藏进程和可执文件。对于在内存中创建的无法改文件名的进程,通过 ID 隐藏进程是两个选项之一。

         

或者,也可以使用配置系统通过特定名称隐藏进程:




r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能      

2.5.3Registry  

注册表项和值通过前缀隐藏。

2.5.4服务  




r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能      

服务通过前缀和配置系统中指定的名称隐藏。根据该列表检查名称和显示名称。  


         

2.5.5TCP UDP 连接  

基于以下任一情况隐藏 TCP 和 UDP 连接:

具体情况:

进程被前缀隐藏。

进程被ID 隐藏。

该进程按名称隐藏。

         

或者具体配置:

在配置系统中找到TCP 或TCPv6 连接的本地或远程端口。

UDP 或UDPv6 连接的端口在配置系统中找到。UDP 连接没有远程端口。




r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能      

 


要隐藏传出 TCP 连接,请将远程端口写入配置系统。例如,隐藏远程 TCP 端口 443 会隐藏所有由 Web 浏览器等创建的 HTTPS 连接。

要隐藏 TCP 侦听器,请将本地端口写入配置系统。

         

2.6配置系统  

位于 HKEY_L配O置CAL_MACHINESOFTW系A统RE$77config 下是。此注册表项的 DACL 设置为在允许所有这用户完全访问注,即册使表它位于 HKLM 中。




r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能      

请注意,安装 r77 时,注册表编辑器会注入 rootkit,并且此注册表项可见。使用测试控制台从 regedit 中分离 rootkit。  


         

r77 每 1000 毫秒读取一次配置,其中包含以下信息:

隐藏进程ID 列表 隐藏进程名称列表

隐藏径列表 隐藏服务名称列表

隐藏的本地TCP 端口列表 隐藏的远程TCP 端口列表 隐藏的UDP 端口列表 启动径列

         

除了 $77 前缀之外,此配置还用于隐藏基于自定义配置的实体。任何进程都可以在没有提升权限的情况下写入配置系统。

值的名称通常会被忽略。值 $77configpidsvc32 和 $77configpidsvc64 保留给 r77 服务,应修改。它们是在 r77 服务启动时自动创建的。

         

注意:使用特定的值名称 要使用随机值名称。每次以编程方式创建新值时,列表会随着时间的推移而增长并最终减慢计算机的速度。

         

2.6.1进程 ID  

子项 $77configpid 包含带有要隐藏的进程 ID 的 DWORD 值。此外,来自隐藏进程的网络连接也被隐藏。可以使用测试控制台测试此功能。

         

2.6.2进程名称  

子项 $77configprocess_names 包含 REG_SZ 值以及要隐藏的进程的文件名。此外,来自隐藏进程的网络连接也被隐藏。

         

注意:仅当文件名能有前缀时,才建议按 ID 或名称而是前缀隐藏进程。工艺挖空尤其如此。该前缀还可以防止进程被注入rootkit。

2.6.3  

子项 $77configpaths 包含 REG_SZ 值,其中包含要隐藏的文件、目录、连接或命名管道的完整径。例子:

C:pathtofile.txt

\.pipemy_named_pipe

2.6.4服务名称  

子项 $77configservice_names 包含带有要隐藏的服务名称的 REG_SZ 值。根据此列表检查服务的名称和显示名称。

         

2.6.5本地 TCP 端口  

子项 $77configtcp_local 包含带有要隐藏的本地 TCP 端口的 DWORD 值。

         

2.6.6远程 TCP 端口  

子项 $77configtcp_remote 包含带有要隐藏的远程 TCP 端口的 DWORD 值。

         

2.6.7UDP 端口  

子项 $77configudp 包含带有要隐藏的 UDP 端口的 DWORD 值。

         

2.6.8启动  

子项$77configstartup 包含 REG_SZ 值,其中包含 r77 服务启动时应执的文件。这发生在 Windows 启动时和任何用户登录之前。

这些文件(通常是可执文件)在 SYSTEM 帐户下启动。

3集成商手册  

本章解释:

如何将 r77 集成到另一个应用程序

如何使用控制管道以编程方式与 rootkit 通信

如何使用 r77 定义启动文件

         

请在阅读本章之前阅读第 2 节。

         

3.1安装.exe  

在您的项目中包含  Install.exe   并执它以安装   r77。从这一点开始,所有进程都被注入,并实现了持久化。需要其他文件,因为它们已捆绑在 Install.exe 中。

         

3.2安装.shellcode  

Install.shellcode 文件是 Install.exe 的等效 shellcode。

您可以简单地将它作为资源或 BYTE[] 包含在您的应用程序中。

1.要调用文件,只需加载到内存中

2.将缓冲区标记为RWX

3.将其转换为函数指针

4.它。

         

请参阅:InstallShellCode.cpp 和 InstallShellCode.cs

LPBYTE shellCode =      

         

DWORD 旧保护;

VirtualProtect(shellCode, shellCodeSize, PAGE_EXECUTE_READWRITE, &oldProtect);

         

((void(*)())shellCode)();

         

Install.shellcode 实际上包含 Install.exe,开头有一些 shellcode,使用进程挖空执安装程序。这样,即使安装程序也可以以无文件方式执

         

为避免   shellcode    的扫描时间检测,建议对文件进加密要将此文件存储在磁盘上!它甚至使安装无文件的目的将被完全击败

方式。

重要提示:您的代码必须以 32 位编译并以提升的权限运

         

3.3控制管道  

r77 提供了一个“控制管道”。这是一个与 rootkit 通信的编程接口。

控制管道是一个命名管道,r77 服务从任何进程接收命令并执它们。这样,一个进程(即使是低权限)可以请求 r77 执某些操作。

控制码

参数

执行动作

CONTROL_R77_TERMINATE_SERVICE            

= 0x1001

终止 r77服务而不从进程中分离rootkit r77服务_ 将要 重新开始 Windows 重新启动。

CONTROL_R77_UNINSTALL

= 0x1002

完全卸载 r77并分离 来自所有人的rootkit 过程。

CONTROL_R77_PAUSE_INJECTION

= 0x1003

暂停注入新进程。

CONTROL_R77_RESUME_INJECTION

= 0x1004

简历 注射 流程。

CONTROL_PROCESSES_INJECT

= 0x2001

DWORD 进程号

注入 r77 进入 A 具体过程。

CONTROL_PROCESSES_INJECT_ALL

= 0x2002

           r77           注入           所有进程。

CONTROL_PROCESSES_DETACH

= 0x2003

DWORD 进程号

           特定r77           分离           过程。

CONTROL_PROCESSES_DETACH_ALL

= 0x2004

           所有进程中分离           r77           

CONTROL_USER_SHELLEXEC

= 0x3001

字符串文件

细绳 命令行

特定文件执行 ShellExecute

如果不需要命令 一个 空的 字符串必须 仍然 通过。

CONTROL_USER_RUNPE

= 0x3002

STRING targetPath DWORD payloadSize BYTE[] payload

执行 RunPE。目标路径必须是匹配的现有可执行文件 位数 有效载荷

有效载荷 一个 EXE文件 归档那个 执行 在下面 目标路径的 文件。

要向 r77 服务发送命令,请连接到命名管道:

\.pipe$77control

         

要写入的前四个字节是控制代码。一些控制代码需要额外的参数。   这些需要写在控制代码之后。

         

STRING 应作为 Unicode 字符序列传输,后跟一个两字节的空终止符。

         

ControlPipe.cpp 中的示例演示了如何使 r77 执 ShellExecute。测试控制台可用于测试所有现有的控制代码。

         

3.4枚举与直接访问  

r77 中的“隐藏”意味着隐藏的实体从枚举中移除。如果用户知道文件名,则仍然可以直接访问文件 或者如果进程 ID 已知,则可以打开进程。

         

打开文件/进程/等的功能。没有被钩住,它们会返回“未找到的错误”来进一步伪装隐藏的实体。一般的假设是会猜到隐藏实体的名称。

         

主要原因是,r77 目前没有其他方法可以自我维护。例如,如果隐藏密钥完全可访问,r77 无法从配置系统中读取。

         

3.5自定义启动文件  

如 2.6.8 节所述,可以将可执文件的径写入注册表。 r77 服务将在系统启动时使用 ShellExecute 运这些文件。

         

问题:如果您为启动设置隐藏文件,例如使用 HKCU…Run 键,Windows 找到该文件,因为它是隐藏的,因此它会启动。

         

解决办法:r77负责启动隐藏文件。这有几个优点:

1.您的文件将在具有系统完整性的 SYSTEM 帐户下启动。

2.您的文件将在第一个用户登录之前启动。

3.你可以添加文件以非提升权限启动,它们将与系统一起启动正直。

         

如果您希望您的进程在特定用户帐户下运,则必须执模拟。   如果您需要访问用户的桌面,这是必需的。

         

注意:只是通过将文件添加到 $77configstartup,它并没有隐式隐藏。同样的规则适用:文件必须有前缀,或者它必须被配置系统隐藏。如果你想要文件

r77 注入,然后将 helper 签名写入可执文件将避免注入(参见 4.9 节)。

         

4实施细节  

本章深入解释了重要的实现细节,如果

⋯⋯您想修改代码并改或添加功能⋯⋯您想创建自己的 FUD 版本的 r77

这是一个非常高级的章节,需要深入解整个项目中使用的某些概念,例如挂钩、内存技术、PE 格式等。

         

4.1编译  

通过构建解决方案,只需一步即可编译 r77。编译后的输出将写入 $Build 目录,以所有相关文件都在一个地方。

         

重要提示:使用 Release 编译而 Debug 配置!将调试生成的 DLL 注入远程进程将无法正常工作。

         

BuildTask.exe 项目在 PostBuild 事件中用于帮助编译。

         

4.2Rootkit DLL  

r77 Rootkit 是一个 DLL 文件(r77x86.dll 和 r77x64.dll),分别为 32 位和 64 位进程编译。一旦注入到一个进程中,这个进程将会显示隐藏的实体。

r77 实现反射 DLL 注入。DLL 需要随时写入磁盘。

相反,该文件被写入远程进程内存并调用 ReflectiveDllMain 导出以最终加载 DLL 并调用 DllMain。因此,该 DLL 未在PEB 中列出。

将 DLL 注入到已注入的进程中没有任何影响。DllMain 将检测到这一点并返回 FALSE 以卸载自身。

         

4.3r77 服务  

Install.exe 时,将设置并启动 r77 服务。r77 服务是无文件的,这意味着安装程序会将任何文件写入磁盘。

         

需要两个单独的 r77 服务进程来注入 32 位和 64 位进程。r77 服务的主要目的是在 r77 服务启动时注入所有正在运的进程,以及注入稍后创建的进程。

         

4.3.1无文件启动  

阶段 1:安装程序为 32 位和 64 位 r77 服务创建两个计划任务。计划任务确实需要存储一个名为 $77svc32.job 和 $77svc64.job 的文件,这是无文件概念的唯一例外。但是,一旦 rootkit 运,计划任务也会被前缀隐藏。

r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能

计划任务会从磁盘启动 r77 服务可执文件。相反,它会在系统启动时使用以下命令启动 powershell.exe:

         

[Reflection.Assembly]::Load([Microsoft.Win32.Registry]::LocalMachine.OpenSubkey( SOFTWARE ).GetValue( $77stager

         

该命令是内联的,需要 .ps1 脚本。此处,利用 PowerShell 的 .NET Framework 功能从注册表加载 C# 可执文件并在内存中

为此,使用了 Assembly.Load().EntryPoint.Invoke()。




r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能      

 


         

此外,内联脚本必须绕过 AMSI 以逃避 AV 检测(请参阅第 4.8.1 节)。

阶段 2:执 C# 二进制文件是 stager。它将使用进程挖空创建 r77 服务进程。

         

r77 服务是在 32 位和 64 位中分别编译的本机可执文件。父进程被欺骗并设置为 winlogon.exe 以增加隐蔽性。一旦 r77 服务运起来,这两个进程就会被 ID 隐藏,在任务管器中是可见的。

         

由于计划任务是在SYSTEM账户下启动PowerShell的,所以r77服务也是在SYSTEM账户下运。因此,它可以使用系统  IL   注入进程,受保护的进程除外,例如 services.exe。

         

r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能

重要提示:唯一写入文件系统的项目是作业文件($77svc32.job 和 $77svc64.job)和带有 stager 可执文件的注册表值 $77stager。没有 EXE 或 DLL 文件直接存储在文件系统中。通过使用 shellcode 安装程序以完全无文件的方式部署 r77,甚至可以避免 Install.exe。

         

         

阶段 3:两个 r77 服务进程现在都在运。执以下操作:

1.进程ID存储在配置系统中,隐藏进程。因为进程是使用进程挖空创建的,所以它们能有 $77 前缀。

2.注入所有正在运的进程。

3.创建一个命名管道来处新创建的子进程的注入。

4.除了子进程挂钩之外,子程序每 100 毫秒检查一次新创建的进程。这是因为有些进程无法注入,但仍然创建子进程。

5.对于受保护的进程 services.exe 尤其如此。5.创建控制管道,处其他接收到的请求(命令)过程。

6.$77configstartup下的文件。

         

4.4子进程挂钩  

当 r77 服务启动时,所有当前运的进程都会被注入。稍后产生的进程也必须被注入。有两个概念可以实现这一点:

         

1.) 挂钩进程的创建:创建进程时总是调用的函数是 NtResumeThread。当进程A创建进程B时,该函数在进程B完全初始化后被进程A调用, 但仍处于挂起状态。这个函数调用之后,进程B的创建就完成了。

         

因此,在实际调用此函数之前,NtResumeThread 被挂钩并将 r77 注入到新进程中。幸的是,32 位进程可以生成 64 位子进程,反之亦然。由于 32 位可执文件无法将 64 位 DLL 注入到 64 位进程中,因此 r77 服务提供了命名管道来处注入请求。将新进程 ID 发送到 r77 服 务时,服务会注入进程并返回确认。收到服务确认后,注入完成,可以调用NtResumeThread。根据创建的子进程的位数,必须选择   32   位或64 位 r77 服务来发送请求。

这样,一个进程在执它自己的任何指令之前就被注入了 r77。这一点非常重要,因为有些程序(例如 RegEdit)初始化速度很快,然后在启动后久就执枚举并显示结果。 Rootkit 必须在一开始就注入!

         

然而,幸的是,并非所有进程都可以注入。 Windows 10  保护某些进程免受访问,例如  services.exe。因此,仅依靠子进程挂钩将导致在没有注入 r77 的情况下产生服务,以及其他进程。这是概念 2 发挥作用的时候。

         

2.)  定期挂接新进程:每  100  毫秒,检索正在运的进程列表该列表中的任何新进程都将被注入。这样,子进程例程遗的进程仍然会被注入。但是,存在长达 100 毫秒的延迟,其中 r77 未在该进程中运

如前所述,进程的双重注入没有负面影响。这是受支持的为。

         

4.5Shellcode安装  

Install.shellcode 是与 Install.exe 等效的 shellcode。

该文件直接以加载 Install.exe 的可执代码开始,该文件存储在 shellcode 的末尾。shellcode 是用汇编程序编写的,只需执进程挖空以运安装程序可执文件。

         

这可以节省您编写自己的 RunPE 的时间。

编译后的 shellcode 小于 1 KB,两个文件在编译时简单地连接在一起,因此在构建解决方案时生成 Install.shellcode。

         

4.6依赖性和要求  

r77 没有任何依赖性,除了操作系统本身和初始操作系统安装后已经存在的工具。二进制文件是用 C 编写的,需要安装 Visual C++ 运时。

         

但是,无文件启动机制需要 PowerShell 和 .NET Framework。这两个依赖项都存在于 Windows 7、10 和 11 的全新安装中。

         

.NET Framework 通常有问题,其中 .NET 2.03.5 和 .NET 4.04.8 是两个同的 CLR。这意味着当仅安装 .NET 4.x 时,面

向 .NET 3.5 的 .NET 可执文件会运,而当仅安装 .NET 3.5 时,面向 .NET 4.x 的 .NET 可执文件会运。但是,这对于r77 stager 来说是问题。

         

在 Windows 7 上,默认安装 .NET 3.5,而在 Windows 10 上,未安装 .NET 3.5,而是安装 4.x。如第 4.3.1 节所述,从 PowerShell在内存中执 C# 二进制文件时,目标版本无关紧要。无文件 stager 的目标框架设置为 .NET 3.5,以避免任何与 .NET 4.x 兼容的代码。但是,如果安装了 .NET 3.5 .NET 4.x,则 stager 将运

或者

         

因此,始终满足此要求。r77 “.NET rootkit”,因为只有启动代码需要.NET,但rootkit 本身完全用C 编写。如果使用 Powershell 或 .NET,就没有实现无文件持久性的实用方法。

4.6.1提升的权限  

具有持久性的完整安装需要提升的权限。使用漏洞利用或 UAC 绕过技术提升权限是该项目的一部分。

         

当使用以中等 IL 运的测试控制台时,r77 DLL 可以注入到具有中等 IL 的进程中,但能注入到提升的进程中。这足以进一些测试,但是当未注入提升的进程时,完整安装没有任何意义。

         

4.7挂钩的 API  

Detours 是用于从 ntdll.dll  挂钩函数的挂钩库。这个 DLL 被加载到操作系统的每个进程中。它是所有系统调用的包装器,这使其成为第 3 环中可用的最低层。来自 kernel32.dll 或其他库和框架的任何 WinAPI 函数最终都会调用 ntdll.dll 函数。直接挂钩系统调 用是可能的。这是 ring 3 rootkit 的常见限制。

         

隐藏服务特别需要挂钩 advapi32.dll 和 sechost.dll。请阅读第 4.7.8 节,了解为么这是一项要求。

以下章节描述了每个挂钩的函数。

         

4.7.1NtQuerySystemInformation  

            该 函 数 用于枚举正在运行的进程和检索CPU 使用率。

4.7.2NtResumeThread  

该函数被挂钩以注入创建的子进程,而新进程仍处于挂起状态。只有在注入完成后,这个函数才会真正被调用。

         

注意:挂接 CreateProcess API 是一个好的选择,因为它会一次性创建和启动一个进程。此外,它是一个高级 API,其中有几个。挂钩许多相似的功能,只完成一个任务将是糟糕的设计。

4.7.3NtQueryDirectoryFile  

此函数枚举文件、目录、连接和命名管道。

         

4.7.4NtQueryDirectoryFileEx  

该函数与NtQueryDirectoryFile 非常相似,也必须挂钩。实现大部分是相同的。

         

cmd.exe 中的 dir 命令使用此函数而 NtQueryDirectoryFile。

         

4.7.5NtEnumerateKey  

该函数用于枚举注册表项。调用者指定一个键的索引来检索它。要隐藏注册表项,必须正索引。因此,必须再次枚举键以找到正确的“新”索引。

4.7.6NtEnumerateValueKey  

该函数用于枚举注册表值。这个钩子的实现与 NtEnumerateKey 非常相似。

         

4.7.7枚举服务组W  

函数用于枚举服务。

         

4.7.8枚举服务状态ExW  

这个函数类似于 EnumServiceGroupW。

注意:这两个函数都通过 RPC 与 services.exe 通信以检索服务列表。ntdll.dll 中的挂钩将起作用,因为只有 services.exe 使用 ntdll 函数。

因此hook了上层DLL的advapi32.dll和sechost.dll。

注意:对于服务隐藏,只有 Unicode 函数被挂钩,因为 EnumServicesStatusExA 等似乎没有被任何应用程序使用。只是缺乏实际应用来实际测试 ANSI 类似物。

4.7.9NtDeviceIoControl文件  

此函数用于使用 IOCTL 访问驱动程序。

如果驱动程序是 DeviceNsi 并且 IOCTL 是 0x12001b,则调用者请求所有 TCP 和 UDP 连接的列表。

         

要隐藏一,所有后续都需要向上移动一个并且总计数需要减少。

         

4.8AV规避技术  

已经实施了多种逃避 AV/EDR 检测的技术。

         

4.8.1AMSI  

Assembly.Load().EntryPoint.Invoke() 从注册表加载 C# stager 可执文件并调用它。但是,AMSI 是在 Powershell 和 .NET Framework

本身中实现的。调用 Assembly.Load() 将触发 AMSI 并将可执文件发送到 AV 进分析。要绕过这个,必须为整个 Powershell 进程禁用AMSI。

         

必须修补函数 amsi.dll!AmsiScanBuffer 以始终返回 AMSI_RESULT_CLEAN。在 Install.c 中,Powershell 启动脚本包含执此补丁的代码。

每次安装 r77 时都会动态混淆 Powershell 变名称。此外,字符文字以多态方式进混淆以逃避字符签名,例如“amsi.dll”。

         

注意:Powershell 代码得包含任何带有 C# 代码的 AddType cmdlet。它会调用 csc.exe(.NET 编译器),这会将 C# DLL 放到磁盘上。相反,通过使用反射来查找某些 .NET 函数,从而使用类似于返回到 libc 的方法。

         

注意:仅在 Windows 10 和 11 上需要绕过 AMSI,因为 AMSI 未在 Windows 7 中实现。

         

4.8.2DLL Unhooking  

许多EDR 解决方案在 ntdll.dll 中实现挂钩,有时在 kernel32.dll 中。这些挂钩监视 API 调用,特别是代码注入、进程挖空等所需的调用。为了逃避进程挖空的检测,需要删除 EDR 挂钩。

         

脱钩必须在以下情况下执

‧ StagerPowershell 调用的C# 可执行文件使用process hollowing 创建r77 服务。为了逃避进程挖空的检测,需要移除 EDR 挂钩。

‧ r77 服务:因为 r77 服务会注入所有正在运行的进程,所以 EDR 挂钩必须是也在这里删除。

         

         

删除 EDR 挂钩是通过从磁盘加载 ntdll.dll 的新副本并将当前加载的 ntdll 模块的 .text 部分替换为原始未挂钩的文件内容来实现的。

         

EDR 挂钩通常是几个可疑 ntdll 函数开头的 jmp 指令。

这些钩子很容删除,因为它们仅存在于用户模式中。 EDR 通常实现内核模式挂钩。

         

4.9r77 标头  

要将进程标记为已注入,或标记为 r77 服务等,使用“r77 header”。

进程内存中最适合写入 r77 标头的位置是 DOS 存根。




r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能      

因为它没有被用于任何东西,所以如果这的字节被覆盖,进程会出现故障:  


请注意,这是可执文件内存的视图,而是磁盘上的文件。

进程可能包含以下任一标头。签名被写入 DOS 存根的前两个字节。任何以下数据都写在签名之后。

签名和默认值

描述

R77_SIGNATURE

= 0x7277

当注入 r77 DLL 时,R77_SIGNATURE 被写入主模块的 DOS 存根。

这样,测试控制台就可以检测到进程是否被注入。

如果 r77 被注入进程,但 r77 签名已经存在,DllMain 返回 FALSE 以避免双重注入。

R77_SIGNATURE 之后,存储了一个 to DetachRootkit()。调用它指将针从进程中优雅地分离 r77。这由测试控制台和 Uninstall.exe 使用。

从进程中分离 r77 时,通过将 DOS 存根恢复到其原始状态来删除 r77 标头。

R77_SERVICE_SIGNATURE

= 0x7273

 r77 服务进程需要能够被 Install.exe Uninstall.exe 识别。此签名在编译时写入可执行文件,以避免在写入签名之前将 r77 注入服务进程。

如果r77被注入到r77服务进程中DllMain也返回FALSE

R77_HELPER_SIGNATURE

= 0x7268

帮助程序签名在编译时写入帮助程序文件。

这些包括测试环境的任何可执行文件,例如 TestConsole.exe

如果将 r77 注入辅助进程DllMain 也会返回 FALSE

如果您不想 r77 注入到文件中,则可以在编译时将帮助程序签名写入您自己的文件。

         

4.10编译时间常  

编译时间常 r77def.h 和 GlobalAssemblyInfo.cs 中定义。必须在两个文件中应用改。

         

4.9 节中已经提到了 r77 签名。改这些时,r77 可以自定义为与公开可用的 r77 二进制文件同并且无法被其检测到。

         

这是可以修改的附加常量列表:

         

常量和默认值

         

HIDE_PREFIX

=             $77

         
描述

         

隐藏实体的前缀。

R77_SERVICE_NAME32

= HIDE_PREFIX + svc32

R77_SERVICE_NAME64

= HIDE_PREFIX + svc64

         
启动 r77 服务进程的计划任务的名称。对于计划任务,会创建一个 .job 文件,因此前缀很重要。

         

CHILD_PROCESS_PIPE_NAME32

=             \\.\pipe\             + HIDE_PREFIX +             childproc32

CHILD_PROCESS_PIPE_NAME64

=             \\.\pipe\             + HIDE_PREFIX +             childproc64

         
用于子进程挂钩请求的命名管道的名称。

         

CONTROL_PIPE_NAME

=             \\.\pipe\             + HIDE_PREFIX +             control

         
3.3 节中描述的控制管道的名称。

         

PROCESS_EXCLUSIONS

= {             MSBuild.exe             }

         
不会注入的硬编码进程列表。

         

4.11 特性的反实现  

取消实现某些功能可能是可取的,如果⋯⋯

⋯⋯不需要一个功能

⋯一个特征可以增加检测的可能性

您想减少可执文件的大小

幸运的是,这个项目的代码得到了精心的维护和定期的重构。以下是一些示例,说明如何取消实现某些功能以生成r77 的定制构建:

禁用钩子函数

Hooks.c 中,编辑函数 InitializeHooks UninitializeHooks。删除带有 InstallHook UninstallHook 以取消实现某些挂钩。请务必阅读挂钩函数中的注释以了解您要删除的内容。一些钩子可能是相互依赖的。要取消实现 NtResumeThread,因为它是核心组件并且是子进程挂钩所必需的。

         

         

如果您只想隐藏某些实体(例如,您想隐藏进程,但您关心隐藏文件),这可能很有用。

         

AMSI

Install.c 在函数 GetPowershellCommand 中,删除块 if (IsWindows10OrGreater2()) 其中 AMSI 附加到

powershell 命令。

该命令应直接以 L[Reflection.Assembly]::Load(….

禁用控制管道

Service.c 中,删除 ControlPipeListener(ControlCallback);。然后 r77 服务应该在没有控制管道功能的情况下编译。

……这些只是几个例子,但删除任何其他功能应该很简单,只需要删除一代码


翻译自网络

原文始发于微信公众号(闲聊知识铺):r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能

版权声明:admin 发表于 2023年3月24日 下午10:03。
转载请注明:r77 Windows Rootkit-无文件的后门、dll劫持、持久性和隐身功能 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...