[Python] Virustotal api using python

雖然本身接觸到不少病毒資料, 不過每次都靠上傳檔案到 Virustotal 實在非常的沒效率

寫程式用 url upload 也不是不行, 不過其實他是有釋出 API 可以用的

一般帳號的 API 規定 1 分鐘最多 4 個 request, 而且是透過 http post 的方法且回傳是 json 格式

( The chosen format for the API is HTTP POST requests with JSON object responses and it is limited to at most 4 requests of any nature in any given 1 minute time frame )

這篇參考的是他的 API 教學頁面, 做一個簡易的上傳跟擷取講解 (目前時間大約是 2013/12/23)
Official Source: https://www.virustotal.com/en/documentation/public-api/

而使用他的 API 需要 API key, 這需要先註冊帳號才可以

首先, 英文版右上方有一個 Join our community (中文是加入我們社群)



依序填完相關資料即可, 這邊應該是沒什麼太大的難度

但是注意信箱要填正確, 他會寄確認通知, 等點了確認通知信之後才會正式開啟

之後到 virustotal 登入, 點右上角的帳號選擇 profile, 就會出現一些相關訊息, 點API就會看到API KEY


中間那個 API KEY複製下來之後, 就可以開始使用了

(他下面的聲明是說如果你用不夠想要更多的數量需求, 再寫信跟他要)

以下都是使用 python code 為範例

Upload Suspicious File

官網是建議利用 httplib 來跟 virustotal 提供的 api 做溝通, 但有三件事情要修改跟注意

首先會看到官網有提供一段 code

import postfile
host = "www.virustotal.com"
selector = "https://www.virustotal.com/vtapi/v2/file/scan"
fields = [("apikey", "1fe0ef5feca2f84eb450bc3617f839e317b2a686af4d651a9bada77a522201b0")]
file_to_send = open("test.txt", "rb").read()
files = [("file", "test.txt", file_to_send)]
json = postfile.post_multipart(host, selector, fields, files)
print json

1. import postfile, 這個檔案必須要從另外一個網站找尋
(網站源頭: http://code.activestate.com/recipes/146306/ )

怕網站失效, 這邊節錄無註解部份

注意, 原始的 code 是使用 httplib.HTTP, 這邊要改成 httplib.HTTPS

不然 json 結果會回傳 Error 400 (Bad Request)!!1

import httplib, mimetypes

def post_multipart(host, selector, fields, files):
    content_type, body = encode_multipart_formdata(fields, files)
    h = httplib.HTTPS(host)
    h.putrequest('POST', selector)
    h.putheader('content-type', content_type)
    h.putheader('content-length', str(len(body)))
    h.endheaders()
    h.send(body)
    errcode, errmsg, headers = h.getreply()
    return h.file.read()

def encode_multipart_formdata(fields, files):
    BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
    CRLF = '\r\n'
    L = []
    for (key, value) in fields:
        L.append('--' + BOUNDARY)
        L.append('Content-Disposition: form-data; name="%s"' % key)
        L.append('')
        L.append(value)
    for (key, filename, value) in files:
        L.append('--' + BOUNDARY)
        L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
        L.append('Content-Type: %s' % get_content_type(filename))
        L.append('')
        L.append(value)
    L.append('--' + BOUNDARY + '--')
    L.append('')
    body = CRLF.join(L)
    content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
    return content_type, body

def get_content_type(filename):
    return mimetypes.guess_type(filename)[0] or 'application/octet-stream'

請將此程式碼存成 postfile.py

2. 將上上述官網的那段 code 也存成 file, 先假設為 test.py

要注意, fields 那邊有一個 apikey, 後面有1fe0e5fec...etc 這邊要改成你剛剛註冊所得到的apikey

然後他範例是讀取一個 test.txt 並且上傳, 這邊可以更改成你要上傳的檔案

成功的話, print json 應該會看到一些訊息, 跟你說上傳成功, 請你等會再來問

Query Report

上述完成的話, 會收到一些訊息, 回傳的訊息比較重要的就是 resource field

{"response_code": 1,
 "verbose_msg": "Scan request successfully queued, come back later for the report",
 "resource": "999f7d93aa3d4a1a94cccfb4ea96bc2e28fd48020a481aa2dc7e215f3ce27bc0",
 "scan_id": "999f7d93aa3d4a1a94cccfb4ea96bc2e28fd48020a481aa2dc7e215f3ce27bc0-1324376258",
 "permalink": "https://www.virustotal.com/file/999f7d93aa3d4a1a94cccfb4ea96bc2e28fd48020a481aa2dc7e215f3ce27bc0/analysis/1324376258/",
 "sha256": "999f7d93aa3d4a1a94cccfb4ea96bc2e28fd48020a481aa2dc7e215f3ce27bc0",
 "sha1": "2cc875bca8030d745adfd14388b8c001471c2474",
 "md5": "4a00e1a3a14e4fec6f2b353b4f20bb73"}

之後 query report 要傳入此值才能得到剛剛問的結果

而且後續的 code 更為簡單 (官網的 resource id 範例不一致, 我稍微偷改了一下)

import urllib
import urllib2
url = "https://www.virustotal.com/vtapi/v2/file/report"
parameters = {"resource": "999f7d93aa3d4a1a94cccfb4ea96bc2e28fd48020a481aa2dc7e215f3ce27bc0", "apikey": "1fe0ef5feca2f84eb450bc3617f839e317b2a686af4d651a9bada77a522201b0"}
data = urllib.urlencode(parameters)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
json = response.read()
print json
{
 "response_code": 1,
 "verbose_msg": "Scan finished, scan information embedded in this object",

 "resource": "999f7d93aa3d4a1a94cccfb4ea96bc2e28fd48020a481aa2dc7e215f3ce27bc0",
 "scan_id": "52d3df0ed60c46f336c131bf2ca454f73bafdc4b04dfa2aea80746f5ba9e6d1c-1273894724",
 "md5": "99017f6eebbac24f351415dd410d522d",
 "sha1": "4d1740485713a2ab3a4f5822a01f645fe8387f92",
 "sha256": "52d3df0ed60c46f336c131bf2ca454f73bafdc4b04dfa2aea80746f5ba9e6d1c",

 "scan_date": "2010-05-15 03:38:44",

 "positives": 40,
 "total": 40,

 "scans": {"nProtect": {"detected": true, "version": "2010-05-14.01", "result": "Trojan.Generic.3611249", "update": "20100514"},
           "CAT-QuickHeal": {"detected": true, "version": "10.00", "result": "Trojan.VB.acgy", "update": "20100514"},
           "McAfee": {"detected": true, "version": "5.400.0.1158", "result": "Generic.dx!rkx", "update": "20100515"},
           "TheHacker": {"detected": true, "version": "6.5.2.0.280", "result": "Trojan/VB.gen", "update": "20100514"},
           "VirusBuster": {"detected": true, "version": "5.0.27.0", "result": "Trojan.VB.JFDE", "update": "20100514"},
           "NOD32": {"detected": true, "version": "5115", "result": "a variant of Win32/Qhost.NTY", "update": "20100514"},
           "F-Prot": {"detected": false, "version": "4.5.1.85", "result": null, "update": "20100514"},
           "Symantec": {"detected": true, "version": "20101.1.0.89", "result": "Trojan.KillAV", "update": "20100515"},
           "Norman": {"detected": true, "version": "6.04.12", "result": "W32/Smalltroj.YFHZ", "update": "20100514"},
           "TrendMicro-HouseCall": {"detected": true, "version": "9.120.0.1004", "result": "TROJ_VB.JVJ", "update": "20100515"},
           "Avast": {"detected": true, "version": "4.8.1351.0", "result": "Win32:Malware-gen", "update": "20100514"},
           "eSafe": {"detected": true, "version": "7.0.17.0", "result": "Win32.TRVB.Acgy", "update": "20100513"},
           "ClamAV": {"detected": false, "version": "0.96.0.3-git", "result": null, "update": "20100514"},
           "Kaspersky": {"detected": true, "version": "7.0.0.125", "result": "Trojan.Win32.VB.acgy", "update": "20100515"},
           "BitDefender": {"detected": true, "version": "7.2", "result": "Trojan.Generic.3611249", "update": "20100515"},
           "Comodo": {"detected": true, "version": "4842", "result": "Heur.Suspicious", "update": "20100515"},
           "F-Secure": {"detected": true, "version": "9.0.15370.0", "result": "Trojan.Generic.3611249", "update": "20100514"},
           "DrWeb": {"detected": true, "version": "5.0.2.03300", "result": "Trojan.Hosts.37", "update": "20100515"},
           "AntiVir": {"detected": true, "version": "8.2.1.242", "result": "TR/VB.acgy.1", "update": "20100514"},
           "TrendMicro": {"detected": true, "version": "9.120.0.1004", "result": "TROJ_VB.JVJ", "update": "20100514"},
           "McAfee-GW-Edition": {"detected": true, "version": "2010.1", "result": "Generic.dx!rkx", "update": "20100515"},
           "Sophos": {"detected": true, "version": "4.53.0", "result": "Troj/VBHost-A", "update": "20100515"},
           "eTrust-Vet": {"detected": true, "version": "35.2.7490", "result": "Win32/ASuspect.HDBBD", "update": "20100515"},
           "Authentium": {"detected": false, "version": "5.2.0.5", "result": null, "update": "20100514"},
           "Jiangmin": {"detected": true, "version": "13.0.900", "result": "Trojan/VB.yqh", "update": "20100514"}, [...] },

 "permalink": "https://www.virustotal.com/file/52d3df0ed60c46f336c131bf2ca454f73bafdc4b04dfa2aea80746f5ba9e6d1c/analysis/1273894724/"
}

一樣, apikey 記得要更換成剛剛註冊後的 apikey, resource 欄位要改成剛剛詢問完得到的 number

就會得到結果, 基本上跟直接用web的結果差不多, 只是回傳也是 json 格式, 可以利用 json tool 去存取他, 或者轉成 dict 供後續使用

基本上就差不多是這樣了, 其實 virustotal 還可以掃描 URL, 方法幾乎如出一轍, 而且都比上傳檔案簡單, code 稍微修改就行了

這邊稍微列一下他目前有提供的 API (都要用程式存取)

https://www.virustotal.com/vtapi/v2/file/scan : 上傳檔案掃描
https://www.virustotal.com/vtapi/v2/file/rescan: 重新掃描檔案
https://www.virustotal.com/vtapi/v2/file/report: 取得上傳檔案結果
https://www.virustotal.com/vtapi/v2/url/scan: 掃描 url
https://www.virustotal.com/vtapi/v2/url/report:  取得 url 結果
http://www.virustotal.com/vtapi/v2/ip-address/report: 掃描 ip, 會傳出過去用此 ip 架站的網站以及其網站惡意的紀錄
http://www.virustotal.com/vtapi/v2/domain/report: 類似 ip, 掃描 domain, 會傳出用此 domain 架站的 ip, 以及其惡意紀錄


留言

張貼留言

這個網誌中的熱門文章

[Linux] Linux下查詢硬體記憶體資訊 Memory Information

[Other] Chrome 重新整理所有開啟頁面

[Python] Simple Socket Server