08. What the F#*%? by Chris Truncer and Joe Leon
Engineers explore architecture and security mechanisms for 08. What the F#*%? by Chris Truncer and Joe Leon.
Summary
## Overview
Chris Truncer and Joe Leon from Forty North Security present their exploration of F# as an offensive security tool, motivated by a December 2020 penetration test where traditional app whitelisting bypasses failed. Facing strong defensive controls (ATP, Bit9 app whitelisting), they discovered F# as a viable alternative to C# for establishing C2 communications and executing post-exploitation code, particularly by leveraging the Microsoft-signed FSI (F# Scripting Console).
## Key Topics
**F# Language Fundamentals**: F# is a functional-oriented, strongly-typed language designed for effective function writing. It automatically infers data types (similar to Python) and allows mixing .NET code. The speakers note that while F# syntax is considered difficult to learn and not intuitive for C#/PowerShell developers, it can be effectively weaponized for offensive purposes.
**FSI (F# Scripting Console) as a Bypass**: The F# scripting console, a Microsoft-signed binary, bypassed Bit9 app whitelisting where traditional methods (MSBuild, gadgets-to-JSScript, WimMc, Ghost loader) failed. They identified four required DLL dependencies (fsharp.compiler.interactive.settings, fsharp.compiler.private, fsharpcore, microsoft.build.utilities.core) and successfully executed shellcode injection templates, establishing C2 after four hours of testing.
**Execute Assembly with F#**: Extending the execute assembly concept (unmanaged code loading managed code via CLR), the speakers explored loading F# assemblies in-memory. They encountered invoke-3 errors and fsharpcore.dll dependency issues, testing four solutions: standalone assemblies (too large at 1.5+ MB), dropping DLLs to disk, global assembly cache installation (requires admin), and dynamic dependency resolution.
## Technical Details
**AppDomain.AssemblyResolve Solution**: The breakthrough came through Jean Maes' research on AppDomain.AssemblyResolve—a callback function that fires when the CLR cannot locate an assembly. The speakers embedded fsharpcore.dll bytes directly in code and modified the open-source "hosting CLR" C++ project to dynamically resolve dependencies without disk drops or elevated privileges. This approach completely eliminated dependency resolution errors and enabled true in-memory F# execution.
**Compilation Methods**: FSI.exe location varies by installation path (Program Files/x86/Visual Studio/.../F#/ or .NET SDK 5.0.103 folder). The --standalone flag theoretically embeds dependencies but generates 1.5+ MB binaries and doesn't actually create standalone executables as documented; it produces a loader executable plus separate DLL. This remains a noted limitation.
**Shellcode Injection Templates**: Released templates include basic shellcode injection (Vincent Yiu's original 2018 template), remote process injection via CreateRemoteThread, and QueueUserAPC variants. PInvoke (Platform Invoke) enables Win32 API calls; F# byte array syntax differs significantly from C# (0xhex format with "uy" suffix), but functionality remains compatible.
**Defensive Detection**: Matt Graber and Red Canary identified that AMSI can catch embedded F# applications, .NET ETW captures fsharpcore loading, and focus should be on behavioral indicators of .NET execution rather than language specifics. AMSI and ETW bypass techniques (referenced via mdsec blogs and tools like amzeefail.com) remain applicable to F# code.
## Takeaways
F# presents a viable, relatively underfocused offensive alternative to C# due to limited prior adoption in adversary tooling. The AppDomain.AssemblyResolve approach elegantly solves dependency issues, enabling in-memory execution via execute assembly techniques in frameworks like Cobalt Strike. The speakers released a GitHub repository ("What the F") containing modified hosting CLR code, shellcode templates, and execution guides. Future priorities include Beacon Object File (BOF) implementation for seamless Cobalt Strike integration, syscall integration to bypass API hooking, and porting existing C# tools to F#. Defenders should instrument .NET execution telemetry (AMSI/ETW) to detect behavioral indicators rather than language-specific artifacts.
Related talks
BSidesAugusta·49 min
Security researchers investigate 2014 Chris Truncer and analyze defensive countermeasures.
x33fcon·41 min
Security Performance Engineering
Security Performance Engineering details 10. Chris Nickerson.
BSidesAugusta·1 hr 35 min
Offensive WMI Workshop explores Chris Truncer.


