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

 

参考资料

 
AMSI研究(3) - 绕过及检测 AMSI研究(1) - 基础
公告
password
status
date
icon
category
tags
slug
summary
年轻时,你的潜力是无限的。说实在的,任何事都有可能做成。你可以成为爱因斯坦,也可以成为迪马吉奥。直到某一天,你身上的可能性消失殆尽,你没能成为爱因斯坦,你只是一个无名之辈。那真是糟糕的时刻。
🔮
所谓魔法不过是我们尚未了解的科学。
📚
潜心学习,低调发展。