type
Post
status
Published
date
Jun 19, 2024
slug
AMSI2
summary
tags
开发
攻防
windows安全研究
category
网络安全
icon
password
0x00 基础
分析源代码发现
SampleAmsiProvider 类实现了 IAntimalwareProvider 接口。Scan方法实现了扫描逻辑。
CloseSession方法用于关闭会话。
DisplayName方法返回提供者的显示名称。
Scan 接收IAmsiStream 作为参数,其有两个方法:GetAttribute() 和 Read()。GetAttribute() 方法获取有关待扫描内容的元数据。开发人员通过传递一个 AMSI_ATTRIBUTE 值来请求这些属性,该值指示他们希望检索的信息。
- APP_NAME
- 提交要扫描的内容的应用程序的名称
- CONTENT_NAME
- 如果内容源自磁盘上的文件,则该
contentname为文件的完整路径。如果内容源自内存,则此字段将为空。
- AMSI_ATTRIBUTE_CONTENT_SIZE、AMSI_ATTRIBUTE_CONTENT_ADDRESS
- 待扫描内容的地址和大小,可以通过这两个值取出待扫描内容。
- 一般需要检测的只有
DotNet和VSS事件是二进制数据。 coreclr也是二进制数据,但我感觉 EDR 没有检测的必要。
只有当内容已经完全加载到内存中时才会返回 AMSI_ATTRIBUTE_CONTENT_ADDRESS ,大多数情况下,数据是作为流提供的,在这种情况下,可以使用
Read() 方法来逐块读取缓冲区中的数据。当
Scan()方法返回时,它必须将 HRESULT 和 AMSI_RESULT 传递给调用方。可以在 dll 中直接实现检测逻辑,不过我想实现更接近 EDR 的检测流程:dll 获取检测信息,传递给agent,agent 进行判断后再返回给 dll。
需要特别注意的是,执行操作时会等待 Scan() 方法给出扫描结果,并且没有超时机制,所以此处不能用太复杂的扫描逻辑,不然会严重影响相关程序的执行速度。个人感觉可以先文本正则+二进制yara,并且自己实现超时机制。
如果有复杂的检测逻辑,也许可以先用正则和二进制进行检测,返回结果后客户端再进行复杂的检测,如果检出就上报服务器。如果这时还想阻断,可以考虑不借助 AMSI ,直接杀进程。
此外,前文分析 AMSI 实现时发现,AMSI 得到一个恶意结果后,就会退出循环不再调用其余提供者的扫描函数,如果 EDR 要集成 AMSI 的话,是不是把自己的顺序提到 windows definder 前面会更好?
0x01 实现dll
采用JSON协议进行跨语言RPC,将数据传输给 agent 。
主要代码逻辑如下:
代码还有很多优化的空间,如
- 引入错误处理及超时机制,以免在运行出错、超时的情况下影响 powershell 等程序的运行。
- 优化通信机制,使用更高效的传输方法。
0x02 实现 agent 接收数据
agent 接收数据比较简单,因为前面的数据就是使用的 go 的 net/rpc/jsonrpc 包规定的格式。
0x03 实现规则检测
对于普通的文本数据,使用正则表达式规则来检测,对于二进制数据,使用 YARA 规则来进行检测。(具体代码不贴了,简单的调用库罢了。)
对不同应用的待检测数据进行分析。
powershell
单条命令执行时
执行脚本文件时
告警时,对于得到的脚本文件路径,应该去获取脚本文件的创建、 修改时间、所属用户等信息,对于已经检测过的脚本,可以不再重发触发扫描。
WMI
执行命令产生的数据如下,可以用正则匹配,不过如果做成产品的话也许加入语法解析会更好。
WMIC 执行 cmd 命令
WMIC Process Call Create "cmd /c whoami"powershell 执行 cmd命令
