基于「ClamAv」通過python進(jìn)行病毒檢測(2)-- pyClamd控制clamd詳解

介紹pyClamd模塊一般用法和常用方法等。

我們可以使用python來控制clamd,從而操控ClamAv,需要引入第三方模塊:pyClamd

使用pyClamd控制clamd之前,必須先正確安裝帶有clamdclamav??梢詤⒖贾暗奈恼拢?/p>

一、pyClamd簡介

PyClamdclamd的python接口。clamdClamAv殺毒工具的守護(hù)進(jìn)程。

通過使用pyClamd,我們可以以一種高效而簡單的方式,為python程序添加病毒檢測功能。

二、安裝pyClamd

使用pip快速安裝:

pip install pyClamd

模塊官方文檔:

http://xael.org/pages/pyclamd-en.html

tip1:英文ok的朋友,可以直接閱讀官方文檔,當(dāng)然也可以快速瀏覽本文后,深入研究官方文檔。

tip2:pypipyClamd最后更新時(shí)間是2017年,作者可能沒有繼續(xù)維護(hù)這個(gè)項(xiàng)目了,且行且珍惜吧~

三、使用

3.1 常用方法示例

pyClamd提供了一些常用方法,包括簡單測試clamd是否可用、字節(jié)流掃描、文件/文件夾掃描等。下面,我們在python終端來測試這些方法。

第一步:打開python3命令行終端:
[root@程序員的一天 home]# python3
Python 3.7.4 (default, Sep 18 2020, 14:36:11) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> 
第二步:導(dǎo)入pyClamd:
>>> import pyclamd
>>> 
第三步:實(shí)例化一個(gè)clamd控制對象:
>>> cd = pyclamd.ClamdAgnostic()
>>> 

tip:此處為實(shí)例化的第一種方式,后文會繼續(xù)介紹另外兩種方式,包括通過網(wǎng)絡(luò)連接clamd。

第四步:測試clamd是否可連接:

如果連接成功返回True。

>>> cd = pyclamd.ClamdAgnostic()
>>> cd.ping()
True
>>> 
第五步:查看ClamAv版本:
>>> cd.version()
'ClamAV 0.103.0/25929/Sun Sep 13 21:53:46 2020'
>>> 
第六步:生成測試病毒樣本:

pyClamd提供了一個(gè)EICAR()方法,該方法可以快速生成病毒樣本,用于測試。我們先來看看樣本具體內(nèi)容:

>>> cd.EICAR()
b'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*'
>>> 

tip:可以看到輸出的是一個(gè)python字節(jié)串。雖然是病毒樣本,但是我們并沒有去執(zhí)行它,所以是無害的,大家不要擔(dān)心機(jī)器中毒?。?/p>

第七步:scan_stream()方法檢測bytes流:

scan_stream()方法用于檢測bytes流。

包括網(wǎng)絡(luò)字節(jié)流,也是可以檢測的。比如,在郵箱系統(tǒng)前,對所有的郵件字節(jié)流進(jìn)行檢測,查殺惡意郵件。

我們可以利用EICAR()方法,生成字節(jié)流來測試:

>>> cd.scan_stream(cd.EICAR())
{'stream': ('FOUND', 'Win.Test.EICAR_HDB-1')}
>>> 
>>> cd.scan_stream(b'pythonbytes')
>>> 
>>> cd.scan_stream(b'pythonbytes') is None
True
>>> 

tip:如果檢測到病毒返回字典,否則返回None。

第八步:scan_file()文件/文件夾掃描:

scan_file()方法,用于檢測文件或者文件夾。

scan_file()方法,一旦檢測到病毒,會結(jié)束掃描,立馬返回檢測到的第一個(gè)病毒結(jié)果。

如果,ClamAv采用的源碼編譯方式安裝,那么在ClamAV的源碼解壓包中有一個(gè)test文件夾,里面全部都是ClamAv提供的病毒測試樣本:

[root@程序員的一天 clamAv]# ls
clamav-0.103.0  clamav-0.103.0.tar.gz
[root@程序員的一天 clamAv]# 
[root@程序員的一天 clamAv]# ls clamav-0.103.0/test
clam.7z           clam_cache_emax.tgz  clam.exe.bz2          clam.impl.zip       clam.mail       clam-pespin.exe  clam-upx.exe     Makefile.am
clam.arj          clam.chm             clam.exe.html         clam_IScab_ext.exe  clam-mew.exe    clam-petite.exe  clam-v2.rar      Makefile.in
clam-aspack.exe   clam.d64.zip         clam.exe.mbox.base64  clam_IScab_int.exe  clam.newc.cpio  clam.ppt         clam-v3.rar      README
clam.bin-be.cpio  clam.ea05.exe        clam.exe.mbox.uu      clam_ISmsi_ext.exe  clam-nsis.exe   clam.sis         clam-wwpack.exe
clam.bin-le.cpio  clam.ea06.exe        clam.exe.rtf          clam_ISmsi_int.exe  clam.odc.cpio   clam.tar.gz      clam-yc.exe
clam.bz2.zip      clam.exe             clam.exe.szdd         clam.iso            clam.ole.doc    clam.tnef        clam.zip
clam.cab          clam.exe.binhex      clam-fsg.exe          clamjol.iso         clam.pdf        clam-upack.exe   Makefile
[root@程序員的一天 clamAv]# 

tip:不要輕易持續(xù)掃描test文件夾,因?yàn)槿渴遣《緲颖?,掃描會非常慢(也許可以用于測試ClamAv掃描性能)。可以指定其中的具體某個(gè)文件測試,或者重新生成新的樣本文件測試。

我們可以用這些文件來測試,也可以利用EICAR()方法,將病毒字節(jié)串寫入文件,來生成新的樣本文件測試。我這里使用生成新文件測試。

tmp目錄下生成EICARNO_EICAR文件:

>>> void = open('/tmp/EICAR','w').write(cd.EICAR().decode())
>>> void = open('/tmp/NO_EICAR','w').write('no virus in this file')
>>> 

tip:這里在/tmp目錄下生成了EICARNO_EICAR文件,分別代表病毒樣本文件和正常文件。

scan_file()方法傳入具體文件路徑,進(jìn)行文件掃描

>>> cd.scan_file('/tmp/EICAR')
{'/tmp/EICAR': ('FOUND', 'Win.Test.EICAR_HDB-1')}
>>> 
>>> cd.scan_file('/tmp/NO_EICAR') is None
True
>>> 

tip:一旦檢測到病毒,立馬返回字典,key為具體文件,value為檢測結(jié)果。否則返回None。

同樣,也可以傳入一個(gè)文件夾路徑作為scan_file()方法參數(shù),進(jìn)行文件夾掃描

>>> cd.scan_file('/tmp')      
{'/tmp/EICAR': ('FOUND', 'Win.Test.EICAR_HDB-1')}
>>> 

tip:掃描到第一個(gè)病毒文件后,結(jié)束掃描,返回結(jié)果。

第九步:contscan_file()文件/文件夾掃描:

contscan_file()方法,同樣用于文件/文件夾掃描。

scan_file()方法掃描不同的是,contscan_file()方法會在整個(gè)文件夾全部掃描完后,返回檢測到的所有病毒文件。

為了方便測試,我們在/tmp目錄下再生成一個(gè)EICAR_1樣本文件。然后掃描/tmp目錄:

>>> void = open('/tmp/EICAR_1','w').write(cd.EICAR().decode())
>>> 
>>> cd.contscan_file('/tmp/')
{'/tmp/EICAR': ('FOUND', 'Win.Test.EICAR_HDB-1'),  '/tmp/EICAR_1': ('FOUND', 'Win.Test.EICAR_HDB-1')}
>>> 
>>> cd.scan_file('/tmp') 
{'/tmp/EICAR': ('FOUND', 'Win.Test.EICAR_HDB-1')}
>>> 

tip:可以看到scan_file()方法只返回了一個(gè)結(jié)果,而contscan_file()方法會掃描完整個(gè)文件目錄后,返回檢測到的所有威脅文件。

同樣的,contscan_file()也可以用于單個(gè)文件掃描:

>>> cd.contscan_file('/tmp/EICAR_1')
{'/tmp/EICAR_1': ('FOUND', 'Win.Test.EICAR_HDB-1')}
>>> 
>>> cd.contscan_file('/tmp/EICAR')  
{'/tmp/EICAR': ('FOUND', 'Win.Test.EICAR_HDB-1')}
>>> 

3.2 pyClamd連接clamd方式總結(jié)

在源碼編譯安裝ClamAv,配置clamd時(shí),我們介紹過:如果要允許clamd和其他應(yīng)用程序通信,至少啟用以下選項(xiàng)之一:

# 本地套接字通信
LocalSocket
# 網(wǎng)絡(luò)套接字通信
TCPSocket

比如,這樣配置:

# LocalSocket /tmp/clamd.socket
TCPSocket 3310

tip:通過tcp套接字,在3310端口通信。

同樣的,pyClamdclamd通信,也對應(yīng)了這兩種方式。

pyClamd中,提供了兩個(gè)類,來連接clamd。分別為:

ClamdUnixSocket()
ClamdNetworkSocket()

上面我們使用的ClamdAgnostic()是一個(gè)自動(dòng)選擇的封裝方法。

tip:需要注意的是,不管哪種方法連接,創(chuàng)建實(shí)例化對象后,所有的常用方法都一樣。

接下來,我們分別對它們進(jìn)行介紹。

3.2.1、ClamdAgnostic()方法

ClamdAgnostic()方法,自動(dòng)選擇連接方法。

ClamdAgnostic()方法,首先嘗試使用ClamdUnixSocket連接到clamd。如果失敗,嘗試
使用ClamdNetworkSocket連接。最后返回相應(yīng)的實(shí)例化對象。

在pyclamd.py中ClamdAgnostic()方法定義為:

tip:pyclamd.pypyClamd庫的主要模塊,我們甚至可以直接把這個(gè)文件放入到程序中,而不使用pip安裝pyClamd。

############################################################################

def ClamdAgnostic():
    """
    Tries to connect to clamd using ClamdUnixSocket or if it fails, tries
    with ClamdNetworkSocket and return the corresponding object.
    Of course, it tries to connect with default settings...
    """
    try:
        # Create object for using unix socket
        cd = ClamdUnixSocket()
    except ConnectionError:
        # if failed, test for network socket
        try:
            cd = ClamdNetworkSocket()
        except ConnectionError:
            raise ValueError("could not connect to clamd server either by unix or network socket")
    return cd

############################################################################

如果,我們在同一臺機(jī)器上,通過python控制clamd,那么使用這個(gè)方法就足夠了。具體實(shí)例化示例如下:

>>> cd = pyclamd.ClamdAgnostic()
>>> 
3.2.2、ClamdUnixSocket()

ClamdUnixSocket()使用本地套接字,用于同一臺計(jì)算機(jī)下進(jìn)程通信。

需要clamd.conf中配置LocalSocket選項(xiàng):

# 指定本地套接字路徑
LocalSocket /tmp/clamd.socket

ClamdUnixSocket()部分源碼如下:

class ClamdUnixSocket(_ClamdGeneric):
    """
    Class for using clamd with an unix socket
    """
    def __init__(self, filename=None, timeout=None):
        """
        Unix Socket Class initialisation

        filename (string) : unix socket filename or None to get the socket from /etc/clamav/clamd.conf or /etc/clamd.conf
        timeout (float or None) : socket timeout
        """

        # try to get unix socket from clamd.conf
        if filename is None:
            for clamdpath in ['/etc/clamav/clamd.conf', '/etc/clamd.conf']:
                if os.path.isfile(clamdpath):
                    break
            else:
                raise ConnectionError('Could not find clamd unix socket from /etc/clamav/clamd.conf or /etc/clamd.conf')

可以看到,ClamdUnixSocket()能夠接收兩個(gè)傳入?yún)?shù):

# 指定本地套接字
filename
# 設(shè)置連接超時(shí)
timeout

如果,同一臺計(jì)算機(jī)上,我們希望指定本地套接字,來控制clamd,那么可以實(shí)例化ClamdUnixSocket()類:

>>> cd = pyclamd.ClamdUnixSocket(filename='/tmp/clamd.socket', timeout=10)
>>> 

tip:需要對應(yīng)的本地套接字存在。

3.2.3、ClamdNetworkSocket()

ClamdNetworkSocket()類,允許通過網(wǎng)絡(luò)套接字來控制clamd

需要clamd.conf中配置TCPSocket選項(xiàng):

# 配置監(jiān)聽端口
TCPSocket 3310
# 配置監(jiān)聽地址,默認(rèn)為0.0.0.0
TCPAddr 127.0.0.1

ClamdNetworkSocket()部分源碼如下:

class ClamdNetworkSocket(_ClamdGeneric):
    """
    Class for using clamd with a network socket
    """
    def __init__(self, host='127.0.0.1', port=3310, timeout=None):
        """
        Network Class initialisation
        host (string) : hostname or ip address
        port (int) : TCP port
        timeout (float or None) : socket timeout
        """

可以看到,ClamdNetworkSocket()能夠接收三個(gè)傳入?yún)?shù):

# 指定clamd監(jiān)聽地址
host
# 指定clamd監(jiān)聽端口
port
# 設(shè)置連接超時(shí)
timeout

通過ClamdNetworkSocket(),我們可以跨機(jī)器,通過網(wǎng)絡(luò)套接字來遠(yuǎn)程控制clamd。實(shí)例化ClamdNetworkSocket()類:

>>> cd = pyclamd.ClamdNetworkSocket(host='127.0.0.1', port=3310, timeout=10)
>>> 

到此,pyClamd介紹完畢!
END.

我的部分文章會首發(fā)在公眾號上。微信讀者,可以搜一搜:【程序員的一天】,感興趣的朋友可以關(guān)注,支持一下,謝謝!

每一個(gè)關(guān)注、點(diǎn)贊,都是極大的支持和鼓勵(lì)。最后,非常感謝閱讀。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容