password
status
date
icon
category
tags
slug
summary
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命令
VSS
参考资料
- 作者:fatekey
- 链接:https://blog.fatekey.icu/article/AMSI2
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章