goclamav

package module
v0.7.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2023 License: GPL-2.0 Imports: 6 Imported by: 0

README

go-clamav

GoDoc

go-clamav is go wrapper for libclamav

Environment

Ubuntu
apt-get update && apt-get install -y \
  `# install tools` \
  gcc make pkg-config python3 python3-pip python3-pytest valgrind \
  `# install clamav dependencies` \
  check libbz2-dev libcurl4-openssl-dev libjson-c-dev libmilter-dev \
  libncurses5-dev libpcre2-dev libssl-dev libxml2-dev zlib1g-dev

  python3 -m pip install --user cmake / apt-get install cmake

Download the source from the clamav downloads page

tar xzf clamav-[ver].tar.gz
cd clamav-[ver]

mkdir build && cd build

cmake ..
cmake --build .
ctest
sudo cmake --build . --target install

For other Linux distributions, see clamav documentation

Quick Start

Dynamic linking
$ cd example && cat main.go
package main

import (
	"fmt"

	clamav "git.cyber.gent/friedkiwi/go-clamav"
)

func main() {
	// new clamav instance
	c := new(clamav.Clamav)
	err := c.Init(clamav.SCAN_OPTIONS{
		General:   0,
		Parse:     clamav.CL_SCAN_PARSE_ARCHIVE | clamav.CL_SCAN_PARSE_ELF,
		Heuristic: 0,
		Mail:      0,
		Dev:       0,
	})

	if err != nil {
		panic(err)
	}

	// free clamav memory
	defer c.Free()

	// load db
	signo, err := c.LoadDB("./db", uint(clamav.CL_DB_DIRECTORY))
	if err != nil {
		panic(err)
	}
	fmt.Println("db load succeed:", signo)

	// compile engine
	err = c.CompileEngine()
	if err != nil {
		panic(err)
	}

	c.EngineSetNum(clamav.CL_ENGINE_MAX_SCANSIZE, 1024*1024*40)
	c.EngineSetNum(clamav.CL_ENGINE_MAX_SCANTIME, 9000)
	// fmt.Println(c.EngineGetNum(clamav.CL_ENGINE_MAX_SCANSIZE))

	// scan
	scanned, virusName, ret := c.ScanFile("./test_file/nmap")
	fmt.Println(scanned, virusName, ret)
}
$ CGO_LDFLAGS="-L/usr/local/lib -lclamav" go run main.go

db load succeed: 9263
209 YARA.Unix_Packer_UpxDetail.UNOFFICIAL Virus(es) detected

If the libclamav.so file is not found, try it:

$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib CGO_LDFLAGS="-L/usr/local/lib -lclamav" go run main.go

db load succeed: 9263
209 YARA.Unix_Packer_UpxDetail.UNOFFICIAL Virus(es) detected
Static build
$ sudo bash ./prepare.sh
$ SRCDIR=$(pwd)
$ export CGO_CFLAGS="-g -Wall -I${SRCDIR}/clamav-mussels-cookbook/mussels/install/include"
$ export CGO_LDFLAGS="-L${SRCDIR}/clamav-mussels-cookbook/mussels/install/lib -lclamav_static -lbz2_static -lclammspack_static -lclamunrar_iface_static -lclamunrar_static -lcrypto -ljson-c -lpcre2-8 -lpcre2-posix -lssl -lxml2 -lz -lm -ldl -lstdc++"
$ CGO_ENABLED=1 go build --ldflags '--extldflags "-static -fpic"' main.go

Reference

mirtchovski/clamav ca110us/go-clamav

This is an adaptation of mirtchovski/clamav because it fails to compile on newer versions of go on macOS.

Documentation

Overview

Package go-clamav is go wrapper for libclamav see https://docs.clamav.net/manual/Development/libclamav.html

Index

Constants

View Source
const (
	/* general */
	CL_SCAN_GENERAL_ALLMATCHES           = 0x1  /* scan in all-match mode */
	CL_SCAN_GENERAL_COLLECT_METADATA     = 0x2  /* collect metadata (--gen-json) */
	CL_SCAN_GENERAL_HEURISTICS           = 0x4  /* option to enable heuristic alerts */
	CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE = 0x8  /* allow heuristic match to take precedence. */
	CL_SCAN_GENERAL_UNPRIVILEGED         = 0x10 /* scanner will not have read access to files. */

	/* parsing capabilities options */
	CL_SCAN_PARSE_ARCHIVE = 0x1
	CL_SCAN_PARSE_ELF     = 0x2
	CL_SCAN_PARSE_PDF     = 0x4
	CL_SCAN_PARSE_SWF     = 0x8
	CL_SCAN_PARSE_HWP3    = 0x10
	CL_SCAN_PARSE_XMLDOCS = 0x20
	CL_SCAN_PARSE_MAIL    = 0x40
	CL_SCAN_PARSE_OLE2    = 0x80
	CL_SCAN_PARSE_HTML    = 0x100
	CL_SCAN_PARSE_PE      = 0x200

	/* heuristic alerting options */
	CL_SCAN_HEURISTIC_BROKEN                  = 0x2    /* alert on broken PE and broken ELF files */
	CL_SCAN_HEURISTIC_EXCEEDS_MAX             = 0x4    /* alert when files exceed scan limits (filesize, max scansize, or max recursion depth) */
	CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH   = 0x8    /* alert on SSL mismatches */
	CL_SCAN_HEURISTIC_PHISHING_CLOAK          = 0x10   /* alert on cloaked URLs in emails */
	CL_SCAN_HEURISTIC_MACROS                  = 0x20   /* alert on OLE2 files containing macros */
	CL_SCAN_HEURISTIC_ENCRYPTED_ARCHIVE       = 0x40   /* alert if archive is encrypted (rar, zip, etc) */
	CL_SCAN_HEURISTIC_ENCRYPTED_DOC           = 0x80   /* alert if a document is encrypted (pdf, docx, etc) */
	CL_SCAN_HEURISTIC_PARTITION_INTXN         = 0x100  /* alert if partition table size doesn't make sense */
	CL_SCAN_HEURISTIC_STRUCTURED              = 0x200  /* data loss prevention options, i.e. alert when detecting personal information */
	CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL   = 0x400  /* alert when detecting social security numbers */
	CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED = 0x800  /* alert when detecting stripped social security numbers */
	CL_SCAN_HEURISTIC_STRUCTURED_CC           = 0x1000 /* alert when detecting credit card numbers */
	CL_SCAN_HEURISTIC_BROKEN_MEDIA            = 0x2000 /* alert if a file does not match the identified file format, works with JPEG, TIFF, GIF, PNG */

	/* mail scanning options */
	CL_SCAN_MAIL_PARTIAL_MESSAGE = 0x1

	/* dev options */
	CL_SCAN_DEV_COLLECT_SHA              = 0x1 /* Enables hash output in sha-collect builds - for internal use only */
	CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO = 0x2 /* collect performance timings */

	/* cl_countsigs options */
	CL_COUNTSIGS_OFFICIAL   = 0x1
	CL_COUNTSIGS_UNOFFICIAL = 0x2
	CL_COUNTSIGS_ALL        = (CL_COUNTSIGS_OFFICIAL | CL_COUNTSIGS_UNOFFICIAL)
)
View Source
const CL_INIT_DEFAULT C.uint = C.CL_INIT_DEFAULT

CL_INIT_DEFAULT is a macro that can be passed to cl_init() representing the default initialization settings

Variables

This section is empty.

Functions

func CloseMemory

func CloseMemory(f *Fmap)

CloseMemory destroys the fmap associated with an in-memory object

func Strerr

func Strerr(code ErrorCode) error

Wraps the corresponding error message

Types

type Callback

type Callback struct {
	sync.Mutex
	// contains filtered or unexported fields
}

Callback is used to store the interface passed to ScanFileCb. This object is then returned in each ClamAV callback for the duration of the file scan

type Clamav

type Clamav struct {
	// contains filtered or unexported fields
}

func (*Clamav) CompileEngine

func (c *Clamav) CompileEngine() error

When all required databases are loaded you should prepare the detection engine by calling CompileEngine

func (*Clamav) CvdVerify

func (c *Clamav) CvdVerify(path string) error

Use the CvdVerify to verify a database directly: As the comment block explains, this will load-test the database. Be advised that for some larger databases, this may use a fair bit system RAM.

func (*Clamav) EngineGetNum

func (c *Clamav) EngineGetNum(field EngineField) (uint64, error)

EngineGetNum acquires a number from the specified field of the engine configuration. Tests show that the ClamAV library will not overflow 32-bit fields, so a GetNum on a 32-bit field can safely be cast to uint32.

func (*Clamav) EngineSetNum

func (c *Clamav) EngineSetNum(field EngineField, num uint64) error

EngineSetNum sets a number in the specified field of the engine configuration. Certain fields accept only 32-bit numbers, silently truncating the higher bits of the engine config. See dat.go for more information.

func (*Clamav) Free

func (c *Clamav) Free() error

Free the memory allocated to clamav instance, Free should be called when the engine is no longer in use.

func (*Clamav) Init

func (c *Clamav) Init(options SCAN_OPTIONS) error

Init new clamav instance

func (*Clamav) LoadDB

func (c *Clamav) LoadDB(path string, dbopts uint) (uint, error)

Load clamav virus database

func (*Clamav) ScanDesc

func (c *Clamav) ScanDesc(desc int32, fileName string) (uint, string, error)

ScanDesc scans a file descriptor for viruses using the ClamAV databases. It returns the number of bytes read from the file (if found), the virus name and an error code. If the file is clean, the virus name is empty and the error code is nil,but if the file is insecure, the error code is "Virus(es) detected" and virus name is the matching rule.

func (*Clamav) ScanFile

func (c *Clamav) ScanFile(path string) (uint, string, error)

ScanFile scans a single file for viruses using the ClamAV databases. It returns the number of bytes read from the file (if found), the virus name and an error code. If the file is clean, the virus name is empty and the error code is nil,but if the file is insecure, the error code is "Virus(es) detected" and virus name is the matching rule.

func (*Clamav) ScanFileCB

func (c *Clamav) ScanFileCB(path string, context interface{}) (uint, string, error)

ScanFileCB scans a single file for viruses using the ClamAV databases and using callbacks from ClamAV to read/resolve file data. The callbacks can be used to scan files in memory, to scan multiple files inside archives, etc. The function returns the number of bytes read from the file (if found), the virus name and an error code. If the file is clean, the virus name is empty and the error code is nil,but if the file is insecure, the error code is "Virus(es) detected" and virus name is the matching rule. The context argument will be sent back to the callbacks, so effort must be made to retain it throughout the execution of the scan from garbage collection

func (*Clamav) ScanMapCB

func (c *Clamav) ScanMapCB(fmap *Fmap, fileName string, context interface{}) (uint, string, error)

ScanMapCB scans custom data

type DBOptions

type DBOptions uint
db options

clang-format off

const (
	CL_DB_PHISHING          DBOptions = C.CL_DB_PHISHING
	CL_DB_PHISHING_URLS     DBOptions = C.CL_DB_PHISHING_URLS
	CL_DB_PUA               DBOptions = C.CL_DB_PUA
	CL_DB_CVDNOTMP          DBOptions = C.CL_DB_CVDNOTMP /* obsolete */
	CL_DB_OFFICIAL          DBOptions = C.CL_DB_OFFICIAL /* internal */
	CL_DB_PUA_MODE          DBOptions = C.CL_DB_PUA_MODE
	CL_DB_PUA_INCLUDE       DBOptions = C.CL_DB_PUA_INCLUDE
	CL_DB_PUA_EXCLUDE       DBOptions = C.CL_DB_PUA_EXCLUDE
	CL_DB_COMPILED          DBOptions = C.CL_DB_COMPILED  /* internal */
	CL_DB_DIRECTORY         DBOptions = C.CL_DB_DIRECTORY /* internal */
	CL_DB_OFFICIAL_ONLY     DBOptions = C.CL_DB_OFFICIAL_ONLY
	CL_DB_BYTECODE          DBOptions = C.CL_DB_BYTECODE
	CL_DB_SIGNED            DBOptions = C.CL_DB_SIGNED            /* internal */
	CL_DB_BYTECODE_UNSIGNED DBOptions = C.CL_DB_BYTECODE_UNSIGNED /* Caution: You should never run bytecode signatures from untrusted sources. Doing so may result in arbitrary code execution. */
	CL_DB_UNSIGNED          DBOptions = C.CL_DB_UNSIGNED          /* internal */
	CL_DB_BYTECODE_STATS    DBOptions = C.CL_DB_BYTECODE_STATS
	CL_DB_ENHANCED          DBOptions = C.CL_DB_ENHANCED
	CL_DB_PCRE_STATS        DBOptions = C.CL_DB_PCRE_STATS
	CL_DB_YARA_EXCLUDE      DBOptions = C.CL_DB_YARA_EXCLUDE
	CL_DB_YARA_ONLY         DBOptions = C.CL_DB_YARA_ONLY
)

type EngineField

type EngineField C.enum_cl_engine_field

EngineField selects a particular engine settings field

const (
	CL_ENGINE_MAX_SCANSIZE        EngineField = C.CL_ENGINE_MAX_SCANSIZE        /* uint64_t */
	CL_ENGINE_MAX_FILESIZE        EngineField = C.CL_ENGINE_MAX_FILESIZE        /* uint64_t */
	CL_ENGINE_MAX_RECURSION       EngineField = C.CL_ENGINE_MAX_RECURSION       /* uint32_t */
	CL_ENGINE_MAX_FILES           EngineField = C.CL_ENGINE_MAX_FILES           /* uint32_t */
	CL_ENGINE_MIN_CC_COUNT        EngineField = C.CL_ENGINE_MIN_CC_COUNT        /* uint32_t */
	CL_ENGINE_MIN_SSN_COUNT       EngineField = C.CL_ENGINE_MIN_SSN_COUNT       /* uint32_t */
	CL_ENGINE_PUA_CATEGORIES      EngineField = C.CL_ENGINE_PUA_CATEGORIES      /* (char *) */
	CL_ENGINE_DB_OPTIONS          EngineField = C.CL_ENGINE_DB_OPTIONS          /* uint32_t */
	CL_ENGINE_DB_VERSION          EngineField = C.CL_ENGINE_DB_VERSION          /* uint32_t */
	CL_ENGINE_DB_TIME             EngineField = C.CL_ENGINE_DB_TIME             /* time_t */
	CL_ENGINE_AC_ONLY             EngineField = C.CL_ENGINE_AC_ONLY             /* uint32_t */
	CL_ENGINE_AC_MINDEPTH         EngineField = C.CL_ENGINE_AC_MINDEPTH         /* uint32_t */
	CL_ENGINE_AC_MAXDEPTH         EngineField = C.CL_ENGINE_AC_MAXDEPTH         /* uint32_t */
	CL_ENGINE_TMPDIR              EngineField = C.CL_ENGINE_TMPDIR              /* (char *) */
	CL_ENGINE_KEEPTMP             EngineField = C.CL_ENGINE_KEEPTMP             /* uint32_t */
	CL_ENGINE_BYTECODE_SECURITY   EngineField = C.CL_ENGINE_BYTECODE_SECURITY   /* uint32_t */
	CL_ENGINE_BYTECODE_TIMEOUT    EngineField = C.CL_ENGINE_BYTECODE_TIMEOUT    /* uint32_t */
	CL_ENGINE_BYTECODE_MODE       EngineField = C.CL_ENGINE_BYTECODE_MODE       /* uint32_t */
	CL_ENGINE_MAX_EMBEDDEDPE      EngineField = C.CL_ENGINE_MAX_EMBEDDEDPE      /* uint64_t */
	CL_ENGINE_MAX_HTMLNORMALIZE   EngineField = C.CL_ENGINE_MAX_HTMLNORMALIZE   /* uint64_t */
	CL_ENGINE_MAX_HTMLNOTAGS      EngineField = C.CL_ENGINE_MAX_HTMLNOTAGS      /* uint64_t */
	CL_ENGINE_MAX_SCRIPTNORMALIZE EngineField = C.CL_ENGINE_MAX_SCRIPTNORMALIZE /* uint64_t */
	CL_ENGINE_MAX_ZIPTYPERCG      EngineField = C.CL_ENGINE_MAX_ZIPTYPERCG      /* uint64_t */
	CL_ENGINE_FORCETODISK         EngineField = C.CL_ENGINE_FORCETODISK         /* uint32_t */
	CL_ENGINE_DISABLE_CACHE       EngineField = C.CL_ENGINE_DISABLE_CACHE       /* uint32_t */
	CL_ENGINE_DISABLE_PE_STATS    EngineField = C.CL_ENGINE_DISABLE_PE_STATS    /* uint32_t */
	CL_ENGINE_STATS_TIMEOUT       EngineField = C.CL_ENGINE_STATS_TIMEOUT       /* uint32_t */
	CL_ENGINE_MAX_PARTITIONS      EngineField = C.CL_ENGINE_MAX_PARTITIONS      /* uint32_t */
	CL_ENGINE_MAX_ICONSPE         EngineField = C.CL_ENGINE_MAX_ICONSPE         /* uint32_t */
	CL_ENGINE_MAX_RECHWP3         EngineField = C.CL_ENGINE_MAX_RECHWP3         /* uint32_t */
	CL_ENGINE_MAX_SCANTIME        EngineField = C.CL_ENGINE_MAX_SCANTIME        /* uint32_t */
	CL_ENGINE_PCRE_MATCH_LIMIT    EngineField = C.CL_ENGINE_PCRE_MATCH_LIMIT    /* uint64_t */
	CL_ENGINE_PCRE_RECMATCH_LIMIT EngineField = C.CL_ENGINE_PCRE_RECMATCH_LIMIT /* uint64_t */
	CL_ENGINE_PCRE_MAX_FILESIZE   EngineField = C.CL_ENGINE_PCRE_MAX_FILESIZE   /* uint64_t */
	CL_ENGINE_DISABLE_PE_CERTS    EngineField = C.CL_ENGINE_DISABLE_PE_CERTS    /* uint32_t */
	CL_ENGINE_PE_DUMPCERTS        EngineField = C.CL_ENGINE_PE_DUMPCERTS        /* uint32_t */
)

Engine settings

type ErrorCode

type ErrorCode C.cl_error_t

ErrorCode models ClamAV errors

const (
	/* libclamav specific */
	CL_CLEAN    ErrorCode = C.CL_CLEAN
	CL_SUCCESS  ErrorCode = C.CL_SUCCESS
	CL_VIRUS    ErrorCode = C.CL_VIRUS
	CL_ENULLARG ErrorCode = C.CL_ENULLARG
	CL_EARG     ErrorCode = C.CL_EARG
	CL_EMALFDB  ErrorCode = C.CL_EMALFDB
	CL_ECVD     ErrorCode = C.CL_ECVD
	CL_EVERIFY  ErrorCode = C.CL_EVERIFY
	CL_EUNPACK  ErrorCode = C.CL_EUNPACK

	/* I/O and memory errors */
	CL_EOPEN    ErrorCode = C.CL_EOPEN
	CL_ECREAT   ErrorCode = C.CL_ECREAT
	CL_EUNLINK  ErrorCode = C.CL_EUNLINK
	CL_ESTAT    ErrorCode = C.CL_ESTAT
	CL_EREAD    ErrorCode = C.CL_EREAD
	CL_ESEEK    ErrorCode = C.CL_ESEEK
	CL_EWRITE   ErrorCode = C.CL_EWRITE
	CL_EDUP     ErrorCode = C.CL_EDUP
	CL_EACCES   ErrorCode = C.CL_EACCES
	CL_ETMPFILE ErrorCode = C.CL_ETMPFILE
	CL_ETMPDIR  ErrorCode = C.CL_ETMPDIR
	CL_EMAP     ErrorCode = C.CL_EMAP
	CL_EMEM     ErrorCode = C.CL_EMEM
	CL_ETIMEOUT ErrorCode = C.CL_ETIMEOUT

	/* internal (not reported outside libclamav) */
	CL_BREAK              ErrorCode = C.CL_BREAK
	CL_EMAXREC            ErrorCode = C.CL_EMAXREC
	CL_EMAXSIZE           ErrorCode = C.CL_EMAXSIZE
	CL_EMAXFILES          ErrorCode = C.CL_EMAXFILES
	CL_EFORMAT            ErrorCode = C.CL_EFORMAT
	CL_EPARSE             ErrorCode = C.CL_EPARSE
	CL_EBYTECODE          ErrorCode = C.CL_EBYTECODE          /* may be reported in testmode */
	CL_EBYTECODE_TESTFAIL ErrorCode = C.CL_EBYTECODE_TESTFAIL /* may be reported in testmode */

	/* c4w error codes */
	CL_ELOCK  ErrorCode = C.CL_ELOCK
	CL_EBUSY  ErrorCode = C.CL_EBUSY
	CL_ESTATE ErrorCode = C.CL_ESTATE

	CL_VERIFIED ErrorCode = C.CL_VERIFIED /* The binary has been deemed trusted */
	CL_ERROR    ErrorCode = C.CL_ERROR    /* Unspecified / generic error */

	/* no error codes below this line please */
	CL_ELAST_ERROR ErrorCode = C.CL_ELAST_ERROR
)

type Fmap

type Fmap C.cl_fmap_t

Fmap models in-memory files

func OpenMemory

func OpenMemory(start []byte) *Fmap

OpenMemory creates an object from the given memory that can be scanned using ScanMapCb

type SCAN_OPTIONS

type SCAN_OPTIONS struct {
	General   uint
	Parse     uint
	Heuristic uint
	Mail      uint
	Dev       uint
}

scan options

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL