前言在当今世界,杀毒软件从普通用户到最大的组织,大多数公司依赖杀毒软件作为抵御网络威胁的第一道甚至是最后一道防线。正因为如此,研究防病毒软件,发现其引擎中的漏洞,最重要的是,…
前言
在当今世界,杀毒软件从普通用户到最大的组织,大多数公司依赖杀毒软件作为抵御网络威胁的第一道甚至是最后一道防线。正因为如此,研究防病毒软件,发现其引擎中的漏洞,最重要的是,找到绕过它们的方法,以证明它们根本不提供完全防弹的解决方案。 要进行反病毒绕过研究,了解其内部工作原理和基本原理对于进 行更好的防病毒研究当然是很重要的。这有助于用户和组织评估其防病毒软件是否提供了预期的安全级别。
基础信息
Process Explorer
https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer
参数解读
Process – 进程及其图标的文件名
CPU – 进程的CPU资源百分比
Private Bytes – 分配给进程的内存量
Working Set – 分配给该进程的RAM量
PID – 进程标识符
Description – 进程的描述
Company Name – 进程的公司名称
Process Explorer允许添加更多列,以获取有关操作系统中任何进程的更多信息。
在菜单栏 右键--->Select Columns
想要获取操作系统中特定过程的数据,我们可以双击进程名称,然后获取以下窗口:
参数解读
Image – 有关进程的信息,包括其版本、构建时间、路径和更多
Performance – 有关进程绩效的信息
Performance Graph – 基于图形的有关设备性能的信息过程
Disk and Network – 磁盘和网络输入/输出(I/O)的计数
CPU Graph – 基于图形的CPU使用数据、专用GPU内存、,系统GPU内存等
Threads – 进程的线程
TCP/IP – 输入和输出网络连接
Security – 进程的权限
Environment – 环境变量
Job – 分配给作业对象的进程列表
Strings – 作为进程一部分的字符串(图像级和内存级)
为了让防病毒软件对操作系统中存在的每个过程进行监控,它通常执行hook
hook通常是一个 DLL,它被注入到操作系统中运行的每个过程中,并且它包含某种类型的信息
Ctrl+D
然后选中一个exe
让我们在看一下System 它的PID是4
Processor Monitor
https://docs.microsoft.com/en-us/sysinternals/downloads/procmon
找到防病毒软件用于进行文件扫描的过程
双击进程可以获取更加详细的信息
参数解读
Event – 有关事件的信息,如事件的日期、创建事件的操作结果、可执行的路径等
Process – 事件中有关流程的信息
Stack – 进程的堆栈
对测试文件进行扫描之前,我们首先需要运行Procmon.exe
启动过程监视器后,我们可以看到操作系统上执行许多操作的许多过程,因此我们需要使用筛选
或者(Ctrl+L)
我们要根据company name进行筛选
进行添加包含条件
然后进行AVG 扫描病毒
主要观察两个进程
AVGUI.exe
和AVGSvc.exe
AVGSvc.exe
进程是AVG服务,也参与扫描文件中的病毒
之后,AVGUI.exe
进程,即AVG的GUI流程,开始执行
Ctrl+T
可以看到 执行流程
我们也可以筛选 只有.exe
的进程
同样是Ctrl+L
Autoruns
相对于持久化,Windows 包含许多可能使用持久性的地方
在 Windows中,有许多地方可以放置操作系统启动时将启动的文件,例如:
注册表中:
1、HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
2、HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
3、HKLM\System\CurrentControlSet\Services
4、HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
5、%AppData%\Microsoft\Windows\Start Menu\Programs\Startup
Autoruns:https://docs.microsoft.com/en-us/sysinternals/downloads/autoruns
使用它可以显示操作系统中可以发生持久性的所有位置。
使用过滤器
这次我们指定一个字符串类型的
显示数十个从操作系统启动的AVG 文件
Regshot
继续
https://nchc.dl.sourceforge.net/project/regshot/regshot/1.9.0/Regshot-1.9.0.7z
我们还需要了解哪些注册表值已添加防病毒软件,以帮助我们找出它添加了哪些文件和注册表值。
要收集此信息,我们将使用Regshot
Regshot是一个开源工具,允许我们拍摄注册表的快照,然后比较两个注册表快照,安装程序之前和之后。
我们打开工具
可以选择普通文本输出 还是HTML 输出
定义文件的保存位置,然后单击 第一个镜头:
然后当我们安装完 防病毒软件之后
继续打开 单击第二个镜头
进行输出
即可比较 安装防病毒软件之后
注册表的变化
Third-party engines
必须认识到,一些防病毒软件公司使用其他公司生产的第三方引擎
完整列表可以看这里:https://www.av-comparatives.org/list-of-consumer-av-vendors-pc/
绕过防病毒软件
两种主要方法
在防病毒软件中查找漏洞
使用检测旁路方法
两者最终都需要导致相同的结果,绕过防病毒软件并在用户的端点上运行恶意代码。
https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=antivirus
Windows操作系统
最早的 Windows 操作系统是针对特定的 CPU 和其他硬件规格开发的。Windows NT 推出了一种新型的 Windows,一种独立于过程的操作系统,它还支持多处理、多用户环境,并为工作站和服务器提供单独的版本。
最初,Windows NT 是为 32 位处理器编写的,但后来扩展到更广泛的架构范围,包括 IA-32、MIPS、钛、ARM 等。
Microsoft 还增加了对 64 位 CPU 架构的支持,以及主要的新功能
例如:Windows API/Native API, Active Directory, NTFS, Hardware Abstraction Layer, security improvements
执行的安全机制
ASLR–地址空间布局随机化
ASLR安全机制可防止恶意软件利用基于操作系统中预期内存位置的安全漏洞。ASLR通过随机化内存地址空间来实现这一点,并将关键DLL加载到启动时随机化的内存地址中
DEP–数据执行预防
DEP内存安全机制可防止代码在标记为不可执行内存页面的特定内存区域执行。这反过来又防止或至少强化了缓冲溢出漏洞的利用尝试。
SEHOP – 结构化异常处理覆盖保护
SEHOP运行时安全机制利用SEH 覆盖的开发技术,滥用 SEH 操作系统结构,防止恶意代码的开发企图。此安全机制也可以由流程缓解选项的组策略集部署。
在引入 Windows 操作系统及其安全机制后,让我们继续使用保护环。
protection rings
Windows访问控制列表
操作系统中的每个文件(包括可执行文件、DLL文件、驱动程序和其他对象)都基于配置的**访问控制列表(ACL)**拥有权限。
简单来说,就是每个文件都有自己的权限
Windows 操作系统中的 ACL 称为 DACL,它包括两个主要部分:
• 第一部分是收到相关权限的安全主体。
• 第二部分是对象除了收到其他继承权限外还收到 的权限。
每个对象都被视为访问控制列表中的定义缩写
我们可以看到将收到相关权限的实体或安全主要对象
防病毒软件中的权限问题
静态签名文件的权限不足
静态签名文件的防病毒软件权限不足。
这意味着任何低特权用户都可以删除文件的内容。
当防病毒软件扫描文件时,它将将 t下摆与空签名文件进行比较。
不当特权
权限问题不仅可能发生在防病毒软件中,而且可能发生在所有安全解决方案的 ki nds 中。在我们的一个研究日志中,我们研究了名为赛门铁克的公司的数据损失预防**(DLP)** 安全解决方案。该软件的主要目标是通过外部硬盘驱动器、USB拇指驱动器或上传到n等服务器的文件等存储设备来阻止和防止敏感数据从组织的网络端点泄漏。
经过简单的引子收集过程后,我们找到了 DLP 解决方案的进程名称以及文件系统中加载过程的完整路径及其权限级别。我们发现赛门铁克 DLP 代理的实施具有不当的特权。这意味着具有 NT 权威+系统升级特权的用户(主要是行政特权用户)可以利用潜在的漏洞并删除 DLP 文件夹中的所有文件。
在这种情况下,在我们将权限从管理员延迟到系统(使用 Sysinals-PSexec实用程序)之后,在收集到指向 DLP 文件夹完整路径的足够线索(使用 Sysinals 内部过程资源管理器实用程序)之后,我们删除了文件夹 contents 并重新启动了机器。有了这个
我们成功地从组织的机器中过滤数据,彻底挫败了这种昂贵而复杂的 DLP解决方案的目的。
我们 联系了赛门铁克关于此漏洞,他们发布了一个更新的版本,其中漏洞被修补和修复。
权限问题也可以表现为未引用的服务路径漏洞。
未引用的服务路径
当在 Windows 操作系统中创建一项服务时,其可执行路径包含空格,且未包含在引号内,该服务将容易受到 未引用的服务路径 漏洞的影响。
要利用此漏洞,必须在服务可执行路径中的特定位置创建可执行文件,
并且我们之前创建的服务不会启动防病毒服务,而是先加载,并导致防病毒软件在操作系统启动期间无法加载
当此类漏洞位于端点时,无论哪种防病毒软件到位,都可以利用该软件实现更高的权限,并具有系统持久性的附加价值。
对于防病毒旁路研究,此漏洞可用于其他目的,强制防病毒软件不加载自己或其组件之一,因此它可能会错过威胁,这样,该漏洞就可以绕过防病毒组织。
未引用的服务路径导致漏洞:https://cxsecurity.com/issue/WLB-2019120105
DLL劫持
此漏洞利用了 Windows 操作系统中不安全的DLL 加载机制。
当软件想要加载特定的DLL时,它使用Windows operating system。 它 通过它希望加载的 DLL 名称作为此功能的参数。
我们不建议使用LoadLibrary()
功能,因为有可能将原始 DLL 替换为另一个同名 DLL,并以此 导致程序运行我们的 DLL 而不是最初预期的 DLL。
在非防病毒软件中,此漏洞可能具有低/中等严重级别,但在防病毒软件中,此漏洞可能达到临界严重程度,since
我们 能 实际上 原因 这 防毒 自 负荷 和 跑 a 恶意 德尔 在 一定 例 它可以 甚至 原因 这 德尔 自 禁用 这 防毒 本身 或 甚至 援助 在 绕过 白名单机制。就是我们通常所说的白+黑。
另一个可以帮助我们绕过反病毒软件的漏洞是缓冲区溢出
缓冲区溢出
缓冲溢流(或溢出)是一种非常常见和众所周知的攻击载体,主要用于"溢出"易受攻击程序。这涉及到发送大量数据,这些数据在没有正确输入验证的情况下处理,导致程序以多种方式之一失败。一旦该漏洞被利用,它可用于注入恶意外壳代码并完全控制受害者的设备
两种类型的缓冲溢出漏洞可以被利用:
• 基于堆栈的缓冲区在流中
• 基于堆的 缓冲器 溢出
定位缓冲溢出漏洞
手动和自动。
手动方法:手动搜索基于用户的输入(如程序参数)和确定用户输入背后的机制及其使用的功能
可以使用拆解器、分解器和调试器等工具
自动化方法涉及使用称为"模糊器"的工具,这些工具可自动完成查找用户输入的任务,并有可能在代码背后的机制和功能中发现漏洞。此活动称为"模糊"或"模糊测试"
基于堆栈的缓冲区溢出
如果没有适当的边界输入验证,可以利用此漏洞。典型的示例涉及使用功能,如斯特卡特 () 和斯特里皮 (),这不验证输入的长度。这些功能可以使用模糊器进行动态测试,甚至可以手动使用IDA Pro
和x64dbg
进行测试
以下是利用此类漏洞的一般步骤:
1. 使程序崩溃以了解漏洞发生的位置。
2. 在我们到达 EIP/RIP(指示指头)寄存器的开头地址之前,请查找溢出的确切字节数。
3. 覆盖 EIP/RIP 寄存器,以指向注入壳码的预期地址。
4. 将外壳代码注入可控的预期 地址。
5.可选地,注射NOP(无操作)雪橇,如果ned。
6.跳转到注入的有效载荷的地址执行它。
实现这一目标的方法有很多种,包括使用"离开"和"ret"指令的组合,促进面向返回的编程(ROP)
缓冲器溢出–防病毒旁路方法
有时防病毒软件在一个甚至几个防病毒引擎组件中不使用适当的边界输入验证。例如,如果防病毒程序的拆解引擎试图用分配的文件内容缓冲区解压m alware,并且它使用称为 strcpy () 的功能将缓冲区从一个地址复制到另一个地址,
攻击者可能会溢出缓冲区,劫持 扩展的指令指头
(EIP) 或杀毒引擎过程的 RIP 注册,并使其跳转到其他位置,因此防病毒软件不会检查文件,即使它是恶意的,甚至崩溃的防病毒程序本身。
恶意软件检测在线网站
https://www.virustotal.com/gui/
https://www.hybrid-analysis.com/
https://mac-cloud.riskivy.com/detect
要求
使用最新版本的防病毒软件。
将签名数据库更新到最新的版本,以确保您拥有最新的静态签名。
在进行研究时关闭互联网连接,因为我们不希望防病毒软件与外部服务器进行接触,并签署我们已发现的旁路技术。
使用最新版本的操作系统
进程注入
进程注入(Process injection)
可以将恶意代码注入操作系统内的内存地址空间中,从而绕过动态防病毒引擎检测
需要借助Windows的API
进程地址空间
前言
进程地址空间是在运行过程中分配给每个进程的空间大小,基于计算机内存大小的系统
分配的每个进程内存空间将被赋予一组内存地址空间
每个内存地址空间有不同的目的,取决于代码
操作系统实际负责加载进程及其属性,将分配的虚拟地址映射到物理地址等等
本质
进程注入注入的本质:是将一段代码注入到,另一个进程的进程内存地址空间,给这个进程内存地址空间执行权限,然后执行注入的代码。
适用于一段shellcode
,一个DLL,甚至一个完整的可执行文件(EXE)
实操
1.选择要注入的进程
2.接收目标进程的句柄以访问其进程地址空间。
3.分配一个虚拟内存地址空间,其中将注入和执行代码,并在需要时分配执行标志。
4.将代码注入目标过程的分配内存地址空间。
5.最后, 执行注入的代码。
Windows API
前言
API是两者之间的桥梁
不同的应用程序、系统和架构
API 功能的主要目标是:函数是抽象底层实现,进行创建项目
Windows API是微软的核心API集,允许开发人员创建代码,与Windows操作系统提供的底层预先编写的功能交互系统
简单代码
一个入门的C代码
#include<stdio.h>
int main(){
printf("HelloWorld");
}
在代码的开始 我们导入了一个头文件:stdio.h
使用#include
指令完成
这个头文件提供了printf
的功能,进行打印输出
和本机API的区别
API函数是用户模式函数,在msdn.microsoft.com的Microsoft网站上有完整的文档 。然而,大多数Windows API函数实际上调用本机API来完成这项工作
DLL注入
使用Windows API函数强制将恶意DLL加载到远程进程中
调用如下
• OpenProcess:使用该函数并提供目标进程ID作为其参数之一,注入器进程 接收到远程进程的句柄。
• VirtualAllocex:使用这个函数,注入器进程将分配一个内存缓冲区,该缓 冲区最终将包含目标进程中加载的DLL的路径。
• WriteProcessMemory:该函数执行实际的注入,将恶意负载插入到目标进程 中。
• createremotethread:这个函数在远程进程中创建一个线程,最后执行将加载 DLL的LoadLibrary()函数。
• loadLibrary/getProcAddress:这些函数返回加载到进程中的DLL的地址。考 虑到Kernel32.dll映射到所有Windows进程的相同地址,可以使用这些函数 获取要在远程进程中加载的API的地址。
简单了解
DLL是一个库文件,包含许多函数,这些函数由 Windows PE文件动态加载和使用
DLL文件包括或实际上导出由PE可执行文件使用或导入的窗口和本机API函数
PE文件
PE文件在Windows操作系统中起着重要的作用
扩展名为.exe的可执行二进制文件 以及扩展名为.dll的DLL都使用PE文件格式
但这些文件类型并不只是使用此通用 文件格式的文件类型。
• CPL:控制面板配置的基本文件,在操作系统中起着基本而重要的作用。
ncpa.cpl
就是一个例子,它是Windows上可用的网络接口的配置文件。
• sys:Windows操作系统设备驱动程序或硬件配置的系统文件,允许 Windows与硬件和设备通信。
• DRV:允许计算机与特定设备交互的文件。
• SCR:用作屏幕保护程序-由Windows操作系统使用。
• OCX:Windows用于ActiveX控件,用于创建窗体和网页小部件等目的。
• DLL:与EXE文件不同,DLL文件不能通过双击在硬盘上运行。运行DLL 文件需要一个导入并执行其功能的宿主进程。有几种不同的方法来实现这 一点。
PE文件格式结构
有两个主要部分:
PE头:包括关于基于PE的文件的相关和重要的技术信息
PE节:包括PE文件内容。每一个部分将服 务于PE文件的不同目标
PE头
磁盘操作系统(DOS)头-标识PE文件的标识符或神奇值。
• DOS存根,一个旧的消息,仍然保留在大多数PE文件。它可能会说这个程序不能在DOS 模式下运行,有时会被操纵以绕过杀毒软件。
• PE头-这个头基本上声明一个文件是PE文件格式的。
• 可选头-- 这将包括变量信息,如代码的大小、可执行文件/库文件的入口点、图 像库、节对齐方式等。
• 区段表
• 代码部分
• 代码部分
这部分将包括中央处理器(CPU)最终将执行的程序(编译代码)的机器代码
• 导入部分
本部分将包括从诸如kernel32.dll和ntdll.dll等DLL导入的所需函数
• 数据部分-此部分将包括程序将使用的变量和函数参数
执行
使用rundll32.exe
它允许使用命令行执行包含在DLL文件中的函数。
RUNDLL32.EXE <dllname>,<entrypoint> <argument>
使用LoadLibrary()/LoadLibraryEx()
函数
将文件加载到EXE文件中。当EXE文件使用LoadLibrary()函数时,它将模块的名称作为参数传递
DLL注入的优势
DLL文件通常对普通用户隐藏。
• 当一个DLL加载到另一个进程中时,该DLL有权访问加载该DLL的进 程的进程内存空间。
• 在DLL上执行自动动态分析比在EXE文件上执行要困难得多。
• 当将DLL加载到进程中时,在系统进程中查找DLL将变得更加困难,从而使防病毒检测和事件响应变得更加困难。
Process hollowing
它是在另一个进程的内存地址空间中运行恶意代码的另一种常见方式,但与经典的DLL注入方式有一些小区别
API函数调用:
• createProcess:该函数使用dwCreationFlags参数创建处于挂起状态的合 法操作系统进程(如Notepad.exe)。 抗病毒 旁路 使用 过程 注射 73
• ZWUNMAPViewOfSection/NTUNMAPViewOfSection:这些本机API函数对 进程特定节的整个内存空间执行取消映射。在此阶段,合法系统进程有一个 中空部分,允许恶意进程将其恶意内容写入此中空部分。
• VirtualAllocex:在编写恶意内容之前,该函数允许我们分配新的内存空间 。
• WriteProcessMemory:正如我们之前在经典DLL注入中看到的,这个 函数实际上将恶意内容写入进程内存。
• SetThreadContext和resUmethRead:这些函数将上下文返回给线程,并将进程 返回到其运行状态,这意味着进程将开始执行。
Process doppelgänging
主要用于绕过防病毒引擎,并可用于规避一些内存取证工具和技术
进程Doppelgänging使用以下Windows API和本机API函数:
• createFileTransacted:此函数基于Microsoft的NTFS-TxF特性创建或打开文件、文件流或目录
这用于打开合法进程,如Notepad.exe。
• WriteFile:此函数将数据写入指定的注入文件
• ntCreateSection:此函数创建一个新节,并将恶意文件加载到新创建的目标 进程中
• RollBackTransaction:该函数最终防止修改后的可执行文件(如Notepad.exe )保存在磁盘上
• NtCreateProcessEXEX、RtlCreateProcessParametersEx、VirtualAllocEx、Wr iteProcessMemory、NtCreateThreadEx、NtresUmethRead:所有这些函数都用于启动和运行更改后的进程,使其能够执行预期的恶意活动
对抗注入:
1. 在静态代码级别检测注入-- 甚至在执行文件之前,就在编译的代码中搜索特定的函数组合。
2. 在运行时检测注入-- 监视操作系统中的进程,以识别某个特定进程何时试图注入到另一个进程中 (这种检测将在目标受害进程的初始句柄操作时发出警报)。
Memory bombing
简单来说 就是占用一个超级大的内存
利用分配大内存使得杀毒软件使用过多的资源在相对较大的内存上进行简单的扫描时迫使杀毒软件放弃检测我们的恶意文件
当antivirus 使用过多的资源对相对较大的内存执行简单扫描时,它会迫使antivirus停止检测恶 意文件
malloc()
malloc()
是C语言的一个函数,在某种程度上,它在大多数主流操作系统 中使用,比如Linux、macOS、Windows
在编写基于C/C++的程序时,我们可以将malloc()函数声明为指针
void *malloc(size)
执行此函数后,它返回一个值,该值带有指向进程堆的已分配内存的指针
如果执行失败,则返回NULL
我们使用free()
函数从进程堆中释放分配的内存
free(*ptr);
free()
函数的*ptr
参数是指向以前用malloc()分配的内 存的指针。
我们是一定要释放分配的内存空间的,主要是为了清除任何可能的数据
calloc()
calloc()
是另一个可用于在进程堆中分配内存的函数
malloc()请求分配内存, 但不会用任何数据填充内存,并且没有对其进行初始化
与此不同,calloc()
初始化并用零位填充所有请求的已分配内存
POC
int main()
{
char *memory_bombing = NULL;
memory_bombing = (char *) calloc(200000000, sizeof(char));
if(memory_bombing != NULL)
{
free(memory_bombing);
payload();
}
return 0;
}
简单分析
1.定义一个main()函数
2. 声明一个名为memory_bombing的指针变量,类型为char
3. 用分配的calloc()内存的返回值的指针初始化memory_bombing变量
(此时,反病毒正在努力扫描文件,并没收)
4. 检查memory_bombing的返回值是否是分配内存的有效指针
5. 最后,使用free()函数释放已分配的内存,并通过调用自定义的payload()函数执行预期的恶意shellcode
原理
其实我们还是依赖于动态防病毒引擎通过分配虚拟内存扫描新产 生的进程中的恶意代码,以便在沙箱环境中扫描已执行的进程中的恶意代码。
由于防病毒引擎不希望影响用户体验(UX),分配的内存受到限制
所以,如果我们分配大量内存,防病毒引擎将选择退出扫描,从而绕过防病毒软件
总结
在准备研究杀毒软件的过程中,基础信息搜集是关键的一步。利用一些工具,我们可以更全面的收集信息。
可以寻找更多的工具来帮助定位其他线索,也有其他优秀的动态恶意软件分析工具
其次两种主要的防病毒绕过方法(基于漏洞的绕过和基于检测的绕过)
Windows API函数及其在Windows操作系统中的使用,以及进程地址空间和不同的进程注入技术
- 本文作者: 略略略
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/501
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!