Skip to content

Intrusion Detection System.#

A simple and basic intrusion detection system is a more advanced one known as trip wire, which monitors log files for suspicious activities. In this example, I have created a simple host-based intrusion detection system (HIDS) that monitors a sample log file. It raises an alert if it detects multiple failed login attempts from a specific IP address within a given time frame.

This system has been implemented in nine different programming languages to demonstrate the variations in the amount of code required to achieve such a simple task or program. It also serves as a good learning curve for experimentation.

  1. Python
  2. Go
  3. C
  4. C++
  5. C#
  6. Rust
  7. Pearl
  8. Ruby
  9. JavaScript

Python#

A simple and basic intrusion detection system using - Python
  1. First, create a sample log file (sample_log.txt) with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
  1. A Python script for the intrusion detection system intrusion_detection.py

import time

def read_log_file(log_file):
    with open(log_file, 'r') as file:
        return file.readlines()

def detect_intrusion(log_entries, max_attempts=3, time_window=60):
    ip_attempts = {}
    for entry in log_entries:
        parts = entry.split()
        if len(parts) >= 5 and parts[-2] == 'failed' and parts[-1] == 'attempt':
            timestamp, _, ip_address, _ = parts[:4]
            timestamp = time.mktime(time.strptime(timestamp, '%Y-%m-%d %H:%M:%S'))
            if ip_address in ip_attempts:
                if timestamp - ip_attempts[ip_address][-1] <= time_window:
                    ip_attempts[ip_address].append(timestamp)
                    if len(ip_attempts[ip_address]) >= max_attempts:
                        return True, ip_address
                else:
                    ip_attempts[ip_address] = [timestamp]
            else:
                ip_attempts[ip_address] = [timestamp]
    return False, None

if __name__ == "__main__":
    log_file = "sample_log.txt"
    log_entries = read_log_file(log_file)
    intrusion_detected, suspicious_ip = detect_intrusion(log_entries)

    if intrusion_detected:
        print(f"Intrusion detected from {suspicious_ip}.")
    else:
        print("No intrusion detected.")
Run the script, and it will analyze the sample_log.txt file to check if there are three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.

Go#

A simple and basic intrusion detection system using - Go
  1. First, create a sample log file sample_log.txt with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
  1. Go script for the intrusion detection system intrusion_detection.go

    package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "time"
)

func readLogFile(logFile string) ([]string, error) {
    file, err := os.Open(logFile)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    var logEntries []string
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        logEntries = append(logEntries, scanner.Text())
    }
    return logEntries, scanner.Err()
}

func detectIntrusion(logEntries []string, maxAttempts int, timeWindow time.Duration) (bool, string) {
    ipAttempts := make(map[string][]time.Time)

    for _, entry := range logEntries {
        parts := strings.Fields(entry)
        if len(parts) >= 5 && parts[3] == "failed" && parts[4] == "login" && parts[5] == "attempt" {
            timestampStr := parts[0] + " " + parts[1]
            timestamp, err := time.Parse("2006-01-02 15:04:05", timestampStr)
            if err != nil {
                continue
            }

            ipAddress := parts[2]
            if attempts, ok := ipAttempts[ipAddress]; ok {
                if time.Since(attempts[len(attempts)-1]) <= timeWindow {
                    ipAttempts[ipAddress] = append(ipAttempts[ipAddress], timestamp)
                    if len(ipAttempts[ipAddress]) >= maxAttempts {
                        return true, ipAddress
                    }
                } else {
                    ipAttempts[ipAddress] = []time.Time{timestamp}
                }
            } else {
                ipAttempts[ipAddress] = []time.Time{timestamp}
            }
        }
    }

    return false, ""
}

func main() {
    logFile := "sample_log.txt"
    logEntries, err := readLogFile(logFile)
    if err != nil {
        fmt.Println("Error reading log file:", err)
        return
    }

    intrusionDetected, suspiciousIP := detectIntrusion(logEntries, 3, 60*time.Second)

    if intrusionDetected {
        fmt.Printf("Intrusion detected from %s.\n", suspiciousIP)
    } else {
        fmt.Println("No intrusion detected.")
    }
}
To run the Go script, make sure you have Go installed on your system. Save the script in a file named intrusion_detection.go and then execute the following command in the terminal:

go run intrusion_detection.go

Run the script, and it will analyze the sample_log.txt file to check if there are three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.

C#

A simple and basic intrusion detection system using - C
  1. Create a sample log file sample_log.txt with entries like the following:

2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
1. Now, let's create the C program for the intrusion detection system intrusion_detection.c

#include <stdio.h>
#include <string.h>
#include <time.h>

#define MAX_LOG_ENTRIES 1000

typedef struct {
    char timestamp[20];
    char ip_address[16];
    char action[20];
} LogEntry;

int readLogFile(const char *logFile, LogEntry logEntries[MAX_LOG_ENTRIES]) {
    FILE *file = fopen(logFile, "r");
    if (file == NULL) {
        printf("Error opening log file.\n");
        return -1;
    }

    int numEntries = 0;
    while (numEntries < MAX_LOG_ENTRIES && fscanf(file, "%19s %15s %19s", logEntries[numEntries].timestamp,
                                                logEntries[numEntries].ip_address,
                                                logEntries[numEntries].action) == 3) {
        numEntries++;
    }

    fclose(file);
    return numEntries;
}

int detectIntrusion(LogEntry logEntries[MAX_LOG_ENTRIES], int numEntries, int maxAttempts, int timeWindow) {
    struct tm timestamp1, timestamp2;

    for (int i = 0; i < numEntries; i++) {
        if (strcmp(logEntries[i].action, "failed") == 0 &&
            strcmp(logEntries[i].ip_address, "login") == 0 &&
            strcmp(logEntries[i].action, "attempt") == 0) {

            strptime(logEntries[i].timestamp, "%Y-%m-%d %H:%M:%S", &timestamp1);
            time_t t1 = mktime(&timestamp1);

            int attempts = 1;
            for (int j = i + 1; j < numEntries; j++) {
                if (strcmp(logEntries[j].ip_address, logEntries[i].ip_address) == 0) {
                    strptime(logEntries[j].timestamp, "%Y-%m-%d %H:%M:%S", &timestamp2);
                    time_t t2 = mktime(&timestamp2);

                    if (t2 - t1 <= timeWindow) {
                        attempts++;
                        if (attempts >= maxAttempts) {
                            return 1; // Intrusion detected
                        }
                    } else {
                        break;
                    }
                }
            }
        }
    }

    return 0; // No intrusion detected
}

int main() {
    const char *logFile = "sample_log.txt";
    LogEntry logEntries[MAX_LOG_ENTRIES];

    int numEntries = readLogFile(logFile, logEntries);
    if (numEntries == -1) {
        return 1;
    }

    int intrusionDetected = detectIntrusion(logEntries, numEntries, 3, 60);

    if (intrusionDetected) {
        printf("Intrusion detected.\n");
    } else {
        printf("No intrusion detected.\n");
    }

    return 0;
}
  1. To compile and run the C program, make sure you have a C compiler installed (e.g., GCC). Save the program in a file named intrusion_detection.c, and then execute the following command in the terminal:
gcc -o intrusion_detection intrusion_detection.c
./intrusion_detection

The C program will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert stating "Intrusion detected."

C++#

A simple and basic intrusion detection system using - C++
  1. Create a sample log file sample_log.txt with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
  1. Now, let's create the C++ program for the intrusion detection system (main.cpp)
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <ctime>
#include <chrono>

struct LogEntry {
    std::string timestamp;
    std::string ip_address;
    std::string action;
};

std::vector<LogEntry> readLogFile(const std::string& logFile) {
    std::ifstream file(logFile);
    std::vector<LogEntry> logEntries;
    std::string line;

    while (std::getline(file, line)) {
        std::istringstream iss(line);
        LogEntry entry;
        iss >> entry.timestamp >> entry.ip_address >> entry.action;
        logEntries.push_back(entry);
    }

    return logEntries;
}

bool detectIntrusion(const std::vector<LogEntry>& logEntries, int maxAttempts, int timeWindow) {
    std::map<std::string, std::vector<time_t>> ipAttempts;

    for (const auto& entry : logEntries) {
        if (entry.action == "failed" && entry.ip_address == "login" && entry.action == "attempt") {
            struct tm timeinfo;
            strptime(entry.timestamp.c_str(), "%Y-%m-%d %H:%M:%S", &timeinfo);
            time_t timestamp = mktime(&timeinfo);

            if (ipAttempts.find(entry.ip_address) != ipAttempts.end()) {
                auto& attempts = ipAttempts[entry.ip_address];
                if (difftime(timestamp, attempts.back()) <= timeWindow) {
                    attempts.push_back(timestamp);
                    if (attempts.size() >= maxAttempts) {
                        return true; // Intrusion detected
                    }
                } else {
                    attempts = { timestamp };
                }
            } else {
                ipAttempts[entry.ip_address] = { timestamp };
            }
        }
    }

    return false; // No intrusion detected
}

int main() {
    const std::string logFile = "sample_log.txt";
    std::vector<LogEntry> logEntries = readLogFile(logFile);
    bool intrusionDetected = detectIntrusion(logEntries, 3, 60);

    if (intrusionDetected) {
        std::cout << "Intrusion detected." << std::endl;
    } else {
        std::cout << "No intrusion detected." << std::endl;
    }

    return 0;
}
  1. To compile and run the C++ program, save the C++ code in a file named main.cpp, and then execute the following commands in the terminal:
g++ -o intrusion_detection main.cpp
./intrusion_detection

The C++ program will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert stating "Intrusion detected."

C##

A simple and basic intrusion detection system using - C#
  1. First, create a sample log file (sample_log.txt) with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
  1. Now, let's create the C# program for the intrusion detection system (Program.cs):
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;

namespace IntrusionDetection
{
    class Program
    {
        static List<string> ReadLogFile(string logFile)
        {
            return new List<string>(File.ReadAllLines(logFile));
        }

        static (bool, string) DetectIntrusion(List<string> logEntries, int maxAttempts, int timeWindow)
        {
            var ipAttempts = new Dictionary<string, List<DateTime>>();

            foreach (var entry in logEntries)
            {
                var parts = entry.Split(' ');
                if (parts.Length >= 6 && parts[3] == "failed" && parts[4] == "login" && parts[5] == "attempt")
                {
                    var timestampStr = parts[0] + " " + parts[1];
                    var timestamp = DateTime.ParseExact(timestampStr, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);

                    var ipAddress = parts[2];
                    if (ipAttempts.TryGetValue(ipAddress, out var attempts))
                    {
                        if (DateTime.Now.Subtract(attempts[attempts.Count - 1]).TotalSeconds <= timeWindow)
                        {
                            attempts.Add(timestamp);
                            if (attempts.Count >= maxAttempts)
                            {
                                return (true, ipAddress); // Intrusion detected
                            }
                        }
                        else
                        {
                            ipAttempts[ipAddress] = new List<DateTime> { timestamp };
                        }
                    }
                    else
                    {
                        ipAttempts[ipAddress] = new List<DateTime> { timestamp };
                    }
                }
            }

            return (false, ""); // No intrusion detected
        }

        static void Main(string[] args)
        {
            var logFile = "sample_log.txt";
            var logEntries = ReadLogFile(logFile);
            var (intrusionDetected, suspiciousIp) = DetectIntrusion(logEntries, 3, 60);

            if (intrusionDetected)
            {
                Console.WriteLine($"Intrusion detected from {suspiciousIp}.");
            }
            else
            {
                Console.WriteLine("No intrusion detected.");
            }
        }
    }
}
  1. To run the C# program, you'll need to have the .NET SDK installed. Save the C# code in a file named Program.cs, and then execute the following command in the terminal:
dotnet run

The C# program will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.

Rust#

A simple and basic intrusion detection system using - Rust
  1. Create a sample log file sample_log.txt with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
  1. Now, let's create the Rust program for the intrusion detection system (main.rs):
    use std::fs::File;
    use std::io::{self, BufRead};
    use std::time::{SystemTime, Duration};
    use chrono::{NaiveDateTime, Timelike};

    fn read_log_file(log_file: &str) -> io::Result<Vec<String>> {
        let file = File::open(log_file)?;
        let reader = io::BufReader::new(file);
        reader.lines().collect()
    }

    fn detect_intrusion(log_entries: Vec<String>, max_attempts: usize, time_window: Duration) -> (bool, String) {
        let mut ip_attempts: std::collections::HashMap<String, Vec<SystemTime>> = std::collections::HashMap::new();

        for entry in log_entries {
            let parts: Vec<&str> = entry.split_whitespace().collect();
            if parts.len() >= 6 && parts[3] == "failed" && parts[4] == "login" && parts[5] == "attempt" {
                let timestamp_str = parts[0].to_owned() + " " + parts[1];
                let timestamp = NaiveDateTime::parse_from_str(&timestamp_str, "%Y-%m-%d %H:%M:%S").unwrap();
                let timestamp = SystemTime::from(timestamp);

                let ip_address = parts[2].to_owned();
                if let Some(attempts) = ip_attempts.get_mut(&ip_address) {
                    if let Some(last_attempt) = attempts.last() {
                        if timestamp.duration_since(*last_attempt).unwrap() <= time_window {
                            attempts.push(timestamp);
                            if attempts.len() >= max_attempts {
                                return (true, ip_address); // Intrusion detected
                            }
                        } else {
                            *attempts = vec![timestamp];
                        }
                    }
                } else {
                    ip_attempts.insert(ip_address, vec![timestamp]);
                }
            }
        }

        (false, String::new()) // No intrusion detected
    }

    fn main() {
        let log_file = "sample_log.txt";
        let log_entries = read_log_file(log_file).expect("Error reading log file.");
        let (intrusion_detected, suspicious_ip) = detect_intrusion(log_entries, 3, Duration::from_secs(60));

        if intrusion_detected {
            println!("Intrusion detected from {}.", suspicious_ip);
        } else {
            println!("No intrusion detected.");
        }
    }
  1. To run the Rust program, you'll need to have the Rust programming language installed. Save the Rust code in a file named main.rs, and then execute the following command in the terminal:
cargo run

The Rust program will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.

Perl#

A simple and basic intrusion detection system using - Perl
  1. Create a sample log file sample_log.txt with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
  1. Create the Perl script for the intrusion detection system intrusion_detection.pl
#!/usr/bin/perl

use strict;
use warnings;
use Time::Piece;
use Time::Seconds;

sub read_log_file {
    my ($log_file) = @_;
    open(my $fh, '<', $log_file) or die "Error opening log file: $!";
    my @log_entries = <$fh>;
    close($fh);
    return @log_entries;
}

sub detect_intrusion {
    my ($log_entries_ref, $max_attempts, $time_window) = @_;
    my %ip_attempts;

    foreach my $entry (@$log_entries_ref) {
        my @parts = split(' ', $entry);
        next unless @parts >= 6 && $parts[3] eq 'failed' && $parts[4] eq 'login' && $parts[5] eq 'attempt';

        my $timestamp_str = $parts[0] . ' ' . $parts[1];
        my $timestamp = Time::Piece->strptime($timestamp_str, '%Y-%m-%d %H:%M:%S');

        my $ip_address = $parts[2];
        if (exists $ip_attempts{$ip_address}) {
            if ($timestamp - $ip_attempts{$ip_address}[-1] <= $time_window) {
                push @{$ip_attempts{$ip_address}}, $timestamp;
                if (@{$ip_attempts{$ip_address}} >= $max_attempts) {
                    return 1, $ip_address; # Intrusion detected
                }
            } else {
                $ip_attempts{$ip_address} = [$timestamp];
            }
        } else {
            $ip_attempts{$ip_address} = [$timestamp];
        }
    }

    return 0, ''; # No intrusion detected
}

sub main {
    my $log_file = 'sample_log.txt';
    my @log_entries = read_log_file($log_file);
    my ($intrusion_detected, $suspicious_ip) = detect_intrusion(\@log_entries, 3, 60);

    if ($intrusion_detected) {
        print "Intrusion detected from $suspicious_ip.\n";
    } else {
        print "No intrusion detected.\n";
    }
}

main();
  1. To run the Perl script, make sure you have Perl installed on your system. Save the script in a file named intrusion_detection.pl, and then execute the following command in the terminal:
perl intrusion_detection.pl

The Perl script will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.

Ruby#

A simple and basic intrusion detection system using - Ruby
  1. First, create a sample log file (sample_log.txt) with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
  1. Create the Ruby script for the intrusion detection system intrusion_detection.rb
require 'time'

def read_log_file(log_file)
File.readlines(log_file)
end

def detect_intrusion(log_entries, max_attempts, time_window)
ip_attempts = {}

log_entries.each do |entry|
    parts = entry.split
    next unless parts.length >= 6 && parts[3] == 'failed' && parts[4] == 'login' && parts[5] == 'attempt'

    timestamp_str = parts[0] + ' ' + parts[1]
    timestamp = Time.parse(timestamp_str)

    ip_address = parts[2]
    if ip_attempts.key?(ip_address)
    if timestamp - ip_attempts[ip_address].last <= time_window
        ip_attempts[ip_address] << timestamp
        if ip_attempts[ip_address].length >= max_attempts
        return true, ip_address # Intrusion detected
        end
    else
        ip_attempts[ip_address] = [timestamp]
    end
    else
    ip_attempts[ip_address] = [timestamp]
    end
end

return false, '' # No intrusion detected
end

def main
log_file = 'sample_log.txt'
log_entries = read_log_file(log_file)
intrusion_detected, suspicious_ip = detect_intrusion(log_entries, 3, 60)

if intrusion_detected
    puts "Intrusion detected from #{suspicious_ip}."
else
    puts "No intrusion detected."
end
end

main
  1. To run the Ruby script, make sure you have Ruby installed on your system. Save the script in a file named intrusion_detection.rb, and then execute the following command in the terminal:
ruby intrusion_detection.rb

The Ruby script will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.

JavaScript#

A simple and basic intrusion detection system using - JavaScript
  1. Create a sample log file sample_log.txt with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
  1. Create the JavaScript code for the intrusion detection system:
const fs = require('fs');
const moment = require('moment');

function readLogFile(logFile) {
return fs.readFileSync(logFile, 'utf8').split('\n');
}

function detectIntrusion(logEntries, maxAttempts, timeWindow) {
const ipAttempts = {};

logEntries.forEach(entry => {
    const parts = entry.split(' ');
    if (parts.length >= 6 && parts[3] === 'failed' && parts[4] === 'login' && parts[5] === 'attempt') {
    const timestampStr = parts[0] + ' ' + parts[1];
    const timestamp = moment(timestampStr, 'YYYY-MM-DD HH:mm:ss');

    const ipAddress = parts[2];
    if (ipAttempts[ipAddress]) {
        if (moment().diff(ipAttempts[ipAddress][ipAttempts[ipAddress].length - 1], 'seconds') <= timeWindow) {
        ipAttempts[ipAddress].push(timestamp);
        if (ipAttempts[ipAddress].length >= maxAttempts) {
            return { intrusionDetected: true, suspiciousIp: ipAddress };
        }
        } else {
        ipAttempts[ipAddress] = [timestamp];
        }
    } else {
        ipAttempts[ipAddress] = [timestamp];
    }
    }
});

return { intrusionDetected: false, suspiciousIp: '' };
}

function main() {
const logFile = 'sample_log.txt';
const logEntries = readLogFile(logFile);
const { intrusionDetected, suspiciousIp } = detectIntrusion(logEntries, 3, 60);

if (intrusionDetected) {
    console.log(`Intrusion detected from ${suspiciousIp}.`);
} else {
    console.log('No intrusion detected.');
}
}

main();
  1. Before running the JavaScript code, you'll need to install the 'moment' library, which is used for handling dates and times. You can install it via npm:
npm install moment
  1. Then, save the JavaScript code in a file named intrusion_detection.js, and execute the following command in the terminal:
node intrusion_detection.js

The JavaScript code will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.

Note

Remember that this is a basic example, and a real-world intrusion detection system requires more sophisticated techniques and continuous monitoring of various system logs, network traffic, and user behaviors. Additionally, a production-grade system would have to consider factors like scalability, real-time monitoring, threat intelligence feeds, and more robust anomaly detection methods.


Developed and Documentation By: Raymond C. TURNER

Last Updated: Monday 28th August 2023 @ 01:03 BST