たれながし.info

とあるITエンジニアの備忘録

VirusTotalの公式APIライブラリ「vt-py」を使ってみた。


はじめに

VirusTotalの自動化について調べていたら、「vt-py」というライブラリを見つけたので使ってみる。

「vt-py」について

「vt-py」とは?

Virus Totalの公式APIに「VirusTotal API v3」があります。

で、「VirusTotal API v3」のPython用公式クライアントライブラリが「vt-py」です。
vt-py」を使うと、「VirusTotal API v3」をより簡単に利用できる(と思われます。)

<公式サイト>
GitHubhttps://github.com/VirusTotal/vt-py
ドキュメント:https://virustotal.github.io/vt-py

vt-py」以外にもサードパーティ製のライブラリがいくつか存在するようです。

動作環境

Python 3.6.0以上

できること

「vt-py」でできること

  1. ファイル、URL、ドメインなどに関する情報をVTから取得する
  2. ファイルと URL のスキャン
  3. VirusTotal Intelligence 検索の実行(詳細
  4. LiveHunt のルールセットと通知を管理する(詳細
  5. Retrohunt ジョブを起動してマッチしたものを取得する(詳細
  6. VirusTotal グラフを操作する(詳細
  7. etc...

1,2は基本無料(一部有料)、3~6は有料と思われます。
(何が無料で、何が有料なのか調べても今一つわからなかったで正しくないかも)

  • 無料:アカウント作成&Public APIキー取得
  • 有料:VirusTotal Enterprise?VirusTotal Premium Service?を購入してPremium APIキーを取得?

APIキーについて

VTのAPIには「Public API」と「Premium API」の2種類あります。

Public APIは無料ですが、1日辺りのリクエスト回数やビジネス用途で使えないといった制限があります。
Premium APIは有償サービス「VirusTotal Enterprise?」「VirusTotal Premium Service?」の購入が必要なようです。
制限の詳細は「Public vs Premium API」に記載されています。

「vt-py」を使うには、APIキーの取得が必要です。今回は「Public API」のAPIキーを取得して使います。
APIキーの取得方法は「Getting started」に記載されています。

使ってみる

「Public API」でできるいくつかの機能を確認してみます。
プログラムの基本的な流れは、以下の通りです。

  1. APIキー使ってVirusTotalに接続
  2. ファイル、URL、ドメインといった調査対象となるオブジェクトの作成と結果取得
  3. 結果を表示

「vt-py」の簡単な使い方は、「クイックスタート」に載っていますが、凝った使い方をする場合は「APIのドキュメント」読んだり、ソースコード調べたりする必要がありそうです。

「vt-py」は事前にpipでインストールします。

> pip install vt-py

ファイル情報をVTから取得する

ファイルのハッシュ値MD5, SHA-1, SHA-256)を基にVTから情報が取得できます。
取得できる情報はAPIのドキュメント「Files」に記載があります。

プログラム
EICARファイルの直近のスキャン時間とスキャン結果を取得してみます。
※「3395856ce81f2b7382dee72602f798b642f14140」はEICARファイルのSHA-1です。

import vt

apikey = "<apikey>"
filehash = "3395856ce81f2b7382dee72602f798b642f14140"

client = vt.Client(apikey)
file = client.get_object("/files/{}", filehash)

client.close()

print(file.get("last_analysis_date"))
print(file.get("last_analysis_stats"))

fileオブジェクトの情報は「vars(file)」や「dir(file)」で見ることができます。

実行結果

>>> print(file.get("last_analysis_date"))
1622838165

>>> print(file.get("last_analysis_stats"))
{'harmless': 0, 'type-unsupported': 9, 'suspicious': 0, 'confirmed-timeout': 0, 'timeout': 0, 'failure': 0, 'malicious': 61, 'undetected': 5}

ファイルをスキャンする

ファイルを送信してスキャンします。
取得できる情報はAPIのドキュメント「Analyses」に記載があります。

プログラム
試しにWindows10の計算機(calc.exe)を送信してみます。

import vt

apikey = "<apikey>"
filepath = "C:\Windows\System32\calc.exe"

client = vt.Client(apikey)

with open(filepath, "rb") as f:
    analysis = client.scan_file(f)

while True:
    analysis = client.get_object("/analyses/{}", analysis.id)
    print(analysis.status)
    if analysis.status == "completed":
        break
    time.sleep(30)

client.close()

print(analysis.get("_id"))
print(analysis.get("date"))
print(analysis.get("stats"))

実行結果

>>> print(analysis.get("_id"))
Zjg4Y2MwNTEzNGM1NTVkNGUxY2QxZGVmNzgxNjJhOWE6MTYyMjkwNzAzMg==

>>> print(analysis.get("date"))
1622907032

>>> print(analysis.get("stats"))
{'harmless': 0, 'type-unsupported': 5, 'suspicious': 0, 'confirmed-timeout': 0, 'timeout': 0, 'failure': 0, 'malicious': 0, 'undetected': 69}

URL情報をVTから取得する

import vt

apikey = "<api key>"
url = "https://google.co.jp"

client = vt.Client(apikey)
url_id = vt.url_id(url)
url = client.get_object("/urls/{}", url_id)

client.close()

print(url.get("categories"))
print(url.get("last_analysis_date"))
print(url.get("last_analysis_stats"))

URL をスキャンする

プログラム

import vt

apikey = "<apikey>"
url = "https://google.co.jp"

client = vt.Client(apikey)
analysis = client.scan_url(url)

while True:
    analysis = client.get_object("/analyses/{}", analysis.id)
    print(analysis.status)
    if analysis.status == "completed":
        break
    time.sleep(30)

client.close()

print(analysis.get("_id"))
print(analysis.get("date"))
print(analysis.get("stats"))

実行結果

>>> print(analysis.get("_id"))
u-7f7c5306ba7987cb80bedf158c4c092aa5c2d21599ec0fcda2c382289623408b-1622924400

>>> print(analysis.get("date"))
1622924400

>>> print(analysis.get("stats"))
{'harmless': 80, 'malicious': 0, 'suspicious': 0, 'undetected': 8, 'timeout': 0}

ドメイン情報をVTから取得

ドメインに関する情報をVTから取得できます。
取得できる情報はAPIのドキュメントに記載があります。

プログラム
「yahoo.co.jp」について取得してみます。

import vt

apikey = "<apikey>"
domain = "yahoo.co.jp"

client = vt.Client(apikey)
file = client.get_object("/domains/{}", domain)

client.close()

print(file.get("categories"))
print(file.get("last_analysis_stats"))
print(file.get("whois"))

実行結果

# 各サービスでのドメインの分類
>>> print(file.get("categories"))
{'Forcepoint ThreatSeeker': 'search engines and portals', 'sophos': 'portal sites', 'BitDefender': 'news', 'Comodo Valkyrie Verdict': 'mobile communications', 'alphaMountain.ai': 'Search Engines/Portals'}

# 直近のスキャン結果
>>> print(file.get("last_analysis_stats"))
{'harmless': 77, 'malicious': 0, 'suspicious': 0, 'undetected': 8, 'timeout': 0}

# whois情報
>>> print(file.get("whois"))
g. [Organization] Yahoo Japan Corporation
l. [Organization Type] Corporation
p. [ネームサーバ] ns01.yahoo.co.jp
p. [ネームサーバ] ns02.yahoo.co.jp
p. [ネームサーバ] ns11.yahoo.co.jp
p. [ネームサーバ] ns12.yahoo.co.jp

感想

単純なスキャンや情報取得であれば、今回のように「vt-py」を使うのが楽かなと思いました。

しかし、凝ったことをやる場合は「vt-py」と「VirusTotal API v3」の両方を調べることになりそうので、「VirusTotal API v3」だけ使えば良いのでは?という感想です。