This works in windows and linux, maybe in OSX too:
Code: Select all
;
; Binary versions:
;
; https://www.clamav.net/downloads#otherversions
;
; for windows you need to extract the following dlls:
;
; json-c.dll
; libbz2.dll
; libclamav.dll
; libcrypto-1_1.dll
; libmspack.dll
; libxml2.dll
; pcre2-8.dll
; pthreadVC2.dll
;
; the Clamav Virus Definition files:
;
; http://database.clamav.net/main.cvd
; http://database.clamav.net/daily.cvd
;
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
#CL_INIT_DEFAULT = 0
Enumeration
; libclamav specific
#CL_CLEAN = 0
#CL_SUCCESS = 0
#CL_VIRUS
#CL_ENULLARG
#CL_EARG
#CL_EMALFDB
#CL_ECVD
#CL_EVERIFY
#CL_EUNPACK
; I/O And memory errors
#CL_EOPEN
#CL_ECREAT
#CL_EUNLINK
#CL_ESTAT
#CL_EREAD
#CL_ESEEK
#CL_EWRITE
#CL_EDUP
#CL_EACCES
#CL_ETMPFILE
#CL_ETMPDIR
#CL_EMAP
#CL_EMEM
#CL_ETIMEOUT
; internal (Not reported outside libclamav)
#CL_BREAK
#CL_EMAXREC
#CL_EMAXSIZE
#CL_EMAXFILES
#CL_EFORMAT
#CL_EPARSE
#CL_EBYTECODE ; may be reported in testmode
#CL_EBYTECODE_TESTFAIL ; may be reported in testmode
; c4w error codes
#CL_ELOCK
#CL_EBUSY
#CL_ESTATE
; no error codes below this line please
#CL_ELAST_ERROR
EndEnumeration
; db options
#CL_DB_PHISHING = $000002
#CL_DB_PHISHING_URLS = $000008
#CL_DB_PUA = $000010
#CL_DB_CVDNOTMP = $000020 ; obsolete
#CL_DB_OFFICIAL = $000040 ; internal
#CL_DB_PUA_MODE = $000080
#CL_DB_PUA_INCLUDE = $000100
#CL_DB_PUA_EXCLUDE = $000200
#CL_DB_COMPILED = $000400 ; internal
#CL_DB_DIRECTORY = $000800 ; internal
#CL_DB_OFFICIAL_ONLY = $001000
#CL_DB_BYTECODE = $002000
#CL_DB_SIGNED = $004000 ; internal
#CL_DB_BYTECODE_UNSIGNED = $008000
#CL_DB_UNSIGNED = $010000 ; internal
#CL_DB_BYTECODE_STATS = $020000
#CL_DB_ENHANCED = $040000
#CL_DB_PCRE_STATS = $080000
#CL_DB_YARA_EXCLUDE = $100000
#CL_DB_YARA_ONLY = $200000
; recommended db settings
#CL_DB_STDOPT = (#CL_DB_PHISHING | #CL_DB_PHISHING_URLS | #CL_DB_BYTECODE)
Enumeration cl_engine_field
#CL_ENGINE_MAX_SCANSIZE ; uint64_t
#CL_ENGINE_MAX_FILESIZE ; uint64_t
#CL_ENGINE_MAX_RECURSION ; uint32_t
#CL_ENGINE_MAX_FILES ; uint32_t
#CL_ENGINE_MIN_CC_COUNT ; uint32_t
#CL_ENGINE_MIN_SSN_COUNT ; uint32_t
#CL_ENGINE_PUA_CATEGORIES ; (char *)
#CL_ENGINE_DB_OPTIONS ; uint32_t
#CL_ENGINE_DB_VERSION ; uint32_t
#CL_ENGINE_DB_TIME ; time_t
#CL_ENGINE_AC_ONLY ; uint32_t
#CL_ENGINE_AC_MINDEPTH ; uint32_t
#CL_ENGINE_AC_MAXDEPTH ; uint32_t
#CL_ENGINE_TMPDIR ; (char *)
#CL_ENGINE_KEEPTMP ; uint32_t
#CL_ENGINE_BYTECODE_SECURITY ; uint32_t
#CL_ENGINE_BYTECODE_TIMEOUT ; uint32_t
#CL_ENGINE_BYTECODE_MODE ; uint32_t
#CL_ENGINE_MAX_EMBEDDEDPE ; uint64_t
#CL_ENGINE_MAX_HTMLNORMALIZE ; uint64_t
#CL_ENGINE_MAX_HTMLNOTAGS ; uint64_t
#CL_ENGINE_MAX_SCRIPTNORMALIZE ; uint64_t
#CL_ENGINE_MAX_ZIPTYPERCG ; uint64_t
#CL_ENGINE_FORCETODISK ; uint32_t
#CL_ENGINE_DISABLE_CACHE ; uint32_t
#CL_ENGINE_DISABLE_PE_STATS ; uint32_t
#CL_ENGINE_STATS_TIMEOUT ; uint32_t
#CL_ENGINE_MAX_PARTITIONS ; uint32_t
#CL_ENGINE_MAX_ICONSPE ; uint32_t
#CL_ENGINE_MAX_RECHWP3 ; uint32_t
#CL_ENGINE_MAX_SCANTIME ; uint32_t
#CL_ENGINE_PCRE_MATCH_LIMIT ; uint64_t
#CL_ENGINE_PCRE_RECMATCH_LIMIT ; uint64_t
#CL_ENGINE_PCRE_MAX_FILESIZE ; uint64_t
#CL_ENGINE_DISABLE_PE_CERTS ; uint32_t
#CL_ENGINE_PE_DUMPCERTS ; uint32_t
EndEnumeration
; general
#CL_SCAN_GENERAL_ALLMATCHES = $1 ; scan in all-match mode */
#CL_SCAN_GENERAL_COLLECT_METADATA = $2 ; collect metadata (--gen-json) */
#CL_SCAN_GENERAL_HEURISTICS = $4 ; option To enable heuristic alerts */
#CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE = $8 ; allow heuristic match To take precedence. */
#CL_SCAN_GENERAL_UNPRIVILEGED = $10 ; scanner will Not have Read access To files. */
; parsing capabilities options
#CL_SCAN_PARSE_ARCHIVE = $1
#CL_SCAN_PARSE_ELF = $2
#CL_SCAN_PARSE_PDF = $4
#CL_SCAN_PARSE_SWF = $8
#CL_SCAN_PARSE_HWP3 = $10
#CL_SCAN_PARSE_XMLDOCS = $20
#CL_SCAN_PARSE_MAIL = $40
#CL_SCAN_PARSE_OLE2 = $80
#CL_SCAN_PARSE_HTML = $100
#CL_SCAN_PARSE_PE = $200
; heuristic alerting options
#CL_SCAN_HEURISTIC_BROKEN = $2 ; alert on broken PE And broken ELF files */
#CL_SCAN_HEURISTIC_EXCEEDS_MAX = $4 ; alert when files exceed scan limits (filesize, max scansize, Or max recursion depth) */
#CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH = $8 ; alert on SSL mismatches */
#CL_SCAN_HEURISTIC_PHISHING_CLOAK = $10 ; alert on cloaked URLs in emails */
#CL_SCAN_HEURISTIC_MACROS = $20 ; alert on OLE2 files containing macros */
#CL_SCAN_HEURISTIC_ENCRYPTED_ARCHIVE = $40 ; alert If archive is encrypted (rar, zip, etc) */
#CL_SCAN_HEURISTIC_ENCRYPTED_DOC = $80 ; alert If a document is encrypted (pdf, docx, etc) */
#CL_SCAN_HEURISTIC_PARTITION_INTXN = $100 ; alert If partition table size doesn't make sense */
#CL_SCAN_HEURISTIC_STRUCTURED = $200 ; Data loss prevention options, i.e. alert when detecting personal information */
#CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL = $400 ; alert when detecting social security numbers */
#CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED = $800 ; alert when detecting stripped social security numbers */
#CL_SCAN_HEURISTIC_STRUCTURED_CC = $1000 ; alert when detecting credit card numbers */
#CL_SCAN_HEURISTIC_BROKEN_MEDIA = $2000 ; 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 = $1
; dev options
#CL_SCAN_DEV_COLLECT_SHA = $1 ; Enables hash output in sha-collect builds - For internal use only */
#CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO = $2 ; collect performance timings */
Structure cl_scan_options
general.l
parse.l
alert.l
heuristic_alert.l
mail.l
dev.l
EndStructure
Structure cl_stat
*dir
*stattab
*statdname
entries.l
EndStructure
; Initialization
PrototypeC.i cl_init(options.l)
PrototypeC.i cl_engine_free(*engine)
; Database loading
PrototypeC.i cl_retdbdir()
PrototypeC.i cl_load(path.p-UTF8, *engine, *signo.Long, options.l)
; Error handling
PrototypeC.i cl_strerror(clerror.l)
; Engine structure
PrototypeC.i cl_engine_compile(*engine)
PrototypeC.i cl_engine_new()
; Limits
PrototypeC.i cl_engine_set_num(*engine, field.l, num.q)
PrototypeC.q cl_engine_get_num(*engine, field.l, *err.Long)
PrototypeC.i cl_engine_set_str(*engine, field.l, str.p-UTF8)
PrototypeC.i cl_engine_get_str(*engine, field.l, *err.Long)
; Database checks
PrototypeC.i cl_statinidir(dirname.p-UTF8, *dbstat.cl_stat)
PrototypeC.i cl_statchkdir(*dbstat.cl_stat)
PrototypeC.i cl_statfree(*dbstat.cl_stat)
PrototypeC.i cl_countsigs(*path.p-UTF8, countoptions.l, *sigs.Long)
; Data scan functions
PrototypeC.i cl_scanfile(file.p-UTF8, *virname, scanned, *engine, *option)
PrototypeC.i cl_scandesc(file.p-UTF8, *virname, scanned, *engine, *option)
Global cl_init.cl_init
Global cl_engine_free.cl_engine_free
Global _cl_retdbdir.cl_retdbdir
Global cl_load.cl_load
Global _cl_strerror.cl_strerror
Global cl_engine_compile.cl_engine_compile
Global cl_engine_new.cl_engine_new
Global cl_engine_set_num.cl_engine_set_num
Global cl_engine_get_num.cl_engine_get_num
Global cl_engine_set_str.cl_engine_set_str
Global _cl_engine_get_str.cl_engine_get_str
Global cl_statinidir.cl_statinidir
Global cl_statchkdir.cl_statchkdir
Global cl_statfree.cl_statfree
Global cl_countsigs.cl_countsigs
Global cl_scanfile.cl_scanfile
Global cl_scandesc.cl_scandesc
Procedure.i cl_LoadLibrary()
Protected hDLL.i
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
hDLL = OpenLibrary(#PB_Any, "libclamav.dll")
CompilerCase #PB_OS_Linux
hDLL = OpenLibrary(#PB_Any, "/usr/lib/libclamav.so")
CompilerCase #PB_OS_MacOS
hDLL = OpenLibrary(#PB_Any, "/usr/lib/libclamav.dylib") ; not sure about this
CompilerEndSelect
If hDLL <> 0
cl_init = GetFunction(hDLL, "cl_init")
cl_engine_free = GetFunction(hDLL, "cl_engine_free")
_cl_retdbdir = GetFunction(hDLL, "cl_retdbdir")
cl_load = GetFunction(hDLL, "cl_load")
_cl_strerror = GetFunction(hDLL, "cl_strerror")
cl_engine_compile = GetFunction(hDLL, "cl_engine_compile")
cl_engine_new = GetFunction(hDLL, "cl_engine_new")
cl_engine_set_num = GetFunction(hDLL, "cl_engine_set_num")
cl_engine_get_num = GetFunction(hDLL, "cl_engine_get_num")
cl_engine_set_str = GetFunction(hDLL, "cl_engine_set_str")
_cl_engine_get_str = GetFunction(hDLL, "cl_engine_get_str")
cl_statinidir = GetFunction(hDLL, "cl_statinidir")
cl_statchkdir = GetFunction(hDLL, "cl_statchkdir")
cl_statfree = GetFunction(hDLL, "cl_statfree")
cl_countsigs = GetFunction(hDLL, "cl_countsigs")
cl_scanfile = GetFunction(hDLL, "cl_scanfile")
cl_scandesc = GetFunction(hDLL, "cl_scandesc")
EndIf
ProcedureReturn hDLL
EndProcedure
Procedure.s cl_retdbdir()
Protected DBDir$, *DBDir
*DBDir = _cl_retdbdir()
If *DBDir
DBDir$ = PeekS(*DBDir, -1, #PB_UTF8)
EndIf
ProcedureReturn DBDir$
EndProcedure
Procedure.s cl_strerror(clerror.l)
Protected Error$, *Error
*Error = _cl_strerror(clerror)
If *Error
Error$ = PeekS(*Error, -1, #PB_UTF8)
EndIf
ProcedureReturn Error$
EndProcedure
Procedure.s cl_engine_get_str(*engine, field.l, *err.Long)
Protected EngineStr$, *EngineStr
*EngineStr = _cl_engine_get_str(*engine, field.l, *err.Long)
If *EngineStr
EngineStr$ = PeekS(*EngineStr, -1, #PB_UTF8)
EndIf
ProcedureReturn EngineStr$
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
Define.i hlib, retv
Define.l scanned
Define signo.Long
Define *virname, *Engine
Define dboptions.cl_scan_options
hLib = cl_LoadLibrary()
If hlib
retv = cl_init(#CL_INIT_DEFAULT)
If retv = #CL_SUCCESS
Debug "DB Dir: " + cl_retdbdir()
*Engine = cl_engine_new()
If *Engine <> 0
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
retv = cl_load(".", *Engine, signo, #CL_DB_STDOPT)
CompilerElse
retv = cl_load(cl_retdbdir() + "/.", *Engine, signo, #CL_DB_STDOPT)
CompilerEndIf
If retv = #CL_SUCCESS
Debug "Loaded signatures: " + Str(signo\l)
retv = cl_engine_compile(*Engine)
If retv = #CL_SUCCESS
retv = cl_scanfile("virus.dat", @*virname, @scanned, *Engine, @dboptions)
;Debug scanned
If retv = #CL_VIRUS
Debug "Found: " + PeekS(*virname, -1, #PB_UTF8)
Else
If retv = #CL_CLEAN
Debug "No Virus"
Else
Debug "cl_scanfile failed: " + cl_strerror(retv)
EndIf
EndIf
Else
Debug "cl_engine_compile failed: " + cl_strerror(retv)
EndIf
Else
Debug "cl_load failed: " + cl_strerror(retv)
EndIf
Else
Debug "cl_engine_new failed"
EndIf
cl_engine_free(*Engine)
Else
Debug "cl_init failed: " + cl_strerror(retv)
EndIf
Else
Debug "Was not able to load the lib"
EndIf
CompilerEndIf
I use the EICAR test virus.
The dot in cl_load() points to the current directory (my code/execuable and the vcd files are in the same directory).
So main.cvd and daily.cvd are loaded
Loaded signatures: 8540729
Win.Test.EICAR_HDB-1
You need to select the action 'leave it' in MS defender
Else the test virus will be deleted before it can be scanned by the code.