Skip to content

bad-antics/nullsec-fsharpsignal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 

Repository files navigation

NullSec FSharpSignal

Threat Signal Correlator written in F#

Version Language License

Part of the NullSec offensive security toolkit
Twitter: x.com/AnonAntics
Portal: bad-antics.github.io

Overview

FSharpSignal is a threat intelligence correlation engine that aggregates indicators of compromise (IOCs) and identifies attack patterns through functional programming paradigms. Built with F#'s discriminated unions, pattern matching, and immutable data structures.

F# Features Showcased

  • Discriminated Unions: Type-safe threat categories
  • Active Patterns: Custom pattern matching
  • Computation Expressions: Signal builder monad
  • Higher-Order Functions: Composable pipelines
  • Record Types: Immutable data structures
  • Pattern Matching: Exhaustive case handling
  • List Comprehensions: Functional collections
  • Type Inference: Clean, concise code

Correlation Rules

Rule Description Required Types MITRE
APT Campaign Multi-vector campaign detection IP, Domain, Hash TA0001
C2 Infrastructure Command & control patterns IP, Domain T1071
Lateral Movement Network traversal indicators IP, Process TA0008
Data Staging Exfiltration preparation Hash, Process, Registry T1074
Phishing Infrastructure Phishing campaign IOCs Domain, Email, URL T1566

Installation

# Clone
git clone https://github.com/bad-antics/nullsec-fsharpsignal.git
cd nullsec-fsharpsignal

# Build with .NET SDK
dotnet build

# Or compile directly
fsharpc FSharpSignal.fs -o fsharpsignal.exe

Usage

# Run demo mode
dotnet run

# Process IOC file
dotnet run -- -f indicators.json

# Enable verbose correlation
dotnet run -- -v -f indicators.json

Options

USAGE:
    fsharpsignal [OPTIONS]

OPTIONS:
    -h, --help       Show help
    -f, --file       IOC file to process
    -v, --verbose    Verbose output
    -r, --rules      Custom correlation rules

Sample Output

╔══════════════════════════════════════════════════════════════════╗
β•‘        NullSec FSharpSignal - Threat Signal Correlator           β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

[Demo Mode]

Loading threat intelligence indicators...

  Loaded 13 indicators

Running correlation engine...

  ╔═══════════════════════════════════════════════════════════════╗
  β•‘  CORRELATED SIGNAL: APT Campaign Detection                    β•‘
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
    
    Severity:     CRITICAL
    Score:        42.5/100
    MITRE ID:     TA0001
    Correlation:  2024-01-15 14:30:22 UTC
    
    Indicators:
      [HIGH] IP: 185.220.101.45
      [HIGH] Domain: update-service.duckdns.org
      [CRITICAL] Hash: 44d88612fea8a8f36de82e1278abb02f

  ╔═══════════════════════════════════════════════════════════════╗
  β•‘  CORRELATED SIGNAL: C2 Infrastructure                         β•‘
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
    
    Severity:     HIGH
    Score:        28.0/100
    MITRE ID:     T1071
    Correlation:  2024-01-15 14:30:22 UTC
    
    Indicators:
      [HIGH] IP: 185.220.101.45
      [HIGH] Domain: c2-beacon.no-ip.com

═══════════════════════════════════════════════════════════════════

  Summary:
    Total Signals:    4
    Critical:         1
    High:             2
    Medium:           1
    Combined Score:   112.5

Code Highlights

Discriminated Unions for Type Safety

type Severity =
    | Critical
    | High
    | Medium
    | Low
    | Informational

type IndicatorType =
    | IPAddress
    | Domain
    | FileHash
    | URL
    | Email
    | Registry
    | ProcessName
    | Mutex

Active Patterns for Custom Matching

let (|C2Domain|PhishingDomain|LegitDomain|) (domain: string) =
    let c2Patterns = [".onion"; ".bit"; "duckdns.org"; "no-ip.com"]
    let phishingKeywords = ["login"; "secure"; "verify"]
    let lowerDomain = domain.ToLowerInvariant()
    if c2Patterns |> List.exists (fun p -> lowerDomain.EndsWith(p)) then C2Domain
    elif phishingKeywords |> List.exists (fun k -> lowerDomain.Contains(k)) then PhishingDomain
    else LegitDomain

// Usage
let enrichDomain indicator =
    match indicator.Value with
    | C2Domain -> { indicator with Category = C2Infrastructure }
    | PhishingDomain -> { indicator with Category = Phishing }
    | LegitDomain -> indicator

Computation Expression (Signal Builder)

type SignalBuilder() =
    member _.Bind(x, f) = 
        match x with
        | Some value -> f value
        | None -> None
    member _.Return(x) = Some x
    member _.Zero() = None

let signal = SignalBuilder()

// Usage
let result = signal {
    let! indicator = findIndicator "185.220.101.45"
    let! enriched = enrichIndicator indicator
    return correlate enriched
}

Pipeline Composition

let correlate (indicators: Indicator list) =
    defaultRules
    |> List.map (fun rule -> matchRule rule indicators)
    |> List.choose (function
        | SignalFound signal -> Some signal
        | _ -> None)
    |> List.sortByDescending (fun s -> Severity.toInt s.AggregatedSeverity)

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               FSharpSignal Architecture                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                        β”‚
β”‚   β”‚  IOC Input       β”‚  (IP, Domain, Hash, URL, Email)        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚            β”‚                                                   β”‚
β”‚            β–Ό                                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                        β”‚
β”‚   β”‚  Type Inference  β”‚  Discriminated Unions                  β”‚
β”‚   β”‚  & Validation    β”‚  Active Patterns                       β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚            β”‚                                                   β”‚
β”‚            β–Ό                                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                        β”‚
β”‚   β”‚  Enrichment      β”‚  IP β†’ GeoIP, ASN                       β”‚
β”‚   β”‚  Pipeline        β”‚  Hash β†’ Malware DB                     β”‚
β”‚   β”‚  (List.map)      β”‚  Domain β†’ Classification               β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚            β”‚                                                   β”‚
β”‚            β–Ό                                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚           Correlation Engine                      β”‚        β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚        β”‚
β”‚   β”‚  β”‚ APT Rules   β”‚ β”‚ C2 Rules    β”‚ β”‚ Phish Rules β”‚ β”‚        β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚        β”‚
β”‚   β”‚                Pattern Matching                   β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                            β”‚                                   β”‚
β”‚                            β–Ό                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚
β”‚   β”‚  Result Type     β”‚    β”‚  Report          β”‚               β”‚
β”‚   β”‚  SignalFound     │───▢│  Generation      β”‚               β”‚
β”‚   β”‚  NoMatch         β”‚    β”‚                  β”‚               β”‚
β”‚   β”‚  InsufficientDataβ”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚                                                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why F#?

Requirement F# Advantage
Correctness Exhaustive pattern matching
Immutability Default immutable data
Composition Function pipelines
Type Safety Discriminated unions
Conciseness Type inference
.NET Ecosystem Full interoperability

License

MIT License - See LICENSE for details.

Related Tools

About

πŸ›‘οΈ Threat intelligence correlation engine with discriminated unions and active patterns - F#

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages