Skip to main content

KICOM Anti-Virus II - Open source antivirus engine for Python

Project description

KicomAV v0.41

License Platform Platform Platform
Language PyPI Downloads

KicomAV is an open source antivirus engine designed for detecting malware and disinfecting it. This antivirus engine is created and maintained by Kei Choi.

Features

  • Multi-format scanning: Files, archives (ZIP, RAR, 7z, CAB, ALZ, EGG, APK, OneNote), and nested containers
  • YARA integration: Custom YARA rules support for advanced threat detection
  • Intelligent caching: Dual-cache system with scan mode awareness for consistent, fast rescans
  • Exclusion rules: Flexible file/directory exclusion with glob patterns
  • Parallel scanning: Multi-threaded scanning for improved performance
  • Daemon mode: REST API and clamd-compatible socket protocol
  • Cross-platform: Windows, Linux, macOS support
  • Library API: Use as a Python library in your projects
  • PyInstaller support: Scan PyInstaller executables (Windows PE and Linux ELF)

Table of Contents

Requirements

Daemon mode dependencies (k2d, k2c):

Optional dependencies:

  • pylzma - LZMA compression (for NSIS)

Installation

Via pip (Recommended)

pip install kicomav

From source

git clone https://github.com/hanul93/kicomav.git
cd kicomav
pip install -e .

With daemon support

pip install kicomav[daemon]

Configuration

KicomAV uses environment variables for configuration. Create a .env file in your home directory:

Windows:

mkdir %USERPROFILE%\.kicomav
copy .env.example %USERPROFILE%\.kicomav\.env

Linux/macOS:

mkdir -p ~/.kicomav
cp .env.example ~/.kicomav/.env

Then edit ~/.kicomav/.env to configure:

Variable Description Example
UNRAR_TOOL Path to UnRAR executable /usr/bin/unrar or C:\Program Files\WinRAR\UnRAR.exe
RAR_TOOL Path to RAR executable /usr/bin/rar or C:\Program Files\WinRAR\Rar.exe
SYSTEM_RULES_BASE System rules path /var/lib/kicomav/rules or C:\kicomav\rules
USER_RULES_BASE User rules path /home/user/kicomav_rules or C:\kicomav\user_rules

Note: You can also place a .env file in the current working directory for project-specific settings (takes priority over global settings).

Components

KicomAV provides three command-line tools:

Tool Description
k2 Main scanner - scan files and directories for malware
k2d Daemon server - REST API and socket protocol service
k2c Client - communicate with k2d daemon

Quick Overview

  • Standalone scanning: Use k2 directly for local file scanning
  • Client-server mode: Run k2d as a service, use k2c to send scan requests

Command-Line Usage (k2)

$ k2 path[s] [options]

Basic Options

Option Description
-f, --files Scan files (default)
-r, --arc Scan archives
-R, --nor Do not recurse into folders
-I, --list Display all files
-V, --vlist Display virus list
-?, --help Show help

Scan Actions

Option Description
-p, --prompt Prompt for action
-d, --dis Disinfect files
-l, --del Delete infected files
--move Move infected files to quarantine
--copy Copy infected files to quarantine

Performance Options

Option Description
--parallel Enable parallel file scanning
--workers=N Number of worker threads (default: CPU count)
--cache Enable scan cache (default)
--no-cache Disable scan cache

Other Options

Option Description
-G, --log=FILE Create log file
-e, --app Append to log file
-F, --infp=PATH Set quarantine folder
--password=PWD Password for encrypted archives
--no-color Disable colored output
--sigtool Extract files from archives to output folder
--update Update malware signatures

Examples

Update signatures:

$ k2 --update

Scan current directory:

$ k2 . -I

Scan with archive support:

$ k2 /path/to/scan -r -I

Parallel scanning with 8 workers:

$ k2 /path/to/scan --parallel --workers=8

Scan and disinfect:

$ k2 /path/to/scan -d

Advanced Features

Exclusion Rules

KicomAV supports flexible file exclusion to skip unwanted files during scans.

Command-Line Options

Option Description Example
--exclude=PATTERN Exclude files matching glob pattern --exclude=*.log
--exclude-ext=EXT Exclude by extension (comma-separated) --exclude-ext=log,tmp
--max-size=SIZE Skip files larger than size --max-size=100MB
--ignore-file=FILE Load rules from file --ignore-file=.kicomav-ignore

Size units: B, KB, MB, GB

Examples

# Skip log files and files over 50MB
k2 /path/to/scan --exclude-ext=log --max-size=50MB

# Skip multiple patterns
k2 /path/to/scan --exclude=**/node_modules/** --exclude=**/cache/**

# Use an ignore file
k2 /path/to/scan --ignore-file=.kicomav-ignore

Ignore File Format (.kicomav-ignore)

Create a .kicomav-ignore file (similar to .gitignore):

# Comment lines start with #
*.log                    # Exclude all .log files
*.tmp                    # Exclude all .tmp files
node_modules/            # Exclude node_modules directory
build/                   # Exclude build directory
**/cache/**              # Exclude cache directories anywhere
>100MB                   # Skip files larger than 100MB

Ignore file search order:

  1. Current directory
  2. Parent directories (up to root)
  3. ~/.kicomav/.kicomav-ignore

Pattern Matching

Pattern Matches Does Not Match
*.log app.log, error.log app.txt, log.txt
**/cache/** /project/cache/file.txt /project/cached/file.txt
node_modules/ /project/node_modules/pkg.json /project/my_modules/pkg.json
file?.txt file1.txt, fileA.txt file10.txt, file.txt

Library Usage

from kicomav.kavcore.k2exclude import ExclusionRule, create_exclusion_rule

# Create rule with factory function
rule = create_exclusion_rule(
    patterns=["**/node_modules/**", "**/cache/**"],
    extensions=["log", "tmp", "bak"],
    max_size="100MB"
)

# Check if a file should be excluded
if rule.should_exclude("/path/to/file.log"):
    print("File excluded")

Scan Cache

KicomAV supports intelligent caching to skip unchanged files during rescans, significantly improving scan performance.

How It Works

  • SQLite database stored at ~/.kicomav/cache.db
  • Dual cache system: Separate caches for regular files and archives
  • Files are skipped if unchanged since last scan
  • Cache invalidates when signature version changes
  • Configurable expiration period (default: 7 days)

Cache Architecture

KicomAV uses a sophisticated dual-cache system:

Cache Type Purpose Key
scan_cache Regular files file_path
archive_cache Archives (ZIP, RAR, 7z, etc.) (archive_path, scan_mode)

Scan Mode Awareness: The archive cache tracks whether -r (deep archive scan) option was used:

  • -I and -r -I scans maintain separate cache entries
  • Switching between scan modes produces consistent results
  • Each mode's statistics (Files, Packed, Infected) are preserved independently

Archive Cache Features

  • Contents hash: Archives identified by hash of internal file list
  • Infection tracking: Cached results include infected file paths with malware names
  • Statistics preservation: File count, packed count, and scan paths are cached
  • Smart revalidation: Re-compressed archives with same files remain cache-valid

Command-Line Options

Option Description Default
--cache Enable scan cache Enabled
--no-cache Disable scan cache -
--cache-clear Clear all cache entries -
--cache-stats Show cache statistics -
--cache-expire=DAYS Set expiration (0=never) 7

Examples

# Scan with cache (default behavior)
k2 /path/to/scan -r

# Disable cache for fresh scan
k2 /path/to/scan -r --no-cache

# View cache statistics
k2 --cache-stats

# Clear cache
k2 --cache-clear

# Set 30-day cache expiration
k2 /path/to/scan --cache-expire=30

Cache Statistics Output

Scan Cache Statistics
----------------------------------------
Cache path: ~/.kicomav/cache.db
Cache size: 1.2MB
Total entries: 5532 (files: 5432, archives: 100)
Clean files: 5410
Infected files: 22
Clean archives: 95
Infected archives: 5
Expired entries: 128
Expire days: 7

Cache Invalidation

The cache automatically invalidates when:

  1. File modified: File size or modification time changed
  2. Signature updated: Signature version differs from cached version
  3. Cache expired: Entry older than expiration period
  4. File deleted: Entry removed during maintenance
  5. Scan mode changed: Archive scanned with different -r option (archive cache only)
  6. Contents changed: Archive internal file list differs (archive cache only)

Performance Impact

Example scan times with caching enabled:

Scan Option Time Notes
First -r -I ~40s Full scan, cache populated
Second -r -I ~2s Cache hit
Third -I ~18s Different mode, separate cache
Fourth -I ~0s Cache hit
Fifth -r -I ~2s Returns to cached -r results

This ensures:

  • Rescanning unchanged files/archives is nearly instant
  • Different scan modes maintain independent, consistent results
  • Infected entries from previous scans are reported from cache

Library Usage

from kicomav.kavcore.k2cache import (
    ScanCache, compute_file_hash, compute_contents_hash, create_cache
)

# Create cache with custom expiration
cache = create_cache(expire_days=14)

# Check if file needs scanning
if cache.needs_scan("/path/to/file", signature_version="1.0"):
    file_hash = compute_file_hash("/path/to/file")
    cache.update("/path/to/file", file_hash, "clean", signature_version="1.0")
else:
    result = cache.get_cached_result("/path/to/file", "1.0")
    if result:
        scan_result, malware_name = result
        print(f"Cached result: {scan_result}")

# Archive cache usage
# Create contents hash from archive entries (filename, size, crc)
entries = [("file1.txt", 100, 12345), ("file2.txt", 200, 67890)]
contents_hash = compute_contents_hash(entries)

# opt_arc parameter controls cache separation:
# - opt_arc=False: -I option (partial archive scan)
# - opt_arc=True: -r -I option (full archive scan)
opt_arc = True  # Using -r option

# Check if archive needs scanning
if cache.needs_archive_scan("/path/to/archive.zip", contents_hash, "1.0", opt_arc):
    # Perform archive scan...
    # After scanning, update cache with results
    infected = [{"path": "malware.exe", "malware": "Trojan.Test"}]
    cache.update_archive(
        "/path/to/archive.zip",
        archive_hash="abc123",
        contents_hash=contents_hash,
        scan_result="infected",
        infected_entries=infected,
        signature_version="1.0",
        opt_arc=opt_arc  # Store scan mode
    )
else:
    # Use cached archive result
    result = cache.get_archive_cached_result(
        "/path/to/archive.zip", contents_hash, "1.0", opt_arc
    )
    if result:
        scan_result, infected_entries, total_files, total_packed, scanned_paths = result
        print(f"Archive result: {scan_result}")
        print(f"Files: {total_files}, Packed: {total_packed}")
        for entry in infected_entries:
            print(f"  Infected: {entry['path']} - {entry['malware']}")

# Get statistics
stats = cache.get_stats()
print(f"Total entries: {stats['total_entries']}")
print(f"File entries: {stats['file_entries']}")
print(f"Archive entries: {stats['archive_entries']}")

# Maintenance
cache.prune_expired()   # Remove expired entries
cache.prune_missing()   # Remove entries for deleted files
cache.vacuum()          # Compact database
cache.close()

Parallel Scanning

Enable multi-threaded scanning for improved performance on multi-core systems.

# Auto-detect CPU count
k2 /path/to/scan --parallel

# Specify worker count
k2 /path/to/scan --parallel --workers=8

Library Usage

KicomAV can be used as a Python library in your projects.

Basic Scanning

import kicomav

# Scan a single file
with kicomav.Scanner() as scanner:
    result = scanner.scan_file("/path/to/suspicious_file.exe")
    if result.infected:
        print(f"Malware detected: {result.malware_name}")
    else:
        print("File is clean")

Directory Scanning

import kicomav

# Scan an entire directory
with kicomav.Scanner() as scanner:
    results = scanner.scan_directory("/path/to/folder", recursive=True)

    infected_files = [r for r in results if r.infected]
    print(f"Scanned {len(results)} files, found {len(infected_files)} infected")

    for result in infected_files:
        print(f"  {result.path}: {result.malware_name}")

Updating Signatures

import kicomav

result = kicomav.update()

if result.package_update_available:
    print(f"New version available: {result.latest_version}")

if result.updated_files:
    print(f"Updated {len(result.updated_files)} signature files")

Configuration Access

import kicomav

config = kicomav.get_config()
print(f"System rules path: {config.system_rules_base}")
print(f"User rules path: {config.user_rules_base}")

Suppress Warnings

from kicomav.kavcore.config import suppress_warnings
suppress_warnings(True)

import kicomav  # No configuration warnings

Archive Exploration

KicomAV provides high-level APIs for exploring and extracting archives.

import kicomav

# List archive contents
with kicomav.Scanner() as scanner:
    info, entries = scanner.list_archive("/path/to/archive.zip")
    print(f"Format: {info.format_type}")
    for entry in entries:
        print(f"{'  '*entry.depth}{entry.path}")

# Extract archive to a folder
with kicomav.Scanner() as scanner:
    result = scanner.extract_archive(
        "/path/to/archive.zip",
        "/output/folder"
    )
    print(f"Extracted {result.extracted_count} files")
    print(f"Log file: {result.log_file}")

# Read a single file from archive into memory
with kicomav.Scanner() as scanner:
    data = scanner.read_archive("/path/to/archive.zip", "config.json")
    if data:
        import json
        config = json.loads(data.decode('utf-8'))

Supported Formats: ZIP, RAR, 7z, CAB, ALZ, EGG, TAR, GZ, BZ2, APK, OneNote, PyInstaller (PE/ELF)

Exception Handling:

import kicomav

try:
    with kicomav.Scanner() as scanner:
        result = scanner.extract_archive("/path/to/archive.zip", "/output")
except kicomav.ArchiveNotFoundError:
    print("Archive file not found")
except kicomav.ArchiveFormatError:
    print("Unsupported or corrupted archive format")
except kicomav.ArchivePasswordError:
    print("Archive is password protected")
except kicomav.ArchiveSecurityError:
    print("Security issue detected (e.g., path traversal)")
except kicomav.ArchiveExtractionError as e:
    print(f"Extraction failed: {e}")

Advanced: Direct Engine Access

import kicomav

engine = kicomav.Engine(verbose=True)
engine.set_plugins("/path/to/plugins")

instance = engine.create_instance()
instance.init()

# Get engine information
info = instance.getinfo()
for plugin_info in info:
    print(f"Plugin: {plugin_info.get('title')}")

# Scan with callback
def on_detect(result, filename, malware_name, malware_id):
    print(f"Detected: {malware_name} in {filename}")

instance.scan("/path/to/file.exe", on_detect)
instance.uninit()

Daemon Mode (k2d & k2c)

KicomAV can run as a daemon server, providing both REST API and clamd-compatible socket protocol.

Server (k2d)

# Start both REST API and Socket server
k2d

# Start REST API only (port 8311)
k2d --http-only

# Start Socket server only (port 3311)
k2d --socket-only

# Generate API key for authentication
k2d --generate-key

Server Configuration

Variable Default Description
K2D_HTTP_HOST 127.0.0.1 HTTP bind address
K2D_HTTP_PORT 8311 HTTP port
K2D_SOCKET_PORT 3311 Socket port
K2D_MAX_UPLOAD_SIZE 52428800 Max upload size (50MB)
K2D_MAX_WORKERS CPU count Max concurrent workers
K2D_API_KEY - API key for authentication
K2D_REQUIRE_AUTH false Require authentication

Client (k2c)

k2c is a command-line client for communicating with the k2d daemon.

# Server status
k2c --ping                     # Check server connection
k2c --version                  # Get version info
k2c --stats                    # Get statistics

# Scan files
k2c /path/to/file              # Scan a file
k2c /path/to/folder            # Scan a directory
k2c --stream < suspicious.exe  # Scan from stdin

# Connection options
k2c --host 192.168.1.100       # Connect to remote server
k2c --socket                   # Use socket protocol
k2c --api-key YOUR_KEY         # Authentication

# Cache management
k2c --cache-stats              # View cache statistics
k2c --cache-clear              # Clear cache

# Output options
k2c --json                     # JSON output
k2c -q                         # Only show infected files

Example

$ k2c eicar.txt
============================================================
KicomAV Client (k2c) v0.41
============================================================

eicar.txt  infected : EICAR-Test-File (not a virus)

----------------------------------------
Files scanned: 1
Infected: 1
Errors: 0

REST API

Method Endpoint Description
GET /ping Health check
GET /version Version and signature info
GET /stats Scan statistics
POST /scan/file Scan uploaded file
POST /scan/path Scan local path
POST /scan/stream Scan base64 encoded data
POST /reload Reload signatures

Examples:

# Health check
curl http://127.0.0.1:8311/ping

# Scan a file
curl -X POST -F "file=@suspicious.exe" http://127.0.0.1:8311/scan/file

# Scan a directory
curl -X POST -H "Content-Type: application/json" \
  -d '{"path": "/path/to/scan", "recursive": true}' \
  http://127.0.0.1:8311/scan/path

Socket Protocol (clamd-compatible)

Command Description
PING Health check (returns PONG)
VERSION Get version info
STATS Get statistics
SCAN <path> Scan a file
CONTSCAN <path> Scan directory recursively
INSTREAM Scan streamed data
RELOAD Reload signatures

Example (Python):

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("127.0.0.1", 3311))

# PING test
sock.send(b"PING\n")
print(sock.recv(1024))  # b'PONG\n'

# Scan a file
sock.send(b"SCAN /path/to/file.exe\n")
print(sock.recv(1024))  # b'/path/to/file.exe: OK\n'

sock.close()

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Kei Choi

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kicomav-0.41.tar.gz (255.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kicomav-0.41-py3-none-any.whl (297.6 kB view details)

Uploaded Python 3

File details

Details for the file kicomav-0.41.tar.gz.

File metadata

  • Download URL: kicomav-0.41.tar.gz
  • Upload date:
  • Size: 255.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for kicomav-0.41.tar.gz
Algorithm Hash digest
SHA256 31b301a7138a6ac824e4ce07f13e0a8ca4705ba2d37dfe943c17034f2c4de536
MD5 cfe4ca70e48881d9d5b033a776080b72
BLAKE2b-256 ea70dbea45f16e194b57dc39c874ce2b303291673201620464d0325ee63d4a07

See more details on using hashes here.

File details

Details for the file kicomav-0.41-py3-none-any.whl.

File metadata

  • Download URL: kicomav-0.41-py3-none-any.whl
  • Upload date:
  • Size: 297.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for kicomav-0.41-py3-none-any.whl
Algorithm Hash digest
SHA256 9f0336b5fda1e1f84562dc693827c847f85f25ec678769a95e656b6aec011302
MD5 fbc3cc6b7f203ac5bf4b5b4d176578a2
BLAKE2b-256 cbd1d6f00d4a500fcf05fd21b9ec69d86b0d301bd4c38cf42acc51127f908d1b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page