Scanner Module

The scanner is the core analysis engine. It receives scan requests (via named pipe or manual input), queues them, and processes them through a multi-stage pipeline: PE parsing โ†’ feature extraction โ†’ classification โ†’ policy enforcement.

Related: Monitor Module ยท PE Parser Module ยท ML Classifier ยท Policy Engine ยท Scan Pipeline Flow


1. Source Files

File Purpose
scanner/scanner.cpp Entry point (wmain), worker thread, pipe server, single-scan mode
scanner/scanner_api.h Public API: InitializeScanner, SubmitScanRequest, ShutdownScanner
scanner/queue.cpp/h Thread-safe bounded scan queue

2. Module Architecture

flowchart TB
    subgraph Scanner["Scanner.exe"]
        direction TB
        
        subgraph Entry["Entry Point (wmain)"]
            Init["InitializeScanner()"]
            Mode{"Select Mode?"}
            Full["Mode 1: RunPipeServer()\n(blocking)"]
            Single["Mode 2: RunSingleFileScan()\n(interactive)"]
            Shut["ShutdownScanner()"]
        end

        subgraph QueueSys["Queue System"]
            Q["std::queue<SCAN_REQUEST>\n(max 10,000)"]
            Mtx["std::mutex"]
            Evt["Win32 Event\n(auto-reset)"]
            Enq["Enqueue()"]
            Deq["Dequeue()"]
        end

        subgraph Worker["ScanWorker Thread"]
            WLoop["Dequeue loop"]
            Norm["NormalizePath()"]
            Valid["Validate file"]
            Parse["SafeParsePE_SEH()"]
            Feat["ExtractFeatures()"]
            Class["Classify()"]
            Policy["ApplyPolicy()"]
        end

        Init --> Mode
        Mode -->|1| Full
        Mode -->|2| Single
        Full --> Enq
        Single --> Enq
        Enq --> Q
        Q --> Deq --> WLoop
        WLoop --> Norm --> Valid --> Parse --> Feat --> Class --> Policy
    end

    style Entry fill:#3a0ca3,color:#fff
    style QueueSys fill:#e07a5f,color:#fff
    style Worker fill:#2d6a4f,color:#fff

3. Scan Modes

Mode 1: Full System Scan (Pipe Server)

sequenceDiagram
    participant M as Monitor
    participant P as Named Pipe
    participant S as Scanner.wmain

    S->>P: CreateNamedPipe("\\.\pipe\ScannerPipe")
    S->>P: ConnectNamedPipe() โ€” blocks
    
    M->>P: CreateFile() โ€” connects
    P-->>S: Client connected
    
    loop Until disconnect
        M->>P: WriteFile(SCAN_REQUEST)
        P->>S: ReadFile(&req)
        S->>S: SubmitScanRequest(&req)
    end
    
    Note over S: ReadFile returns FALSE
    S->>S: CloseHandle(hPipe)

Pipe configuration:

  • Name: \\.\pipe\ScannerPipe
  • Access: PIPE_ACCESS_DUPLEX
  • Mode: PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT
  • Instances: 1
  • Buffer: 1024 bytes each direction

Mode 2: Single File Scan (Interactive)

flowchart TD
    Start["RunSingleFileScan()"]
    Start --> Prompt["Print prompt '> '"]
    Prompt --> Read["fgetws(path)"]
    Read --> Empty{"Empty input?"}
    Empty -->|Yes| Exit["Exit scan mode"]
    Empty -->|No| Build["Build SCAN_REQUEST\n(filePath = input)"]
    Build --> Submit["SubmitScanRequest(&req)"]
    Submit --> Sleep["Sleep(100ms)\n(let worker process)"]
    Sleep --> Prompt

    style Exit fill:#6c757d,color:#fff

4. Worker Thread (ScanWorker)

The ScanWorker is a dedicated thread created by InitializeScanner() that runs for the lifetime of the process.

flowchart TD
    Start["ScanWorker started"]
    Start --> Loop["while (g_Running)"]
    
    Loop --> TryDeq["Dequeue(&req)"]
    TryDeq --> Got{"Success?"}
    Got -->|No| Wait["WaitForQueueSignal()\n(500ms timeout)"]
    Wait --> Loop
    
    Got -->|Yes| Norm["NormalizePath(req.filePath)"]
    Norm --> NormOK{"Normalized?"}
    NormOK -->|No| Loop
    
    NormOK -->|Yes| Attrs["GetFileAttributesW()"]
    Attrs --> AttrCheck{"Valid file?\nNot directory?"}
    AttrCheck -->|No| Loop
    
    AttrCheck -->|Yes| SelfCheck{"Is Scanner.exe or\nFsMinifilterMonitor.exe?"}
    SelfCheck -->|Yes| Loop
    
    SelfCheck -->|No| Parse["SafeParsePE_SEH()"]
    Parse --> ParseOK{"Parsed?"}
    ParseOK -->|No| Loop
    
    ParseOK -->|Yes| Extract["ExtractFeatures()"]
    Extract --> Classify["Classify()"]
    Classify --> Apply["ApplyPolicy()"]
    Apply --> Loop

    style Parse fill:#4361ee,color:#fff
    style Classify fill:#e07a5f,color:#fff
    style Apply fill:#2d6a4f,color:#fff

5. Queue System

Thread-Safe Queue Implementation

Component Type Purpose
g_Queue std::queue<SCAN_REQUEST> FIFO request buffer
g_Mutex std::mutex Mutual exclusion for queue access
g_QueueEvent HANDLE (Win32 auto-reset event) Signal worker thread when items are enqueued
MAX_QUEUE_SIZE 10,000 Backpressure limit

API

Function Description
InitializeQueue() Creates the auto-reset event
Enqueue(const SCAN_REQUEST*) Adds request; drops oldest if at capacity
Dequeue(SCAN_REQUEST*) Removes front item; returns FALSE if empty
WaitForQueueSignal() Blocks up to 500ms on g_QueueEvent
DestroyQueue() Drains queue, closes event handle

Backpressure Strategy

flowchart LR
    New["New Request"] --> Lock["Lock mutex"]
    Lock --> Check{"size >= 10,000?"}
    Check -->|Yes| Drop["Pop oldest\n(tail-drop)"]
    Check -->|No| Push["Push back"]
    Drop --> Push
    Push --> Signal["SetEvent"]
    Signal --> Unlock["Unlock mutex"]

6. Lifecycle Management

sequenceDiagram
    participant Main as wmain()
    participant Init as InitializeScanner()
    participant Q as Queue
    participant W as ScanWorker
    participant Shut as ShutdownScanner()

    Main->>Init: InitializeScanner()
    Init->>Q: InitializeQueue()
    Note over Q: Creates auto-reset event
    Init->>W: CreateThread(ScanWorker)
    Note over W: Worker starts dequeue loop

    Main->>Main: RunPipeServer() or RunSingleFileScan()
    Note over Main: Blocks until done

    Main->>Shut: ShutdownScanner()
    Shut->>Shut: g_Running = FALSE
    Shut->>W: WaitForSingleObject(INFINITE)
    Note over W: Worker exits loop
    Shut->>W: CloseHandle(g_WorkerThread)
    Shut->>Q: DestroyQueue()

7. Global State

Variable Type Scope Lifetime
g_WorkerThread HANDLE scanner.cpp (static) InitializeScanner โ†’ ShutdownScanner
g_Running volatile BOOL scanner.cpp (static) Set FALSE during shutdown
g_Queue std::queue queue.cpp (static) InitializeQueue โ†’ DestroyQueue
g_Mutex std::mutex queue.cpp (static) Process lifetime
g_QueueEvent HANDLE queue.cpp (static) InitializeQueue โ†’ DestroyQueue

Next Steps