Skip to main content

Overview

Scan4all provides a powerful and extensible scanning engine that allows you to create custom scan modules. The engine uses an event-driven architecture with a worker pool for efficient concurrent scanning.

Engine Architecture

The scan4all engine is built on several core components:

Engine Structure

The main engine object is defined in engine/engineImp.go:18:
type Engine struct {
    Context      *context.Context       // Execution context
    Wg           *sync.WaitGroup        // Wait group for goroutines
    Pool         int                    // Thread pool size
    PoolFunc     *ants.PoolWithFunc     // Worker pool function
    EventData    chan *models.EventData // Event data queue
    caseScanFunc sync.Map               // Registered scan functions
}

Key Features

  • Event-driven architecture: All scans are triggered through events
  • Worker pool: Uses ants for efficient goroutine management (default: 5000 workers)
  • Concurrent execution: Each scan module runs independently
  • Built-in deduplication: Prevents redundant scans of the same target

Creating a Custom Scan Module

Step 1: Register Your Scan Function

To create a custom scan module, you need to register it with the engine using the factory pattern:
import (
    "github.com/GhostTroops/scan4all/lib/goSqlite_gorm/lib/scan/Const"
    "github.com/GhostTroops/scan4all/lib/goSqlite_gorm/pkg/models"
    "github.com/GhostTroops/scan4all/lib/util"
)

func init() {
    util.RegInitFunc(func() {
        // Register your scan function with a unique scan type
        util.EngineFuncFactory(Const.ScanType_YourModule, func(evt *models.EventData, args ...interface{}) {
            // Your scan logic here
            performCustomScan(evt)
        })
    })
}

Step 2: Implement Your Scan Logic

Create your scanning function that processes the event data:
func performCustomScan(evt *models.EventData) {
    // Get the target URL from the event
    targetURL := evt.Task.ScanWeb
    
    // Perform your custom scanning logic
    results := doYourScan(targetURL)
    
    // Send results back to the engine
    util.SendEngineLog(evt, Const.ScanType_YourModule, results)
}

func doYourScan(url string) []string {
    var findings []string
    
    // Your custom scan implementation
    // Example: Check for specific vulnerabilities
    if checkVulnerability(url) {
        findings = append(findings, "vulnerability-found")
    }
    
    return findings
}

Step 3: Trigger Additional Scans

You can trigger other scan modules as part of your scan flow:
func performCustomScan(evt *models.EventData) {
    // Perform your scan
    results := doYourScan(evt.Task.ScanWeb)
    
    // Trigger additional scan types
    util.SendEvent(evt, Const.ScanType_Nmap, Const.ScanType_WebScan)
    
    // Send your results
    util.SendEngineLog(evt, Const.ScanType_YourModule, results)
}

Available Scan Types

The following scan types are commonly used:
  • ScanType_GoPoc - Go-based POC scanning
  • ScanType_Nmap - Nmap port scanning
  • ScanType_Masscan - Masscan port scanning
  • ScanType_WebScan - Web vulnerability scanning

Preventing Duplicate Scans

Use the built-in deduplication mechanism:
import "github.com/GhostTroops/scan4all/lib/util"

func performCustomScan(evt *models.EventData) {
    url := evt.Task.ScanWeb
    host := getHost(url)
    
    // Check if this target has already been scanned
    if util.TestRepeat([]string{"custom-scan"}, host, url) {
        return // Skip if already scanned
    }
    
    // Proceed with scan
    // ...
}

Configuration and Options

Access global configuration options:
// Get configuration values
poolSize := util.GetValAsInt("ScanPoolSize", 5000)
enablePOC := util.GetValAsBool("NoPOC")
outputFile := util.Output

// Set environment variables
os.Setenv("noScan", "true")

Sending Results

There are multiple ways to send results:

Basic Result Logging

util.SendEngineLog(evt, scanType, results)

Structured Result with Metadata

util.SendEngineLog4Url(
    url,
    Const.ScanType_YourModule,
    &map[string]interface{}{
        "Urls":         []string{originalURL, finalURL},
        "findings":     findings,
        "severity":     "high",
    },
    util.Scan4all,
)

Best Practices

The engine manages a worker pool automatically. Avoid creating additional goroutines unnecessarily.
Always handle errors gracefully and log them appropriately:
if err != nil {
    log.Printf("Error in custom scan: %v", err)
    return
}
Use the built-in rate limiting mechanisms:
util.DoSyncFunc(func() {
    // Rate-limited operation
    performScan(target)
})
Always clean up resources and handle context cancellation:
select {
case <-util.Ctx_global.Done():
    // Context cancelled, clean up and return
    return
default:
    // Continue processing
}

Example: Complete Custom Module

Here’s a complete example of a custom scan module:
package customscan

import (
    "fmt"
    "log"
    "github.com/GhostTroops/scan4all/lib/goSqlite_gorm/lib/scan/Const"
    "github.com/GhostTroops/scan4all/lib/goSqlite_gorm/pkg/models"
    "github.com/GhostTroops/scan4all/lib/util"
)

const ScanType_Custom = 100 // Choose a unique ID

func init() {
    util.RegInitFunc(func() {
        util.EngineFuncFactory(ScanType_Custom, CustomScanHandler)
    })
}

func CustomScanHandler(evt *models.EventData, args ...interface{}) {
    url := evt.Task.ScanWeb
    
    // Prevent duplicate scans
    if util.TestRepeat([]string{"custom"}, url, url) {
        return
    }
    
    // Perform the scan
    results := performScan(url)
    
    // Send results
    if len(results) > 0 {
        util.SendEngineLog(evt, ScanType_Custom, results)
    }
}

func performScan(url string) []string {
    var findings []string
    
    // Your scan logic here
    log.Printf("Scanning %s with custom module", url)
    
    // Example: detect specific patterns
    if detectPattern(url) {
        findings = append(findings, fmt.Sprintf("custom-finding|%s", url))
    }
    
    return findings
}

func detectPattern(url string) bool {
    // Implement your detection logic
    return false
}

Next Steps

Custom POCs

Learn how to write custom Proof-of-Concept exploits

API Integration

Integrate scan4all into your applications

Build docs developers (and LLMs) love