diff --git a/clamav-devel/ChangeLog b/clamav-devel/ChangeLog index 155c86de5..3bf157463 100644 --- a/clamav-devel/ChangeLog +++ b/clamav-devel/ChangeLog @@ -1,3 +1,13 @@ +Wed Apr 21 00:27:18 CEST 2004 (tk) +---------------------------------- + * libclamav: scanners: + + scan full OLE2 directory (Trog); + + ignore popular file types (Dirk Mueller ) + + improve compression ratio calculation (Dirk Mueller) + + detect more mail file types + * clamscan: add --max-ratio option (Dirk Mueller) + * docs: update Japanese documentation (Masaki Ogawa ) + Tue Apr 20 15:18:58 BST 2004 (njh) ---------------------------------- * clamav-milter: Handle hostaddr == NULL @@ -14,9 +24,9 @@ Mon Apr 19 23:11:48 BST 2004 (njh) ---------------------------------- * clamav-milter: Added --from Return SMFIS_TEMPFAIL on some out of memory errors (some still to do), - based on an idea by Joe Maimon + based on an idea by Joe Maimon Quarantine messages now sorted by date, based on an idea by Christian - Pelissier . + Pelissier . Started code to parse header to find the real infected machine, email notification now contain the first received header, which may (or may not) be helpful diff --git a/clamav-devel/README b/clamav-devel/README index a59f73461..f93eb0bac 100644 --- a/clamav-devel/README +++ b/clamav-devel/README @@ -60,7 +60,7 @@ of mirrors by looking at their ip source address when they try to resolve database.clamav.net. Our DNS servers can answer with a CNAME to: europe.clamav.net, america.clamav.net, asia.clamav.net or other.clamav.net. Our advanced push-mirroring mechanism (maintained by Luca Gibelli) allows -database maintainers to update all the mirrors in less then one minute ! +database maintainers to update all the mirrors in less than one minute ! There will be no major feature enhancements in the 0.7x series. Our work diff --git a/clamav-devel/aclocal.m4 b/clamav-devel/aclocal.m4 index b3255c84c..e6fc84233 100644 --- a/clamav-devel/aclocal.m4 +++ b/clamav-devel/aclocal.m4 @@ -81,7 +81,7 @@ dnl there is now a CREATE_PREFIX_TARGET_H in this file as a shorthand for dnl PREFIX_CONFIG_H from a target.h file, however w/o the target.h ever created dnl (the prefix is a bit different, since we add an extra -target- and -host-) dnl -dnl @version: $Id: aclocal.m4,v 1.34 2004/04/16 12:50:53 kojm Exp $ +dnl @version: $Id: aclocal.m4,v 1.35 2004/04/20 22:33:18 kojm Exp $ dnl @author Guido Draheim STATUS: used often AC_DEFUN([AC_CREATE_TARGET_H], @@ -4041,7 +4041,7 @@ dnl AC_COMPILE_CHECK_SIZEOF(ptrdiff_t, $headers) dnl AC_COMPILE_CHECK_SIZEOF(off_t, $headers) dnl dnl @author Kaveh Ghazi -dnl @version $Id: aclocal.m4,v 1.34 2004/04/16 12:50:53 kojm Exp $ +dnl @version $Id: aclocal.m4,v 1.35 2004/04/20 22:33:18 kojm Exp $ dnl AC_DEFUN([AC_COMPILE_CHECK_SIZEOF], [changequote(<<, >>)dnl diff --git a/clamav-devel/clamd/others.c b/clamav-devel/clamd/others.c index 61a5847c7..1d18d0f32 100644 --- a/clamav-devel/clamd/others.c +++ b/clamav-devel/clamd/others.c @@ -60,19 +60,17 @@ void virusaction(const char *virname, const struct cfgstruct *copt) cmd = strdup(cpt->strarg); - buffer = (char *) mcalloc(strlen(cmd) + strlen(virname) + 10, sizeof(char)); - if((pt = strstr(cmd, "%v"))) { + buffer = (char *) mcalloc(strlen(cmd) + strlen(virname) + 10, sizeof(char)); *pt = 0; pt += 2; strcpy(buffer, cmd); strcat(buffer, virname); strcat(buffer, pt); free(cmd); cmd = strdup(buffer); + free(buffer); } - free(buffer); - /* WARNING: this is uninterruptable ! */ system(cmd); diff --git a/clamav-devel/clamscan/manager.c b/clamav-devel/clamscan/manager.c index f8179aa25..bbb46e907 100644 --- a/clamav-devel/clamscan/manager.c +++ b/clamav-devel/clamscan/manager.c @@ -151,6 +151,10 @@ int scanmanager(const struct optstruct *opt) else limits->maxreclevel = 5; + if(optl(opt, "max-ratio")) + limits->maxratio = atoi(getargl(opt, "max-ratio")); + else + limits->maxratio = 200; #ifdef C_LINUX if(stat("/proc", &sb) == -1) diff --git a/clamav-devel/clamscan/options.c b/clamav-devel/clamscan/options.c index b96513869..19f2bd115 100644 --- a/clamav-devel/clamscan/options.c +++ b/clamav-devel/clamscan/options.c @@ -75,6 +75,7 @@ int main(int argc, char **argv) {"include", 1, 0, 0}, {"max-files", 1, 0, 0}, {"max-space", 1, 0, 0}, + {"max-ratio", 1, 0, 0}, {"max-recursion", 1, 0, 0}, {"disable-archive", 0, 0, 0}, {"no-archive", 0, 0, 0}, diff --git a/clamav-devel/docs/Japanese/clamav.html b/clamav-devel/docs/Japanese/clamav.html index 9fae4e3c6..eb4d95b64 100644 --- a/clamav-devel/docs/Japanese/clamav.html +++ b/clamav-devel/docs/Japanese/clamav.html @@ -4,301 +4,1831 @@ + + + Clam Antivirusに関するメモ + + + +

Clam Antivirusに関するメモ

-

作成日: 2002年8月16日

-

作成者: 小川真樹

+

目次

+
+
1. Clam Antivirusについて +
+
1.1. Clam Antivirusについて
+
1.2. Clam Antivirus ホームページ
+
1.3. ClamAVの能力 +
+
1.3.1. "in the wild"ウイルスへの対応
+
1.3.2. 新種のウイルスへの対応
+
1.3.3. ウイルスの駆除・修復
+
1.3.4. どの程度使い物になるのか
+
+
+
1.4. 未対応のウイルスに対応するまでの流れ +
+
1.4.1. 未対応のウイルスを見かけたら
+
1.4.2. VirusDBチームへウイルスを提供する
+
1.4.3. シグネチャの作成
+
1.4.4. ウイルスデータベース更新のお知らせ
+
+
+
+
+ +
2. インストール +
+
2.1. Clam Antivirusの入手
+
2.2. 必要なもの
+
2.3. clamavユーザ/グループの作成
+
2.4. インストール
+
+
+ +
3. ウイルスデータベースの更新 +
+
3.1. データベースの構成
+
3.2. freshclam +
+
3.2.1. freshclam実行例
+
3.2.2. freshclamのオプション
+
3.2.3. cronで自動更新
+
3.2.4. デーモンとして実行
+
3.2.5. 注意点
+
3.2.6. freshclamの戻り値
+
+
+
+
+ +
4. ウイルスの検出 +
+
4.1. clamscan +
+
4.1.1. clamscanのオプション
+
4.1.2. clamscanの実行例
+
4.1.3. clamscanの戻り値
+
+
+
4.2. clamd +
+
4.2.1. clamd
+
4.2.2. clamav.confの設定
+
4.2.3. clamdの実行例
+
4.2.4. clamdとの通信
+
4.2.5. clamdscan
+
4.2.6. clamdscanのオプション
+
4.2.7. clamdscanの戻り値
+
+
+
4.3. Dazuko+Clamuko +
+
4.3.1. Dazuko
+
4.3.2. Clamuko
+
+
+
+
+ +
5. ClamAV関連のソフト +
+
5.1. MTA +
+
5.1.1. AMaViS/amavisd
+
5.1.2. AMaViS-ng
+
5.1.3. amavisd-new
+
5.1.4. mailscanner
+
5.1.6. OpenProtect
+
5.1.7. clamav-milter
+
5.1.8. mimedefang
+
5.1.9. IVS Milter
+
5.1.10. smtp-vilter
+
5.1.11. j-chkmail
+
5.1.12. nclamd,nclamav-milter
+
5.1.13. qmail-scanner
+
5.1.14. clamdmail
+
5.1.15. qscanq
+
5.1.16. Gadoyanvirus
+
5.1.17. exiscan
+
5.1.18. scanexi
+
5.1.19. sagator
+
5.1.20. cgpav
+
+
+
5.2. MUA周辺 +
+
5.2.1. POP3 Virus Scanner Daemon
+
5.2.2. Sylpheed-Claws
+
5.2.3. Mutt
+
+
+
5.3. その他メール関連 +
+
5.3.1. ClamAssassin
+
5.3.2. trashscan
+
5.3.3. mailman-clamav
+
5.3.4. mailgraph
+
+
+
5.4. その他のサーバ +
+
5.4.1. samba-vscan
+
5.4.2. mod_clamav
+
5.4.3. PureFTPd
+
5.4.4. Viralator
+
+
+
5.5. CD-ROM +
+
5.5.1. INSERT
+
5.5.2. Local Area Security
+
+
+
5.6. その他 +
+
5.6.1. Mail::ClamAV
+
5.6.2. clamavr
+
5.6.3. wbmclamav
+
5.6.4. Scan Log Analyzer
+
5.6.5. ClamWin Antivirus
+
+
+
+
+ +
6. シグネチャの管理・自作 +
+
6.1. VirusDBの構造 +
+
6.1.1. cvdファイルの書式
+
6.1.2. シグネチャの書式
+
6.1.3. VirusDBまとめ
+
+
+
6.2. sigtool +
+
6.2.1. sigtoolのオプション
+
6.2.2. sigtool実行例
+
+
+
6.3. シグネチャの自作・使用 +
+
6.3.1. sigtoolによるシグネチャの作成
+
6.3.2. 手動でのシグネチャの作成
+
6.3.3. 自家製シグネチャの使用
+
+
+
6.4. Netsky.Q用のシグネチャ作成例 +
+
6.4.1. シグネチャの自作こそがClamAVの醍醐味
+
6.4.2. 誰でも簡単に作成可能(責任はもちませんけど)
+
6.4.3. vimエディタで
+
6.4.4. 検出テスト
+
6.4.5. 自家製シグネチャの完成
+
+
+
-

1. Clam Antivirus

+
7. 自作プログラムでclamavを利用する +
+
7.1. libclamav
+
7.2. clamdの利用
+
+
-

1.1 Clam Antivirusについて

+
8. この文書について
+
9. TODO
+
+ +

1. Clam Antivirusについて

+ +

1.1. Clam Antivirusについて

- Clam AntivirusはTomasz Kojmによる、各種UNIX系のシステム(MacOSXも含む)で動作するアンチウィルスソフトです。WindowsでもCygwin上で動作するようです。オープンソースで、GPLライセンスに基づいて利用することができます。また、同じくフリーのOpenAntiVirus(http://www.openantivirus.org/)プロジェクトのウィルスデータベースを利用しています。 + Clam AntivirusはTomasz Kojmによる、LinuxやBSD、Mac OS Xなど各種UNIX系のシステムで動作するアンチウイルスソフトです。シグネチャによるパターンマッチング方式を採用していて、現在約20,700種類(2004年3月23日)のウイルスに対応しています。最も大きな特徴としてはGPLライセンスに従って利用することができるオープンソースのソフトウェアであるということがあります。

- -

1.2 ホームページ

- +
+

1.2. Clam Antivirusについての情報

- Clam Antivirusについての最新かつ正確な情報、ソースコードはhttp://clamav.elektrapro.com/にあります。 + Clam Antivirusについての最新かつ正確な情報、ソースコードなどはhttp://www.clamav.net/にあります。

- -

2. Clam AntiVirusのインストール

- -

2.1 Clam AntiVirusの入手

-

- ソースコードはhttp://clamav.elektrapro.com/から入手することができます。2002年8月16日時点での最新のバージョンは0.23のようです。 + googleなどで検索するときは「clam antivirus」や「clamav」などのキーワードをもとにして探すとよいでしょう。

+
-

2.2 clamavユーザの作成

+

1.3. ClamAVの能力

-

- Clam Antivirusをインストールする前に'clamav'というユーザとグループを作成する必要があります。(Cygwinではこの作業は必要ありません。) -

- -

-  LinuxやSolarisの例
-  
-    # groupadd clamav
-    # useradd -g clamav -s /bin/false -c "Clam Antivirus" clamav
+  

1.3.1. "in the wild"ウイルスへの対応

+

+ ウイルス対策ソフトが十分な品質を備えているかどうかを判断するにはAV-Test.orgVirus Bulletinなどの中立的な機関によって検査され、認められているかどうかが重要で、そのためにはITW(in the wild)ウイルスをほぼ完全に検出できることが重要です。 +

+

+ ITWウイルスは実際に世間に流通し感染の可能性があるとされるコンピュータウイルスのことで、WildList Organizationでは世界中から実際に感染報告のあったウイルスを定期的にまとめています。 +

+

+ ClamAVは未だにこれらの中立的な機関によって公式に評価されていません。評価するまでもない、というのが現時点での評価だといえますが、それに近い方法で評価されたことはあります。 +

+
    +
  • + Fridrik SkulasonがITWウイルスをOpenAntivirusのVirusHammerで検出する実験を行い、その結果が2002年10月29日に報告されました
    + Fridrik Skulasonは実際には他の商用アンチウイルス製品の組織に属していたので中立な立場ではありませんが、この結果によるとVirusHammerが正しく検出できたのは197種類のウイルスに対して正しく検出できたのはそのうち36種類です。ClamAVのVirusDBはOpenAntivirusのものに由来があり、当時ClamAVとOpenAntivirusのVirusDBはほぼ同程度のウイルス(6,000〜7,000種類程度)に対応していたので、この実験結果はその当時のClamAVについてもほぼあてはまるといえるでしょう。 +
  • +
  • + web.deが提供している無料メールサービスにClamAVが採用された件についてのドイツのHeise Online2003年12月4日の記事(ドイツ語)(参考: 英語訳)の中で、 + Heise Onlineがav-test.deのAndreas MarxにClamAVの評価を依頼しITW(in the wild)ウイルスに対してclamavの検査が行われ、716種類のウイルスのうち242種類、全体の33.8%がウイルスとして検出されたという結果が報告されています。検出されなかったウイルスの大半はマクロウイルスかpolymorphicウイルスであるということです。 +
  • +
  • + ドイツのTUV Saarlandは2004年1月にweb.deGMXなどの電子メールホスティングサービスで採用しているアンチウイルス製品について検査を行い、Wildlistのリストに基づいて選別した734個のITWウイルスのうちSymantec製品とSophos製品は100%をウイルスとして検出したが、ClamAVは399個(54.36%)にとどまったとしています(2004年2月24日付)。
    +
    参考:
    +
    GMXによるプレスリリース(ドイツ語)
    +
    Sophosによるプレスリリース(sophos.co.jp)
    +
    www.tekit.de(検査の詳細)
    +
  • +
+

+ ClamAVの作者Tomasz KojmはWildlist.orgについてこんなことを言っています。 +

+
+

少なくともSymantecはWildList.orgのウイルスのサンプルの全てを入手できる。なぜなら、この「独立」の組織はとりわけSARC(Symantec AntiVirus Research Center、Symantecのウイルス研究所)のスタッフによって設立されているからだ。

+

heise.deの不正な記事(この記事でheise.deはClamAVを採用したweb.deを批判している)が公開された後に、わたしたちはWildList.orgにコンタクトをとった(Sat, 06 Dec 2003 10:56:33 +0100)が、彼らからの返答は一切ない。

+

個人的には、この試験(TUV Saarlandによるもの)は中立(independent)のものではないと思う。特に、SophosやSymantecが'100%'であることのほうにむしろ驚いている。なぜなら、わたしたちはこの二つの製品が検出できないウイルスのサンプルを(最近のものを含めて)たくさん所有しているからだ。いずれにしろ、ClamAVだけでなくWildList.orgやドイツの著名なアンチウイルス専門家たちも自身のITWコレクションを更新すべきだろう。

+ Re: [Clamav-users] GMX Systematic Comparisonより引用・日本語訳・注釈 +
+

+ ということで、WildList.orgを絶対視することに懐疑的のようです。 +

+
+

1.3.2. 新種のウイルスへの対応

+

+ ITWウイルスの検出能力の他に、新種のウイルスへの対応の早さはアンチウイルス製品の品質を評価するための重要な要素といえます。ClamAVプロジェクトではClamAVそのものの開発以外にシグネチャ開発のためのVirusDBチームがあり今のところ数名がそれに携わっています。現在では彼らの尽力と多くの人からの素早いウイルス提供により、新種のウイルスへの対応は他の商用製品と比べて遜色のないレベルにあるといってよいと思います(参考: Sophosとclamavとの比較)。実際、2004年1月末頃に爆発的に流行したMyDoom.Aウイルス(ClamAVではSCO.A)のように、ClamAVが他の商用アンチウイルス製品に先んじて最も早く対応することも特に珍しいことではありません。 +

+

+ 課題として、VirusDBチームが欧米在住のメンバーで構成されていて東アジア・オセアニア在住の人間が今のところ参加していないので時間帯によってはむらができる可能性があることや、VirusDBチームの安定した組織としての運用を続けて実績を積む必要があるといったところでしょうか。 +

+

+ また、オープンソースですからVirusDBチームが対応する前に自前でシグネチャを作成して対応してしまえるという、商用製品にはない長所もあります。 +

+
+

1.3.3. ウイルスの駆除・修復

+

+ ClamAVはウイルスに感染したファイルそのものを削除することはできますが、感染したファイルを修復して安全なものにすることはできません。 +

+
+

1.3.4. どの程度使い物になるのか

+

+ アンチウイルスの分野においてオープンソースのソフトが遅れをとっている原因に、「プログラムを作ること自体は難しくはないが、次々と増えていくウイルスに対応するだけのコストをかけられないから」という意見を耳にしたことがありますが、実際には逆のようで、ClamAVの現状は「新種のウイルスへの対応の早さはいい線をいっているが、マクロウイルスやpolymorphicウイルス等への対応が遅れている」といったところでしょうか(マクロウイルスについてはバージョン0.70-rc以降から対応)。結論としてClamAVはまだまだ発展途上、商用製品と肩を並べるまでには至っていません。 +

+

+ で、ここから先は専門家でもないわたしの主観。clamav-0.11の頃から約2年間使っている感想では「かなり使える」とは思います。実際、予想外にウイルスを検出するので驚く人は多いはず。ITWウイルスの検出率は「種類」に対する率であって、そのウイルスに遭遇する頻度などを考慮するならもう少し数値は高くなるんじゃないかと思うので「まったく使いものにならない」というほどではないんじゃないかと。しかもだんだんと着実に良くなっているし。すでに商用製品を使用している場合でもClamAVを加えて二重にチェックさせるのは効果的な方法だと思います。でもバージョン0.70-rcから対応しているとはいえ、マクロウイルスにはまだまだ弱いし、polymorphicウイルス等、課題は多いし。彼らに偏見がないとは思わないけれど、ClamAVのことを「おもちゃ」と呼ぶアンチウイルス専門家はまだまだ多いです。 +

+
+
- MacOSXの例(この例ではuidとgidを402で作成しています) - - $ sudo niutil -create / /groups/clamav - $ sudo niutil -createprop / /groups/clamav gid 402 - $ sudo niutil -createprop / /groups/clamav passwd '*' - $ sudo niutil -create / /users/clamav - $ sudo niutil -createprop / /users/clamav uid 402 - $ sudo niutil -createprop / /users/clamav gid 402 - $ sudo niutil -createprop / /users/clamav passwd '*' - $ sudo niutil -createprop / /users/clamav realname 'Clam Antivirus' - $ sudo niutil -createprop / /users/clamav home /dev/null - $ sudo niutil -createprop / /users/clamav shell /dev/null - - ※NetInfo Managerを使ってGUIで作成してもかまいません。 - +

1.5. 未対応のウイルスに対応するまでの流れ

-

2.3 コンパイル・インストール

- +

1.5.1. 未対応のウイルスを見かけたら

+

+ clamavで検出できないウイルスを見つけたら、念のためfreshclamコマンドでウイルスデータベースが最新であることを確かめてからもう一度clamscanコマンドを試してみましょう。 + Webでのオンラインスキャンも可能です。 +

+
+

1.5.2. VirusDBチームへウイルスを提供する

+

+ ウイルスのシグネチャを作るためには、対象になるウイルスが必要です。ClamAV VirusDB submissionからウイルスを提供すると、VirusDBチームはそのウイルスをもとにシグネチャを作成できます。 +

+
+

1.5.3. シグネチャの作成

+

+ ウイルスが提供されると、VirusDBチームはそのウイルスが本当にウイルスか、未対応のウイルスか、などを調べ、シグネチャを作成し、ウイルスデータベースに登録します。 +

+
+

1.5.4. ウイルスデータベース更新のお知らせ

+

+ ウイルスデータベースを更新すると、VirusDBチームはvirusdbメーリングリストにメールで告知します。提供されたウイルスが実際にはウイルスではなかったり既に対応済みであった場合でも、このメーリングリストで告知されます。また、このメーリングリストのアーカイブを調べればどの頻度で更新されているか、などがわかります。 +

+
+
+ +
+ +

2. インストール

+ +

2.1. Clam Antivirusの入手

+

+ ソースコードはhttp://www.clamav.net/から入手することができます。また、FreeBSDやOpenBSDではPortsを利用することができます。それから、Debian LinuxやVine Linux等、Linuxディストリビューションによってはバイナリパッケージが用意されている場合もあります。 +

+
+

2.2. 必要なもの

+

+ バイナリパッケージを利用せずにソースからインストールする場合にはgccやmakeなどの開発環境とzlibが必要です。また、bzip2ライブラリはbzip2で圧縮されたファイルを検査するために、GNUmp(gmp)はVirusDBの電子署名を検証するためにそれぞれ必要とされますが必須ではありません。 +

+
+

2.3. clamavユーザ/グループの作成

- 他の多くのソフトと同様の手順でコンパイルおよびインストールできるでしょう。GNU makeが必要になります。 + Clam Antivirusをインストールする前に'clamav'というユーザとグループを作成する必要があります。

+
    +
  • LinuxやSolarisの例 +
    
    + # groupadd clamav
    + # useradd -g clamav -s /bin/false -c "Clam Antivirus" clamav
    +  
    +
  • +
  • MacOSXの例(この例ではuidとgidを402として作成しています) +
    
    + $ echo 'clamav:*:402:Clam AntiVirus' | sudo niload group /
    + $ echo 'clamav:*:402:402::0:0:Clam Antivirus:/tmp:/dev/null' | \
    + > sudo niload passwd /
    +  
    + ※NetInfo Managerを使ってGUIで作成してもかまいません。 +
  • +
+
+

2.4. インストール

+

他の一般的なソフトと同様の手順でインストールできます。

+

- $ zcat clamav-0.23.tar.gz | tar xvf -
- $ cd clamav-0.23
+ $ zcat clamav-0.xx.tar.gz | tar xvf -
+ $ cd clamav-0.xx
  $ ./configure
  $ make
  $ sudo make install
  
-

3. ウィルスのスキャン

+

インストール直後には必ずfreshclamコマンドを実行してウイルスデータベースを最新のものに更新しましょう。

+ +

+ $ sudo /usr/local/bin/freshclam
+ 
+ +
+
-

3.1 clamscan

+

3. ウイルスデータベースの更新

+

3.1. データベースの構成

- clamscanコマンドを使って、ウィルスに感染しているファイルがないか検査します。 + ウイルスデータベース関連のファイルは通常 (prefix)/share/clamav/ ディレクトリ内にあります。

-

3.1.1 主なコマンド実行例

+
main.cvd
+
ほとんどのウイルスのシグネチャを格納するファイル
+
daily.cvd
+
最近追加されたシグネチャを格納するファイル。ここに収録されたシグネチャはしばらく後にmain.cvdに移動されます。
+
mirrors.txt
+
freshclamでウイルスデータベースを更新する際に同期するサイトを設定するファイル。
+
その他(*.db)
+
ファイル名の末尾を.dbにすると、clamavはそのファイルからもウイルスのシグネチャを読み込みます。自作のシグネチャを登録する場合に使用します。
+
+
+

3.2. freshclam

+

freshclamはウイルスデータベースをHTTP経由で最新の状態に更新します。

+ +

3.2.1. freshclam実行例

+
+
# freshclam
+
手動でアップデート
+
# freshclam -d -c 24
+
デーモンとして実行し、1日に24回更新のチェックを行う
+
+
+ +

3.2.2. freshclamのオプション

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
--help-h使い方を表示
--version-Vバージョン情報を表示
--verbose-v出力を詳細にする
--debug デバッグ情報を出力
--quiet エラー情報のみ出力
--stdout stderrではなくstdoutへ出力
--log=FILE-l FILE結果をファイルへ記録
--log-verbose 追加情報を結果報告に加える
--config-file=FILE FILEから設定を読み込む
--daemon-dデーモンとして起動
--pid=FILE-p FILEデーモンプロセスのpidをFILEに記録
--user=USER-u USERUSERの権限で実行
--datadir=DIRECTORY VirusDBのディレクトリを指定
--checks=#n-c #nデーモンとして起動したときに1日あたりn回(1-50)更新する
--daemon-notify[=/path/clamav.conf] VirusDBが更新されたときにclamdにRELOADコマンドを送る
--http-proxy=hostname[:port] HTTPプロキシサーバを使用
--proxy-user=user:password HTTPプロキシサーバを使用する場合にユーザ名とパスワードを指定
--on-error-execute=COMMAND エラーが発生した場合にCOMMANDを実行
--on-update-execute=COMMAND VirusDBを更新した場合にCOMMANDを実行
+
+

3.2.3. cronで自動更新

+
    +
  1. + ログファイルを作成 +
    
    + # touch /var/log/clam-update.log
    + # chmod 644 /var/log/clam-update.log
    + # chown clamav /var/log/clam-update.log
    +   
    +
  2. +
  3. + /etc/crontab などに登録 +
    34 * * * * clamav /usr/local/bin/freshclam --quiet
    + -l /var/log/clam-update.log
    +
  4. +
+
+

3.2.4. デーモンとして実行

+

+ -dオプションと-cオプションをつけてfreshclamを起動します。この場合はfreshclam用の起動スクリプトを作成してシステムに登録しておいたほうがよいでしょう +

+
+

3.2.5. 注意点

+

+ freshclamはclamavユーザ権限で動作するため、ログファイルなどにclamav権限でアクセスできるように調整する必要があります。 +

+
+ +

3.2.6. freshclamの戻り値

+ + + + +
0VirusDBが正常に更新された
1VirusDBは既に最新のものなので更新されなかった
その他なんらかの原因でfreshclamは正常に実行されなかった
+
+ +
+ +
+ +

4. ウイルスの検出

+ +

4.1. clamscan

+

clamscanはウイルス検査を行うコマンドです。

+ +

4.1.1. clamscanのオプション

+
    +
  • 出力等に関するオプション + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    --help-h使い方を表示
    --version-Vバージョン情報を表示
    --verbose-v出力を詳細にする
    --debug デバッグ情報を出力
    --quiet エラー情報のみ出力
    --stdout stderrではなくstdoutへ出力
    --log=FILE-l FILE結果をファイルへ記録
    --log-verbose 追加情報を結果報告に加える
    --disable-summary summaryを出力しない
    --infected-iウイルスに感染したファイルのみを出力
    --bellウイルスを検出したらベルを鳴らす
    +
  • +
  • 動作に関するオプション + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    --tempdir=DIRECTORY 一時ファイルを作成するディレクトリを指定
    --database=FILE/DIR-d FILE/DIRVirusDBとして読み込むファイル(or ディレクトリ)を指定
    --recursive-rサブディレクトリごと再帰的に検査。圧縮ファイルは再帰的に解凍して検査
    --exclude=PATT パターンにマッチするファイルを検査しない
    --include=PATT パターンにマッチするファイルのみを検査する
    --remove ウイルスに感染したファイルを削除する
    --move=DIRECTORY ウイルスに感染したファイルをDIRECTORYへ移動する
    --force エラーを無視して強制的に検査を行う
    +
  • +
  • ファイル形式に関するオプション + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    --mbox-mmbox形式、rfc(2)822形式のファイルを検査する
    --no-ole2 OLE2機能を無効にする
    --no-archive 圧縮されたファイルを解凍・展開しない
    --detect-encrypted
    --max-files=#n 圧縮されたファイルを解凍・展開する際のファイル数の上限
    --max-space=#n 圧縮されたファイルを解凍・展開する際のファイルサイズの上限
    --max-recursion=#n 圧縮されたファイルを再帰的に解凍・展開する際の最大深度
    --unzip=[FULLPATH] .zipファイルを解凍
    --unrar=[FULLPATH] .rarファイルを解凍
    --unace=[FULLPATH] .aceファイルを解凍
    --unarj=[FULLPATH] .arjファイルを解凍
    --unzoo=[FULLPATH] .zooファイルを解凍
    --lha=[FULLPATH] .lzhファイルを解凍
    --jar=[FULLPATH] unzipコマンドを使って.jarファイルを解凍
    --deb=[FULLPATH] arコマンドを使って.debファイルを解凍
    --tar=[FULLPATH] tarファイルを展開
    --tgz=[FULLPATH] GNU tarを使ってtar+gzipファイルを解凍・展開
    + ※clamscanは上記のオプションなしでもzip/gzip/bzip2/rar(2.0)に対応している +
  • +
+
+ +

4.1.2. clamscanの実行例

+
$ clamscan <file>
-
ファイルを検査します。
+
ファイルを検査
$ cat <file> | clamscan -
-
標準入力のデータを検査します。
+
標準入力のデータを検査
$ clamscan
-
現在のディレクトリにあるファイルを検査します。
+
現在のディレクトリにあるファイルを検査
$ clamscan -r [<dir>]
-
ディレクトリとサブディレクトリにあるファイルを再帰的に検査します。
-
+
ディレクトリとサブディレクトリにあるファイルを再帰的に検査
+
# clamscan -r --mbox /var/spool/mail
+
メールスプールを検査
+
$ clamscan -d /tmp/newclamdb --max-space=50m -r /tmp
+
/tmp/newclamdbからデータベースを読み込んでディスク使用量の上限を50MBとして検査
+ +
-

3.2 圧縮ファイルのスキャン

+

4.1.3. clamscanの戻り値

+

単独のファイルを検査したときに限り、clamscanは以下のような戻り値を返す

+ + + + +
0ウイルスは検出されなかった
11つか複数のウイルスが検出された
その他なんらかの理由でclamscanが正常に実行されなかった
+
+ +
+ +

4.2. clamd

+ +

4.2.1. clamd

+

+ clamdはサーバとして動作し、TCPまたはunixソケットを通じてクライアントと通信し、ウイルスを検査します。 +

+

+ clamscanはコマンドとして動作し、実行されるたびにウイルスデータベースを読みこみますが、clamdは最初に起動したときに一度ウイルスデータベースを読みこむだけなので、頻繁にウイルス検査を行うような用途の場合にはclamscanよりもclamdのほうが有利です。 +

+

+ 一方、clamdは起動時にのみウイルスデータベースを読みこむので、ウイルスデータベースが更新された場合にはclamdに再度読みこませる必要があります(最近のバージョンではclamdが定期的にウイルスデータベースの更新をチェックして自動で再読み込みするようです)。clamdの運用のためには起動スクリプトの設置やclamav.confファイルでの設定が必要になり、また、clamdプロセスにトラブルが発生してまともに動作しなくなった場合のケアが必要になるなど、clamdを使う場合にはclamscanと比べて管理が煩雑になります。 +

+
+

4.2.2. clamav.confの設定

+

+ clamdを運用するためにはclamav.confファイルでの設定が必要です。clamav.confファイルの場所は一般的には/etc/clamav.confか/usr/local/etc/clamav.confですが、-cオプションで明示的に独自の設定ファイルを指定できます。 +

+
基本的な設定項目
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
項目名パラメータ説明
Example この項目が設定されている場合、clamdはすぐに終了する
Foreground backgroundではなくforegroundで稼動させる
Debug デバッグモードで稼動させる
PidFilePATHメインthreadのpidを指定したファイルに記録する (Default: 無効)
DatabaseDirectoryPATHVirusDBファイル(main.cvd/daily.cvd/*.db等)のあるディレクトリを明示して指定
SelfCheckSECOND指定された間隔(秒)ごとにDataDirectory内のデータベースファイルの更新をチェックし、自動的に再読み込みを行う。 (Default: 3600)
UserUSERNAMEroot権限で起動した場合にはこのユーザ権限に移行する (Default: 無効)
AllowSupplementaryGroups root権限で起動しユーザ権限を移行する際にグループ権限も移行する
TemporaryDirectoryPATH一時的な使い捨てファイルなどを作成するディレクトリを指定
FixStaleSocket 前回にclamdが異常終了したなどが原因で残されたままになっているsocketファイルを除去する
VirusEventCOMMAND ...ウイルスが検出されたら指定したコマンドを実行する。コマンドの引数に%v(ウイルス名)と%f(感染したファイル名)を指定できるが、%fの取り扱いに注意しなければセキュリティ上の問題が発生するので使用しないこと
+
サーバ・スレッド等の設定項目
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
項目名パラメータ説明
LocalSocketPATHunixソケットでの通信を行う場合のscoketファイルの場所
TCPAddrIPTCPでの通信を行う場合のIPアドレス
TCPSocketNUMBERTCPでの通信を行う場合のポート番号
MaxConnectionQueueLengthNUMBERlisten(2)のbacklogの値 (Default: 15)
MaxThreadsNUMBER同時に動くスレッドの数の上限 (Default: 5)
ReadTimeoutNUMBERクライアント側からのアイドル時のタイムアウト時間(秒数) (Default: 120 | 0で無制限)
StreamSaveToDisk STREAMコマンドで送られたデータを一旦ディスクに記録してから検査する。STREAMコマンドにおいて圧縮ファイルへの対応のために必要
StreamMaxLengthSIZESTREAMコマンドで送られるデータの容量の上限 (Default: 無制限)
MaxDirectoryRecursionNUMBERサブディレクトリを再帰的に検査する際の深度の上限 (Default: 無制限)
FollowDirectorySymlinks シンボリックリンクディレクトリの本体を検査の対象にする。この項目を有効にする場合にはMaxDirectoryRecursionの設定に注意すること
FollowFileSymlinks シンボリックリンクファイルの本体を検査の対象にする
+
ログ間連の設定項目
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
項目名パラメータ説明
LogFilePATH指定したファイルにログを記録する (Default: 無効)
LogFileUnlock LogFileで指定したログファイルをロックしない (Default: 無効)
LogFileMaxSizeSIZELogFileで指定したログファイルの容量の上限 (Default: 1M | 0で無制限)
LogTime 日付と時刻をログの内容に加える (Default: 無効)
LogSyslog syslogへ出力する(LOCAL6)
LogVerbose 詳細にログ出力
+
ファイル形式に関する設定項目
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
項目名パラメータ説明
ScanOLE2 マクロウイルスに対応
ScanMail mbox/rfc(2)822形式に対応
ScanArchive 圧縮ファイルに対応
ScanRAR 内蔵RARエンジンで.rarに対応
ArchiveBlockEncrypted パスワード付きで圧縮されたzip/rarファイルを無条件でEncrypted.Zip/Encrypted.RARウイルスとして検出する
ArchiveMaxFileSizeSIZE解凍・展開する圧縮ファイルの容量の上限 (Default: 10M | 0で無制限)
ArchiveMaxRecursionNUMBER再帰的に解凍・展開する際の深度の上限 (Default: 5 | 0で無制限)
ArchiveMaxFilesNUMBER解凍・展開する圧縮ファイルが内包するファイル数の上限 (Default: 1000 | 0で無制限)
ArchiveMaxCompressionRatioNUMBER解凍後の容量がこの比率より大きくなる場合はarchive bombsと判断し、Oversized.Zipウイルスとして検出する (Default: 200)
ArchiveLimitMemoryUsage メモリの節約とひきかえに解凍速度を遅くする (bzip2解凍のみに作用)
+
Clamuko間連の設定項目
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
項目名パラメータ説明
ClamukoScanOnLine Clamukoオンラインスキャンを有効にする。 Dazukoが正常に動作している必要がある。
ClamukoScanOnOpen ファイルをOpenする際に検査を実行
ClamukoScanOnClose ファイルをCloseする際に検査を実行
ClamukoScanOnExec ファイルを実行する際に検査を実行
ClamukoIncludePathPATH指定した領域を検査の対象にする (Clamukoを有効にする場合は必須)
ClamukoExcludePathPATH指定した領域を検査の対象から除外する
ClamukoMaxFileSizeSIZE検査するファイルの容量の上限
ClamukoScanArchive 圧縮ファイルを解凍・展開して検査を行う。 ScanArchiveとは独立して作用するが、 ArchiveMax*の制限の影響を受ける
+
+ +

4.2.3. clamdの実行例

+
+
# clamd
+
clamdを起動します
+
# clamd -c /home/clamav/clamav.conf
+
clamdを起動し/home/clamav/clamav.confの設定を使用します
+
# clamd --debug
+
デバッグモードで起動します
+
# kill (clamdのpid)
+
clamdを終了します
+
# kill -HUP (clamdのpid)
+
clamav.confの設定の変更をclamdに適用させます
+
# kill -USR2 (clamdのpid)
+
clamdにVirusDBを再読み込みさせます
+
+
+ +

4.2.4. clamdとの通信

+
コマンド一覧
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PINGサーバが正常に稼動していれば"PONG"を返します
VERSIONバージョン情報を返します
RELOADVirusDBを再読み込みします
SHUTDOWNclamdプロセスを終了させます
SCAN <PATH>指定した場所のファイルやディレクトリを(再帰的に)検査させます。clamav.confの設定で無効になっていなければ圧縮ファイルを解凍・展開して検査します。
RAWSCAN <PATH>指定した場所のファイルやディレクトリを(再帰的に)検査させます。圧縮ファイルの解凍・展開は行いません。
CONTSCAN <PATH>指定した場所のファイルやディレクトリを(再帰的に)検査させます。clamav.confの設定で無効になっていなければ圧縮ファイルを解凍・展開して検査します。また、ウイルスが途中で検出されてもそこで停止せずに最後まで検査を続行します。
STREAMサーバは"PORT 番号"を返します。クライアントはこの後サーバのこのポート番号へデータを送信して検査します。FTPプロトコルのPORTコマンドのようなもの。
SESSION/ENDSESSIONコマンドで、1つのセッション内で複数のコマンドを実行できるようになります。セッションを終了するにはENDコマンドを送ります。
+
clamdとの通信の例
+

telnetコマンドを使うと雰囲気がつかみやすいと思います。

+
  • PINGコマンド +
    
    +$ telnet localhost 3310
    +Trying 127.0.0.1...
    +Connected to localhost.
    +Escape character is '^]'.
    +PING
    +PONG
    +Connection closed by foreign host.
    +   
    +
  • +
  • RELOADコマンドでVirusDBを再読み込み +
    
    +$ telnet localhost 3310
    +Trying 127.0.0.1...
    +Connected to localhost.
    +Escape character is '^]'.
    +RELOAD
    +RELOADING
    +Connection closed by foreign host.
    +   
    +
  • +
  • SCANコマンドによるウイルス検査 +
    
    +$ telnet localhost 3310
    +Trying 127.0.0.1...
    +Connected to localhost.
    +Escape character is '^]'.
    +SCAN /tmp/virus
    +/tmp/virus/bugbear.virus: W32.BugBear.A FOUND
    +Connection closed by foreign host.
    +   
    +
  • +
  • CONTSCANコマンドによるウイルス検査 +
    
    +$ telnet localhost 3310
    +Trying 127.0.0.1...
    +Connected to localhost.
    +Escape character is '^]'.
    +CONTSCAN /tmp/virus
    +/tmp/virus/bugbear.virus: W32.BugBear.A FOUND
    +/tmp/virus/klez.virus: Worm.Klez.H FOUND
    +/tmp/virus/clamav.test: ClamAV-Test-Signature FOUND
    +/tmp/virus/mydoom.virus: Worm.SCO.A FOUND
    +/tmp/virus/netsky_q.virus: Worm.SomeFool.Q FOUND
    +Connection closed by foreign host.
    +   
    +
+
+ +

4.2.5. clamdscan

+

+ clamscanは起動するたびにVirusDBを解凍・展開し、それを読み込んでから検査を行います。VirusDBの本体main.cvdは圧縮時でも約1MBはあるので、例えば1秒に何件ものメールをさばくようなサーバで検査したり、fetchmail+procmailで一度に1000件ほどのメールを受信して検査するような場合には1件のメールごとにclamscanを起動していたのでは速度や負荷の面で問題が発生するのは十分に想像されることです。 +

+

+ clamdscanはclamscanと同様のインターフェースを持ち、clamdのクライアントとしてウイルスを検査するコマンドです。clamdscan+clamdでclamscanの全ての機能を置き換えることはできませんが、ほとんどの場合重すぎるclamscanを簡単にすぐに置き換えることが出来ます。 +

+
+ +

4.2.6. clamdscanのオプション

+

clamdscanはclamscanとほぼ共通のオプションを使用しますが、clamscanでは使えるもののclamdcanでは対応していないオプションを指定した場合でもエラー等を出力せず(また何も機能せずに)そのまま実行します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
--help-h使い方を表示
--version-Vバージョンを表示
--verbose-v詳細に出力
--quiet エラーのみを出力
--stdout stderrではなくstdoutに出力
--log=FILE-l FILEFILEにログを記録する
--log-verbose 詳細なログ出力
--disable-summary summary表示をしない
--config-file=FILE 設定として読み込むclamav.confを明示する。clamdscanはclamdと同じclamav.confを使用する必要がある
+
+ +

4.2.7. clamdscanの戻り値

+

clamdscanの戻り値は基本的にはclamscanと同じになります。

+ + + + +
0ウイルスは検出されなかった
11つか複数のウイルスが検出された
2Errorが発生した
+
+ +
+ +

4.3. Dazuko+Clamuko

+ +

4.3.1. Dazuko

+

+ DazukoはLinuxおよびFreeBSD対応のカーネルモジュールで、アンチウイルスツールとの組み合わせでファイルシステムへのアクセスを監視してウイルスから利用者を保護します。ただしNFS経由でのアクセスには対応していません。 +

+
+

4.3.2. Clamuko

+

+ Clamukoはclamdのもう一つの機能でclamavのDazukoとの組み合わせでの使用を可能にします。 +

+

+ Clamukoを使用するにはclamav.confでいくつかの項目を設定する必要があります。 +

+
    +
  • /homeをClamuko+Dazukoで保護する場合 +
    
    + ClamukoIncludePath /home
    +    
    +
  • +
  • システム全体をClamuko+Dazukoで保護する場合 +
    
    + ClamukoIncludePath /
    + ClamukoExcludePath /proc
    + ClamukoExcludePath /tempdir/of/mail/scanner
    +    
    +
  • +
+
+ +
+ +
+ +

5. ClamAV関連のソフト

- 圧縮されたファイル等、なんらかの形式で加工されたファイルを検査するためには、それらを一度元のファイルに戻す必要があります。たとえば、「clamscan /var/spool/mail」を実行しても、メールスプール内の添付ファイルを正しく検査することができません。また、MacOSXにおいて「clamscan -r ~/Library/Mail」を実行しても、同様にMail.appのメールデータを正しく検査することはできません。 -

-

- ただし、一部の圧縮フォーマットについては、clamscanコマンドにそれぞれのオプションをつけることで外部コマンドを利用して解凍しながら検査することが可能です。このときに「-r」オプションを併用すると、再帰的に解凍しながら検査します。また、圧縮されたファイル自体がウィルスに感染しているかどうかも検査されます。 + ClamAVに対応、あるいは組み合わせて使用できる主なツールの一部です。

-

3.2.1 圧縮ファイル用の主なオプション

-
-
--unzip[=/path/to/unzip]
-
.zip形式のファイルを検査します。
-
--unrar[=/path/to/unrar]
-
.rar形式のファイルを検査します。
-
--lha[=/path/to/lha]
-
.lzh形式のファイルを検査します。
-
--tar[=/path/to/tar]
-
.tar形式のファイルを検査します。GNU tarが必要です。
-
--tgz[=/path/to/tar]
-
.tgzおよび.tar.gz形式のファイルを検査します。GNU tarが必要です。
-
--jar[=/path/to/unzip]
-
.jar形式のファイルを検査します。
-
--deb[=/path/to/ar]
-
.deb形式のファイルを検査します。
-
+

5.1. MTA

+ +

5.1.1. AMaViS/amavisd

+

+ AMaViSとamavisdはsendmailやpostfixやqmailなどのMTAとウイルススキャナを組み合わせて利用するためのインターフェースとして機能します。 +

+
+ +

5.1.2. AMaViS-ng

+

+ AMaViS-ngはHilko BengenがAMaViSを書き直したものです。 +

+
    +
  1. インストール後にamavis.confを編集して次の行のコメントを解除します。 +
    
    + virus-scanner = CLAM
    +    
    +
  2. +
  3. amavis.confの[CLAM]セクションにclamscanのpathを設定します。 +
    
    + [CLAM]
    + clamscan = /usr/local/bin/clamscan
    +    
    +
  4. +
+
+ +

5.1.3. amavisd-new

+

+ amavisd-newは、amavisdをもとにMark Martinecが書き直し、パフォーマンスの向上とSpamAssassinによるanti-spam機能を加えたものですが、anti-spamとanti-virusのどちらかを外して使用することもできます。他の商用アンチウイルス製品とclamavとを共用で2重に検査したり、また通常はclamdを使いclamdに問題が発生したときにはclamscanを代わりに使用して対処する、といったこともできます。amavisd.confを編集し、@av_scannersの項目でclamdを有効にして使います。 +

+
+ +

5.1.4. MailScanner

+

+ MailScannerは、各種MTAとanti-virusおよびanti-spamプログラムとを組み合わせて使用しますが、Postfixとの組み合わせは推奨されていません。 +

+
-

4. ウィルス定義データベース

+

5.1.6. OpenProtect

+
-

4.1 データベース

+

5.1.7. clamav-milter

+

+ ClamAVのclamav-milter機能を利用すればSendmail milterと連携してウイルス検査を行うことができます。 +

+

+ clamav-milterを使用するにはClamAVを次のようにconfigureを実行してコンパイル・インストールします。 +

+

+ $ ./configure --enable-milter
+  
+

+ インストールが終わったらsendmail.mcに次のように記述して設定します。 +

+

+ INPUT_MAIL_FILTER(‘clmilter’,‘S=local:/var/run/clmilter.sock, F=, T=S:4m;R:4m’)dnl
+ define(‘confINPUT_MAIL_FILTERS’, ‘clmilter’)
+  
+

+ それから、clamav.confの設定が次のようになっているのを確認してから +

+

+ LocalSocket /var/run/clamd.sock
+ ScanMail
+ SaveStreamToDisk
+  
+

+ clamav-milterを起動します。 +

+

+ /usr/local/sbin/clamav-milter -blo /var/run/clmilter.sock
+  
+

+ 最後にsendmailを再起動します。 +

+
+ +

5.1.8. mimedefang

+

+ MIMEDefangは、Sendmailとanti-virusおよびanti-spamプログラムとを組み合わせて使用します。 +

+
+ +

5.1.9. IVS Milter

+

+ IVS Milter (Industrial Virus + Spam milter)は、Sendmail milterでClamAV(clamd)等のアンチウイルスソフトやSpamAssassin(spamd)によるメールのフィルタリングのためのソフトです。 +

+
+ +

5.1.10. smtp-vilter

+

+ smtp-vilterは、Sendmail milterでClamAV(clamd)とSpamAssassin(spamc or libspamc)によるメールのフィルタリングのためのソフトです。 +

+
+ +

5.1.11. j-chkmail

+
+ +

5.1.12. nclamd,nclamav-milter

+

+ nclamdとnclamav-milter、nclamdscanは本家のclamd,clamav-milter,clamdscanを置き換えるソフトで、thread主義のClamAVに対してApache2のpreforkのように動作し、ClamAVが内蔵のMIME解析ルーチンを使うのに対してripMIMEを使用します。 +

+
+ +

5.1.13. qmail-scanner

+

+ Qmail-Scannerはqmailとウイルススキャナを組み合わせて使用します。softlimitの値を多めに設定して使用するほうがよいらしい。 +

+
+ +

5.1.14. clamdmail

+

+ Clamdmailはqmailをはじめとする各種MTAとclamdとを組み合わせてウイルススキャンを実現します。 +

+
+ +

5.1.15. qscanq

+
+ +

5.1.16. Gadoyanvirus

+
+ +

5.1.17. exiscan

+

+ exiscanはExim 4に対するパッチで、content scanning 機能をEximに追加します。 +

+
+ +

5.1.18. Scanexi

+

+ Scanexiはexiscanをベースにしてできたもので、EximでClamAVとSpamassassinによるアンチウイルス/アンチスパムの機能を実現します。 +

+
+ +

5.1.19. sagator

+

+ sagatorはPythonで書かれていて、Postfix等のMTAとclamavやSpamAssassin等とを組み合わせて使用します。 +

+
+ +

5.1.20. cgpav

+
+ +
+ +

5.2. MUA周辺

-

- Clam Antivirusのウィルス定義データベースは、デフォルトでは/usr/local/share/clamav/viruses.dbにインストールされます。最新のウィルスに対応するためにはこのファイルをこまめに更新する必要があります。 -

-

- また、バージョン0.23以降では、このviruses.dbと同じディレクトリにexample.dbのようなファイル名の末尾に「.db」を含むファイルがある場合は、そのファイルもウィルス定義データベースとして使用するようになっています。つまり標準のウィルス定義データベースに加えて独自作成もしくはサードパーティ製のデータベースを併用することが可能です。 -

+

5.2.1. POP3 Virus Scanner Daemon

+
+ +

5.2.2. Sylpheed-Claws

+

+ Sylpheed-Clawsはいわゆる3ペインの電子メールソフトです。プラグインによってclamavの機能を使えるようです。 +

+
+ +

5.2.3. Mutt

+

+ Muttはテキストベースの電子メールクライアントソフトです。Mutt自体にアンチウイルス機能はありませんが、添付ファイルごとにパイプでclamscanに検査させることはできます。 +

+
+ +
-

4.2 freshclam

+

5.3. その他メール関連

+ +

5.3.1. ClamAssassin

+
-

4.3 oav-update

+

5.3.2. TrashScan

+

+ TrashScanはclamav-x.xx/contrib/trashscan/ に収録されている簡単なbashスクリプトで、procmailとclamscanとの組み合わせでウイルススキャンを実現します。 +

+
-

5. AMaViSを利用した電子メールのスキャン

+

5.3.3. mailman-clamav

+
-

5.1 AMaViS-perl

+

5.3.4. mailgraph

+
-

- AMaViS-perlとClam Antivirusを連係させて使用すると、サーバサイドでの電子メールのウィルススキャンをさせることができます。 -

-

- 使用するためにはClam Antivirusのソースコードに含まれているパッチ(support/amavis/clamavis.patch)を使ってAMaViS-perlをClam Antivirusに対応させる必要があります。まずはhttp://www.amavis.org/からamavis-perl-11.tar.gzを入手します。それから以下のような手順でパッチをあてます。 -

+
-

- $ tar zxpvf amavis-perl-11.tar.gz
- $ cp clam-0.23/support/amavis/clamavis.patch amavis-perl-11
- $ cd amavis-perl-11
- $ patch -p1 < clamavis.patch
- $ find . -exec touch 01010000 {} \;
- 
+

5.4. その他のサーバ

+ +

5.4.1. sambaa-vscan

+

+ sambaa-vscanはOpenAntiVirusプロジェクトによるソフトの一つで、SambaのVFSモジュールとしてファイルサーバでのアンチウイルス機能を可能にします。 +

+
-

- パッチをあてた後は、通常のAMaViS-perlのインストール手順と同じようにインストール・設定・使用することができます。AMaViS-perlについての詳細な情報についてはhttp://www.amavis.org/を調べて下さい。 -

+

5.4.2. mod_clamav

+

+ mod_clamavはApache2のモジュールです。mod_proxyとの組み合わせでプロキシサーバにアンチウイルス機能を組み込むことが可能です。 +

+
-

5.2 AMaViS-ng

- -

- AMaViS-ngはパッチをあてるまでもなくデフォルトでClam Antivirusに対応しています。また、AMaViS-perlに比べて若干インストールが楽です。が、MIME構造の壊れたメールなどの配送を保留してしまったりするのが少し困りものです。 -

+

5.4.3. PureFTPd

+

+ PureFTPdにはuploadscript機能があり、clamscan等と組み合わせて、アップロードされたファイルをウイルススキャンすることができます。 +

+
-

- AMaViS-ngはhttp://sourceforge.net/projects/amavisから入手できます。インストール後に、amavis.confの次のような行のコメントを外します。 -

+

5.4.4. Viralator

+

+ ViralatorはSquidと各種アンチウイルスソフトとの組み合わせでsquidプロキシサーバでのアンチウイルス機能を可能にします。 +

+
-

- virus-scanner = CLAM
- 
+
+ +

5.5. CD-ROM

+ +

5.5.1. INSERT

+
-

- それから、同じくamavis.confの[CLAM]セクションにclamscanのpathを設定します。 -

+

5.5.2. Local Area Security

+
+ +
+ +

5.6. その他

-

-[CLAM]
+  

5.6.1. Mail::ClamAV

+

+ Mail::ClamAVはPerlの拡張モジュールで、このモジュールを使えばPerlスクリプトでウイルススキャンを実装できます。 +

+
-clamscan = /usr/local/bin/clamscan -
+

5.6.2. clamavr

+
-

6. ウィルスシグネチャ

+

5.6.3. wbmclamav

+
-

6.1 ClamAV-Test-Signatureのシグネチャ

+

5.6.4. Scan Log Analyzer

+
-

- ClamAV-Test-SignatureはClam Antivirusに含まれているテスト用のウィルス(動作確認用のもので実際には害をもたらさない)です。ソースコードではtest/test1にあります。このファイルがどのようになっているか見てみましょう。 -

-

- $ cat test/test1
- $CEliacmaTrESTuScikgsn$FREE-TEST-SIGNATURE$EEEEE$
- 
-

- 一方、このClamAV-Test-Signature用のシグネチャは次のようになっています。 -

-

- $ grep ClamAV-Test-Signature /usr/local/share/clamav/viruses.db
- ClamAV-Test-Signature=2443456c6961636d615472455354755363696b67736e24465245452d544553542d5349474e4154555245244545454545240a
- 
-

- 「=」の左側がウィルスの名前、右側がウィルスのシグネチャ本体であることがわかると思います。では、このシグネチャはどのようにして作成されたのでしょうか。その前にとりあえずClamAV-Test-Signatureのファイルを16進数で出力してみましょう。これはSolarisでの実行例です。 -

-

- $ od -t x1 test1
- 0000000 24 43 45 6c 69 61 63 6d 61 54 72 45 53 54 75 53
- 0000020 63 69 6b 67 73 6e 24 46 52 45 45 2d 54 45 53 54
- 0000040 2d 53 49 47 4e 41 54 55 52 45 24 45 45 45 45 45
- 0000060 24 0a
- 0000062
- 
-

- もうお分りいただけたと思います。シグネチャの正体はウィルス(の断片)をhexdumpしたものだったんですね。このClamAV-Test-Signatureの場合はファイルが小さいので全体をhexdumpしていますが、通常はファイルの一部を使います。 -

+

5.6.5. ClamWin Antivirus

+

+ ClamWin AntivirusはClamAVのWindows版バイナリ+GUIインターフェースで、UnixになじみのないWindows利用者でも簡単に使用できます。 +

+
-

6.2 シグネチャの作成

+
+ +
-

- シグネチャを作成するにはウィルスのデータをhexdumpすればよいことがわかりました。このシグネチャと一致する箇所をもつファイルをウィルスに感染しているとみなすわけです。 -

-

- ところが、ウィルスに感染したファイルをそのままhexdumpしたものをシグネチャとして配布してしまうと、ウィルスそのものを配布しているのと変わりありません。また、シグネチャそのものが肥大化してしまうので、それを読みこむアンチウィルスソフトの負担が大きくなります。また、感染したファイルごとに形を変えるようなタイプのものに対しては効果がありません。 -

-

- したがって、シグネチャの作成のために抽出する箇所は次のような条件を満たす必要があります。 -

-
    -
  • 手頃な長さであること
  • -
  • そのウィルスに感染したファイルに必ず含まれること
  • -
  • そのウィルスに感染していないファイルには含まれないこと
  • -
  • それだけでは無害であること
  • -
-

- これらの条件をみたすようなシグネチャを作成するためには、まずウィルスに感染したファイルを入手する必要があります。また、同じウィルスに感染したファイルを、別の経路から複数入手するか、あるいは一つのウィルスを閉じられた環境で培養してみて、該当のウィルスの性質などについてより深く調べる必要があるでしょう。また、当然のことですが、たとえばWindowsに感染するウィルスのシグネチャをWindows上で作成するのは危険です。 -

-

- シグネチャを作成したら、ウィルス定義データベースに登録しましょう。Clam Antivirusの標準のデータベースファイルはviruses.dbですが、このファイルに追加すると、データベースを更新するときに上書きされて失われてしまうので、たとえばlocal.dbというような名前のファイルを新規に作成し、そこに追加していくとよいでしょう。 -

+

6. シグネチャの管理・自作

-

6.3 sigtool

+

6.1. VirusDBの構造

-

- このように、「どの部分をシグネチャに採用するか」という問題のために、自力で良質なシグネチャを作成するのはやや困難であるといえるでしょう。Clam Antivirusに含まれるsigtoolコマンドは、このシグネチャの作成を支援するものです。 -

-

- sigtoolは、ウィルスに感染したファイルを細切れにして、それを他のウィルススキャナにかけ、そのウィルススキャナが細切れにされたファイルからウィルスを検出するかを調べます。そういったことをくり返して、その他のウィルススキャナが、どの部分をウィルスとして検出するかを正確につきとめます。そしてその部分をhexdumpします。 -

-

- sigtoolでシグネチャを作成するためには以下の条件が必要です。 -

-
    -
  • ウィルスに感染したファイルがある
  • -
  • そのウィルスをClam Antivirusでは検出できない
  • -
  • ほかのウィルススキャナでは、そのウィルスを検出できる
  • -
  • そのウィルススキャナがコマンドラインでのインターフェースを持ち、なおかつ標準出力にウィルス検出時の固有のメッセージを出力する
  • -
-

- 仮にこの他のウィルススキャナのコマンド名を「otherscan」とし、ウィルスに感染したファイルを「virus.exe」とします。また、このotherscanコマンドがvirus.exeからウィルスを検出したとき「infected」という文字列が標準出力に出力するメッセージに含まれるものとします。 -

-

- これらの条件下でsigtoolを次のように実行します。 -

-

- $ sigtool -c "otherscan" -f virus.exe -s "infected"
- 
-

- このコマンドを実行すると、「virus.exe.sig」というファイルにシグネチャを出力します。これだけではまだOpenAntivirusのシグネチャのフォーマットの右辺だけで不充分ですので、適切なウィルスの識別名を左辺に設定します。 -

+

6.1.1. cvdファイルの書式

+

+ VirusDBは基本的にmain.cvdとdaily.cvdの2つですが、これらのcvdファイルは固定長(512バイト)のヘッダ部分+可変長のデータ部分とで構成されています。 +

+

+ データ部分はシグネチャ本体(viruses.db,viruses.db2)とGPL2で配布されていることをしめすCOPYINGの2つをtar+gzでまとめたものです。 +

+

+ ヘッダ部分はフィールドごとにコロン(":")で区切られていて、余白は空白文字(0x20)で埋められます。 +

+
ヘッダ部分のフィールド一覧
+
    +
  1. 「ClamAV-VDB」という文字列
  2. +
  3. 作成日時
  4. +
  5. バージョン
  6. +
  7. 収録シグネチャ数
  8. +
  9. 収録シグネチャ使用に必要な機能レベル
  10. +
  11. データ部分のMD5チェックサム値
  12. +
  13. 電子署名
  14. +
  15. 作成者名
  16. +
+
ヘッダ部分の例
+
ClamAV-VDB:15 Apr 2004 01-38 +0200:263:844:1:ed0bf80996eef5326e7830cb7
+f394f13:FSW1coiymNODboGDmmeg5gNm6psCuAOCTsm4gXEqMP8k9H7H/QPfZvvvMPQTup
+0sf2LtrRImxkgYvR6ksiS/Zal8QdhiPS6LuHBBbjuzHYW+PLIwuG5Hzd0tj2p4mhiwv2Eb
+Q2agcPH6n5xekRLOIDb3qggf+6F9YwDw8JX6nj:ccordes
+   
+
-

7. フリーのアンチウィルスについて

+

6.1.2. シグネチャの書式

+

+ ウイルスデータベースにはウイルスを検出するためのシグネチャが格納されています。viruses.dbやviruses.db2を見てください。1行ごとにシグネチャ1つという構成で「ウイルス名=文字列」という書式になっています。 +

+

+ 右辺の文字列はウイルス固有のパターンをhexdumpしたものですが、「*」(任意の文字列に一致)と「??」(任意の1バイトに一致)のように簡単な正規表現を使うことができます。 +

+

Clamav用のテスト用ウイルスClamAV-Test-Signatureを例にしてみます。このウイルスのシグネチャは以下のとおりです。

+
ClamAV-Test-Signature=2443456c6961636d615472455354755363696b67736e2446
+5245452d544553542d5349474e4154555245244545454545240a
+   
+

ClamAV-Test-Signatureをhexdumpした結果と比較してみてください。

+
0000000 24 43 45 6c 69 61 63 6d 61 54 72 45 53 54 75 53
+0000020 63 69 6b 67 73 6e 24 46 52 45 45 2d 54 45 53 54
+0000040 2d 53 49 47 4e 41 54 55 52 45 24 45 45 45 45 45
+0000060 24 0a
+0000062
+   
+

+ +

+
-

- OpenAntiVirusをはじめとするフリーのアンチウィルスプロジェクトは、いまだに商用のものには、足もとさえ全く及びません。何もしないよりはましかもしれませんが、現在のところ、Clam AntivirusやOpenAntiVirus等を導入したからといって、十分であるとは到底言えない状況です。2002年8月16日の時点で、検出できるウィルスの種類は1800にも届いていません。また、OpenAntiVirusのウィルス定義データベースの現在の最終更新日付は7月1日で、1ヵ月半以上更新されていません。 -

+

6.1.3. VirusDBまとめ

+
 VirusDB
+  + main.cvd (本体)
+  |  + ヘッダ部分(512byte固定長)
+  |  |  + 'ClamAV-VDB'
+  |  |  + 作成日時
+  |  |  + CVDのバージョン
+  |  |  + 収録シグネチャ数
+  |  |  + 収録シグネチャの使用に必要な機能レベル
+  |  |  + データ部分のMD5チェックサム値
+  |  |  + 電子署名
+  |  |  + 作成者名
+  |  |
+  |  + データ部分(tarball)
+  |     + COPYING
+  |     + viruses.db
+  |        + VirusName=HexStrings
+  |
+  + daily.cvd (日々更新される)
+  |  + ヘッダ部分(512byte固定長)
+  |  |  + 'ClamAV-VDB'
+  |  |  + 作成日時
+  |  |  + CVDのバージョン
+  |  |  + 収録シグネチャ数
+  |  |  + 収録シグネチャの使用に必要な機能レベル
+  |  |  + データ部分のMD5チェックサム値
+  |  |  + 電子署名
+  |  |  + 作成者名
+  |  |
+  |  + データ部分(tarball)
+  |     + COPYING
+  |     + viruses.db2
+  |        + VirusName=HexStrings
+  |
+  + *.db (local側などで独自に登録)
+     + VirusName=HexStrings
+   
+
-

8. この文書について

+
-

8.1 ライセンスなど

-

- この文書はGNU General Public Licenseに基づいています。 -

-

- この文書は小川真樹がClam Antivirusについて調べたもので、忘れないように記録したものをまとめたものです。 +

6.2. sigtool

+ +

sigtoolは大まかにわけてウイルスからシグネチャを生成するのを補助する機能とVirusDBを取り扱う機能の2つの機能を持っています。

+ +

6.2.1. sigtoolのオプション

+ +
基本的なもの
+ + + + + + + + + + + + + + + + + + + + + +
--help-h使い方を表示
--version-Vバージョン情報を表示
--quiet エラーのみを出力
--debug デバッグ情報を出力
--stdout stderrではなくstdoutへ出力
+ +
シグネチャ生成補助
+ + + + + + + + + + + + + + + + + +
--hex-dump 標準入力から受け取ったデータをhex stringとして出力
--command=COMMAND-c COMMANDウイルス検査コマンドを指定
--string=STRING-s STRINGウイルス検出時にコマンドが出力する文字列を指定
--file=FILE-f FILEウイルスに感染しているファイルを指定
+ +
VirusDB
+ + + + + + + + + + + + + + + + + + + + + + + + + +
--info=FILE-i FILECVDファイルの情報を表示
--unpack=FILE-u FILECVDファイルを解凍・展開する
--unpack-current=NAME 現在使用しているCVDファイルを解凍・展開する
--list-sigs[=FILE]-l [FILE]シグネチャに登録されているウイルス名一覧を表示
--build=NAME-b NAMECVDファイルを作成 (VirusDB開発者用のオプション)
--server=ADDR ClamAV 電子署名サーバを指定 (VirusDB開発者用のオプション)
+ +
+ +

6.2.2. sigtool実行例

+
+
$ sigtool -i /usr/local/share/clamav/main.cvd
+
main.cvdの情報を表示
+
$ sigtool -u /usr/local/share/clamav/main.cvd
+
main.cvdからシグネチャファイルを取り出す
+
$ sigtool -l
+
登録されているウイルスの一覧を表示
+
+
+ +
+ +

6.3. シグネチャの自作・使用

+ +

6.3.1. sigtoolによるシグネチャの生成

+

+ sigtoolは、ウイルスのシグネチャ作成を補助するツールで、ウイルスに感染したファイルを細切れにして他のウイルススキャナにかけ、そのウイルススキャナが細切れにされたなかからどのファイルからウイルスを検出するかを調べます。これをくり返しながらそのウイルススキャナがどの部分をウイルスとして検出するのかを特定しその箇所をhexdumpします。 +

+

+ sigtoolでシグネチャを作成するためには以下の条件が必要です。 +

+
    +
  • ウイルスに感染したファイルがある
  • +
  • そのウイルスをClam Antivirusでは検出できない
  • +
  • 他のウイルススキャナでは、そのウイルスを検出できる
  • +
  • そのウイルススキャナがコマンドラインでのインターフェースを持ち、なおかつ>標準出力にウイルス検出時の固有のメッセージを出力する
  • +
+

+ 仮にこの「他のウイルススキャナ」のコマンド名を「anotherscan」とし、ウイルスに感染したファイルを「virus.exe」とします。また、このanotherscanコマンドがvirus.exeからウイルスを検出したとき「infected」という文字列が標準出力に出力するメッセージに含まれるものとします。 +

+

+ これらの条件下でsigtoolを次のように実行します。 +

+

+   $ sigtool -c "anotherscan" -f virus.exe -s "infected"
+   
+

+ このコマンドを実行すると「virus.exe.sig」というファイルにシグネチャを出力します。これだけではまだシグネチャのフォーマットの右辺だけにすぎませんから、適切なウイルスの識別名を左辺として設定します。 +

+
+ +

6.3.2. 手動でのシグネチャの作成

+

+ 手作業でシグネチャを作成するにはウイルス固有の箇所を好きなツールを使ってhexdumpして「ウイルス名=hexdumpした出力」の形式にまとめるだけです。hexdumpする箇所については以下のことに注意する必要があります。 +

+
    +
  • そのウイルスに必ず含まれていなければすり抜けられる危険性があります
  • +
  • 誤検出(false positive)防止のためそのウイルス以外には含まれていてはいけません
  • +
  • 安全のためシグネチャからウイルスを復元できないようにすべきです
  • +
  • 適度な長さ(40〜300文字くらい)が望ましい。短すぎると誤検出の危険性があり、長すぎるとClamAVに負担をかけます
  • +
  • 「00」で始まらないこと。clamav 0.54以下では処理能力が低下します
  • +
+
+ +

6.3.3. 自家製シグネチャの使用

+

+ 自家製のシグネチャを登録するには、VirusDBを格納しているディレクトリにlocal.dbのような「〜.db」というファイルを作成して追加します。 +

+
+ +
+ +

6.4. Netsky.Q用のシグネチャ作成例

+ +

6.4.1. シグネチャの自作こそがClamAVの醍醐味

+

+ ClamAVはオープンソースですから当然ながらシグネチャも自作できるのです。シグネチャの自作こそがClamAVの醍醐味であると断言します。VirusDBを最新にしても検出できない新種のウイルスを見つけたら対応するまで指をくわえて待つのではなくさっさとシグネチャを自作して自力で対応してしまいましょう。ウイルスさえ手に入ればシグネチャを作成できるのですから。ClamAVさえあれば、どこそこのアンチウイルス製品は対応した、またはまだ対応していない、とか、そんな情報を探しまわるような不毛な時間に別れを告げられます。そしてシグネチャを自作したら公開して他の人にも使ってもらいましょう。もちろんVirusDBチームにウイルスを送って一刻も早く正式対応してもらうのも忘れずに。 +

+
+ +

6.4.2. 誰でも簡単に作成可能(責任はもちませんけど)

+

+ ClamAVはいわゆるパターンマッチ方式によってウイルスを検出しています。つまりはそのウイルスに固有のパターンを登録してしまえばよいのです。だから極端な話disassembleなどでウイルスの解析をする必要なし。検出さえされればそれでよいというわけ。まぁ厳密にはそういうわけにはいかない場合もありますが、品質さえ度外視すればほとんどの場合は難しく考えなくてもシグネチャを作成可能です。どうせ数時間後には(きっと)正式に対応されるのだからそれまでのつなぎと考えればよいと思うのです。 +

+
+ +

6.4.3. vimエディタで

+

+ とりあえず(圧縮されていたら解凍して)Netsky.Qのウイルス本体を取り出し、16進表示できるエディタで開きます。ここではvimを使い、「:%!xxd」の呪文を唱えることにします。 +

+
00008d0: 191d 8cad 3dc1 135a 3182 5c6c 4233 9063  ....=..Z1.\lB3.c
+00008e0: beb7 2dad c336 9a54 417a 3d56 135e 1f62  ..-..6.TAz=V.^.b
+00008f0: 11da a9fb e100 eac3 c948 ade7 2089 75f9  .........H.. .u.
+0000900: 0d5a 8e31 2fd8 40be bc08 8ef3 a109 a526  .Z.1/.@........&
+0000910: 3949 1a80 d7d6 6c60 2662 0286 a03a 6fa0  9I....l`&b...:o.
+0000920: 3132 f9cb b767 9675 9020 ddd3 5d5e 9785  12...g.u. ..]^..
+0000930: 6a29 e69e f3f0 5159 c664 0688 678c 9250  j)....QY.d..g..P
+0000940: aef5 62a0 05bf 0a70 1616 7e12 658d a4a7  ..b....p..~.e...
+0000950: 57be 4e03 6db0 4635 4b7d 6b8b 7452 bd4d  W.N.m.F5K}k.tR.M
+0000960: df86 09a7 b92d a8a6 0814 d12f 3caa d02b  .....-...../<..+
+0000970: 3a7e 2b3d d1b6 a088 1c22 0d61 611b 7913  :~+=.....".aa.y.
+0000980: 674d 3612 3e05 f921 00c3 c011 de0c 4564  gM6.>..!......Ed
+0000990: 638e 39a6 325c 7849 4ea6 7a76 9a02 691a  c.9.2\xIN.zv..i.
+00009a0: a62a 4c9a 4469 bca6 9096 9ae0 69fc e06c  .*L.Di......i..l
+00009b0: e671 1616 3c5a c3b0 0557 80cb ebe9 f6e1  .q..<Z...W......
+00009c0: cb06 e3ef e413 1b6c 2d11 0b11 0332 331d  .......l-....23.
+00009d0: c12d 1309 0a30 9225 0061 3336 2438 333d  .-...0.%.a36$83=
+00009e0: 0803 3c2b 3823 2737 7b06 4f02 222f 2078  ..<+8#'7{.O."/ x
+   
+

+ ぱっと見で誤検出の可能性が少なそうな箇所を取り出してみることにします。誤検出が気になるなら多めに取り出すとよいのではないでしょうか。 +

+
6c6026620286a03a6fa03132f9cbb76796759020ddd35d5e97856a29e69ef3f05159c6
+640688678c9250aef562a005bf0a7016167e12658da4a757be4e036db046354b7d6b8b
+7452bd4ddf8609a7b92da8a60814d12f3caad02b3a7e2b3dd1b6a0881c220d61611b79
+13674d36123e05
+   
+

+ 左辺にウイルスの名称を加えて完成。とりあえず/tmp/db/local.dbに保存します。 +

+

+Worm.Netsky.Q@mm=6c6026620286a03a6fa03132f9cbb76796759020ddd35d5e97856
+a29e69ef3f05159c6640688678c9250aef562a005bf0a7016167e12658da4a757be4e0
+36db046354b7d6b8b7452bd4ddf8609a7b92da8a60814d12f3caad02b3a7e2b3dd1b6a
+0881c220d61611b7913674d36123e05
+   
+
+ +

6.4.4. 検出テスト

+

+ できあがったシグネチャで本当に検出できるか確認してみます。 +

+
$ clamscan -d /tmp/db/local.db netsky_q.virus
+netsky_q.virus: Worm.Netsky.Q@mm FOUND
+
+----------- SCAN SUMMARY -----------
+Known viruses: 1
+Scanned directories: 0
+Scanned files: 1
+Infected files: 1
+Data scanned: 0.02 MB
+I/O buffer size: 131072 bytes
+Time: 0.001 sec (0 m 0 s)
+   
+

+ ということなので、ちゃんと検出できることが証明されました。問題なのはウイルスによって形が変化する場合ですが、いくつか届いたNetsky.QのMD5値を調べてみるとどれも同じなのでそれは気にしなくても良さそう。 +

+
+ +

6.4.5. 自家製シグネチャの完成

+

+ できあがったシグネチャを本番環境に投入します。clamdが稼動している場合はVirusDBを再読み込みさせる必要があります。 +

+
# cat /tmp/db/local.db >> /usr/local/share/clamav/local.db
+# kill -USR2 `cat /var/run/clamd.pid`
+  
+

+ あとはログを観察して誤検出していないか注意するだけ。ちなみにNetsky.QはClamAVではSomefool.Qとしてすでに対応済みであって、ここではシグネチャ作成例として取り上げているだけです。 +

+
+ +
+ +

7. 自作プログラムでclamavを利用する

+ +

7.1. libclamav

+

libclamavを利用することで自作のプログラムにアンチウイルス機能を加えることができます。詳細についてはclamav.hやclamdoc.pdfを読んでください。また、clamav-x.xx/examples/ex1.cにサンプルのソースがあります。

+
+

7.2. clamdの利用

+

+ 多くのプログラムではlibclamavよりもclamdとの通信を通じてウイルスの検査をさせるほうが手軽にアンチウイルス機能を実現できることが多いと思います。この場合、clamdとの通信に失敗したときにclamscanを予備のスキャナとして呼び出すような仕組みにしておくとよいでしょう。 +

+
+ +
+ +
+ +

8. この文書について

+ +
    +
  • この文書はGNU General Public Licenseに基づいています。
  • +
  • + この文書は小川真樹がClam Antivirusについて調べたもので、忘れないように記録したものをまとめたものです。 この文書の内容についての意見や感想、あるいは誤りの指摘についてはproc@mac.comまでご連絡下さい。 -

    +
  • +
  • + ここに書かれてあるものは完全に無保証です。ここに書かれてあることをそのまま実行してそのとおりに動作する保証は全くありません。また私自身は特にウイルスの専門家ではありませんのでご了承ください。 +
  • +
  • + この文書の最新版は次の場所から入手できます。
    + http://homepage.mac.com/proc/clamav.html +
  • -

    8.2 免責事項

    -

    - ここに書かれてあるものは完全に無保証です。ここに書かれてあることをそのまま実行してそのとおりに動作する保証は全くありません。特にシグネチャの作成の部分については、他にまとまった資料らしいものをみつけられなかった(もしそういった資料について知っている方がいたら教えてください)こともあって、間違ったことを書いている可能性が比較的高いです。 -

    +
+ +
+ +

9. TODO

+ +
    +
  • Dazuko+Clamukoの部分
  • +
  • cvdの電子署名の仕組み
  • +
  • 間連ソフトの説明
  • +
  • clamdwatchとかmonitなど監視ツールを追加する
  • +
  • 過去のセキュリティホール情報とか追加する
  • +
+ +

-

-戻る -

+ + diff --git a/clamav-devel/docs/man/clamscan.1 b/clamav-devel/docs/man/clamscan.1 index 89c168391..47cc5f59c 100644 --- a/clamav-devel/docs/man/clamscan.1 +++ b/clamav-devel/docs/man/clamscan.1 @@ -87,6 +87,9 @@ Extract first #n kilobytes from each archive. You may give the number in megabyt \fB\-\-max\-recursion=#n\fR Set archive recursion level limit. This option protects your system against DoS attacks (default: 5). .TP +\fB\-\-max\-ratio=#n\fR +Set maximum archive compression ratio limit. This option protects your system against DoS attacks (default: 200). +.TP \fB\-\-unzip[=FULLPATH]\fR In most cases you don't need this option \- the built\-in unarchiver will do extract Zip archives. This option however may be used as a backup for internal unpacker \- see the full documentation for more information. When enabled without an argument, unzip program will be searched in $PATH. If unzip cannot be found in $PATH, you must force it with =pathname. Remember about '=' between the option and an argument. .TP diff --git a/clamav-devel/libclamav/ole2_extract.c b/clamav-devel/libclamav/ole2_extract.c index 6260f77c8..ceb26eb32 100644 --- a/clamav-devel/libclamav/ole2_extract.c +++ b/clamav-devel/libclamav/ole2_extract.c @@ -513,9 +513,9 @@ static void ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir, snprintf(dirname, strlen(dir)+8, "%s/%.6d", dir, prop_index); mkdir(dirname, 0700); cli_dbgmsg("OLE2 dir entry: %s\n",dirname); - ole2_walk_property_tree(fd, hdr, dirname, + ole2_walk_property_tree(fd, hdr, dir, prop_block[index].prev, handler, rec_level+1, file_count); - ole2_walk_property_tree(fd, hdr, dirname, + ole2_walk_property_tree(fd, hdr, dir, prop_block[index].next, handler, rec_level+1, file_count); ole2_walk_property_tree(fd, hdr, dirname, prop_block[index].child, handler, rec_level+1, file_count); @@ -719,11 +719,11 @@ int cli_ole2_extract(int fd, const char *dirname) /* NOTE: Select only ONE of the following two methods */ - ole2_read_property_tree(fd, &hdr, dirname, handler_writefile); + /* ole2_read_property_tree(fd, &hdr, dirname, handler_writefile); */ /* OR */ - /* ole2_walk_property_tree(fd, &hdr, dirname, 0, handler_writefile, 0, 0); */ + ole2_walk_property_tree(fd, &hdr, dirname, 0, handler_writefile, 0, 0); return 0; } diff --git a/clamav-devel/libclamav/scanners.c b/clamav-devel/libclamav/scanners.c index 0c2af46f8..200fecaa6 100644 --- a/clamav-devel/libclamav/scanners.c +++ b/clamav-devel/libclamav/scanners.c @@ -79,18 +79,32 @@ static const struct cli_magic_s cli_magic[] = { {0, "Return-path: ", 13, "Maildir", CL_MAILFILE}, {0, "Delivered-To: ", 14, "Mail", CL_MAILFILE}, {0, "X-UIDL: ", 8, "Mail", CL_MAILFILE}, + {0, ">From ", 6, "Mail", CL_MAILFILE}, + {0, "Date: ", 6, "Mail", CL_MAILFILE}, + {0, "Message-Id: ", 12, "Mail", CL_MAILFILE}, + {0, "Message-ID: ", 12, "Mail", CL_MAILFILE}, + {0, "X-Apparently-To: ", 17, "Mail", CL_MAILFILE}, {0, "For: ", 5, "Eserv mail", CL_MAILFILE}, {0, "From: ", 6, "Exim mail", CL_MAILFILE}, {0, "X-Symantec-", 11, "Symantec", CL_MAILFILE}, - {0, "X-Apparently-To: ", 17, "Mail", CL_MAILFILE}, - {0, "For: ", 5, "Eserv mail", CL_MAILFILE}, {0, "X-EVS", 5, "EVS mail", CL_MAILFILE}, - {0, ">From ", 6, "Symantec", CL_MAILFILE}, {0, "v:\015\012Received: ", 14, "VPOP3 Mail (DOS)", CL_MAILFILE}, {0, "v:\012Received: ", 13, "VPOP3 Mail (UNIX)", CL_MAILFILE}, {0, "Hi. This is the qmail-send", 26, "Qmail bounce", CL_MAILFILE}, {0, "\320\317\021\340\241\261\032\341", 8, "OLE2 container", CL_OLE2FILE}, + /* Ignored types */ + + {0, "\000\000\001\263", 4, "MPEG video stream", CL_DATAFILE}, + {0, "\000\000\001\272", 4, "MPEG sys stream", CL_DATAFILE}, + {0, "RIFF", 4, "RIFF file", CL_DATAFILE}, + {0, "GIF87a", 6, "GIF (87a)", CL_DATAFILE}, + {0, "GIF89a", 6, "GIF (89a)", CL_DATAFILE}, + {0, "\x89PNG\r\n\x1a\n", 8, "PNG", CL_DATAFILE}, + {0, "\377\330\377\340", 4, "JPEG", CL_DATAFILE}, + {0, "\377\330\377\356", 4, "JPG", CL_DATAFILE}, + {0, "OggS", 4, "Ogg Stream", CL_DATAFILE}, + {-1, NULL, 0, NULL, CL_UNKNOWN_TYPE} }; @@ -352,19 +366,18 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const break; } - cli_dbgmsg("Zip -> %s, compressed: %d, normal: %d, encrypted flag: %d\n", zdirent.d_name, zdirent.d_csize, zdirent.st_size, zdirent.d_flags); - - if(limits && limits->maxratio > 0 && source.st_size && (zdirent.st_size / source.st_size) >= limits->maxratio) { - *virname = "Oversized.Zip"; - ret = CL_VIRUS; - break; - } + cli_dbgmsg("Zip -> %s, compressed: %u, normal: %u, ratio: %d (max: %d)\n", zdirent.d_name, zdirent.d_csize, zdirent.st_size, zdirent.st_size / (zdirent.d_csize+1), limits ? limits->maxratio : -1 ); if(!zdirent.st_size) { /* omit directories and null files */ files++; continue; } + if(limits && limits->maxratio > 0 && ((unsigned) zdirent.st_size / (unsigned) zdirent.d_csize) >= limits->maxratio) { + files++; + continue; + } + /* work-around for problematic zips (zziplib crashes with them) */ if(zdirent.d_csize < 0 || zdirent.st_size < 0) { files++; @@ -412,9 +425,8 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const break; } - while((bytes = zzip_file_read(zfp, buff, FILEBUFF)) > 0) { - if(fwrite(buff, bytes, 1, tmp)*bytes != bytes) { + if(fwrite(buff, 1, bytes, tmp) != (size_t) bytes) { cli_dbgmsg("Zip -> Can't fwrite() file: %s\n", strerror(errno)); zzip_file_close(zfp); zzip_dir_close(zdir); @@ -624,89 +636,103 @@ static int cli_scanbzip(int desc, const char **virname, long int *scanned, const } #endif -static int cli_scanole2(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev) +static int cli_scandir(const char *dirname, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev) { - const char *tmpdir; - char *dir, *fullname; - unsigned char *data; - int ret = CL_CLEAN, fd, i, data_len; - vba_project_t *vba_project; - - cli_dbgmsg("in cli_scanole2()\n"); - - tmpdir = getenv("TMPDIR"); + DIR *dd; + struct dirent *dent; + struct stat statbuf; + char *fname; - if(tmpdir == NULL) -#ifdef P_tmpdir - tmpdir = P_tmpdir; -#else - tmpdir = "/tmp"; -#endif - /* generate the temporary directory */ - dir = cl_gentemp(tmpdir); - if(mkdir(dir, 0700)) { - cli_errmsg("ScanOLE2 -> Can't create temporary directory %s\n", dir); - return CL_ETMPDIR; - } + if((dd = opendir(dirname)) != NULL) { + while((dent = readdir(dd))) { + if(dent->d_ino) { + if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { + /* build the full name */ + fname = cli_calloc(strlen(dirname) + strlen(dent->d_name) + 2, sizeof(char)); + sprintf(fname, "%s/%s", dirname, dent->d_name); - if((ret = cli_ole2_extract(desc, dir))) { - cli_errmsg("ScanOLE2 -> %s\n", cl_strerror(ret)); - cli_rmdirs(dir); - free(dir); - return ret; - } + /* stat the file */ + if(lstat(fname, &statbuf) != -1) { + if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) { + if (cli_scandir(fname, virname, scanned, root, limits, options, reclev) == CL_VIRUS) { + free(fname); + closedir(dd); + return CL_VIRUS; + } + } else + if(S_ISREG(statbuf.st_mode)) + if(cli_scanfile(fname, virname, scanned, root, limits, options, reclev) == CL_VIRUS) { + free(fname); + closedir(dd); + return CL_VIRUS; + } - if((vba_project = (vba_project_t *) vba56_dir_read(dir))) { - - for(i = 0; i < vba_project->count; i++) { - fullname = (char *) malloc(strlen(vba_project->dir) + strlen(vba_project->name[i]) + 2); - sprintf(fullname, "%s/%s", vba_project->dir, vba_project->name[i]); - fd = open(fullname, O_RDONLY); - if(fd == -1) { - cli_errmsg("Scan->OLE2 -> Can't open file %s\n", fullname); - free(fullname); - ret = CL_EOPEN; - break; - } - free(fullname); - cli_dbgmsg("decompress VBA project '%s'\n", vba_project->name[i]); - data = (unsigned char *) vba_decompress(fd, vba_project->offset[i], &data_len); - close(fd); - - if(!data) { - cli_dbgmsg("WARNING: VBA project '%s' decompressed to NULL\n", vba_project->name[i]); - } else { - if(cl_scanbuff(data, data_len, virname, root) == CL_VIRUS) { - free(data); - ret = CL_VIRUS; - break; } - - free(data); + free(fname); } } - - for(i = 0; i < vba_project->count; i++) - free(vba_project->name[i]); - free(vba_project->name); - free(vba_project->dir); - free(vba_project->offset); - free(vba_project); } + } else { + cli_errmsg("ScanDir -> Can't open directory %s.\n", dirname); + return CL_EOPEN; + } - - cli_rmdirs(dir); - free(dir); - return ret; + closedir(dd); + return 0; } -static int cli_scandir(char *dirname, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev) + +static int cli_vba_scandir(const char *dirname, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev) { + int ret = CL_CLEAN, i, fd, data_len; + vba_project_t *vba_project; DIR *dd; struct dirent *dent; struct stat statbuf; - char *fname; + char *fname, *dir, *fullname; + unsigned char *data; + + cli_dbgmsg("VBA scan dir: %s\n", dirname); + if((vba_project = (vba_project_t *) vba56_dir_read(dirname))) { + for(i = 0; i < vba_project->count; i++) { + fullname = (char *) cli_malloc(strlen(vba_project->dir) + strlen(vba_project->name[i]) + 2); + sprintf(fullname, "%s/%s", vba_project->dir, vba_project->name[i]); + fd = open(fullname, O_RDONLY); + if(fd == -1) { + cli_errmsg("Scan->OLE2 -> Can't open file %s\n", fullname); + free(fullname); + ret = CL_EOPEN; + break; + } + free(fullname); + cli_dbgmsg("decompress VBA project '%s'\n", vba_project->name[i]); + data = (unsigned char *) vba_decompress(fd, vba_project->offset[i], &data_len); + close(fd); + + if(!data) { + cli_dbgmsg("WARNING: VBA project '%s' decompressed to NULL\n", vba_project->name[i]); + } else { + if(cl_scanbuff(data, data_len, virname, root) == CL_VIRUS) { + free(data); + ret = CL_VIRUS; + break; + } + + free(data); + } + } + + for(i = 0; i < vba_project->count; i++) + free(vba_project->name[i]); + free(vba_project->name); + free(vba_project->dir); + free(vba_project->offset); + free(vba_project); + } + + if(ret != CL_CLEAN) + return ret; if((dd = opendir(dirname)) != NULL) { while((dent = readdir(dd))) { @@ -719,15 +745,11 @@ static int cli_scandir(char *dirname, const char **virname, long int *scanned, c /* stat the file */ if(lstat(fname, &statbuf) != -1) { if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) - cli_scandir(fname, virname, scanned, root, limits, options, reclev); - else - if(S_ISREG(statbuf.st_mode)) - if(cli_scanfile(fname, virname, scanned, root, limits, options, reclev) == CL_VIRUS) { - free(fname); - closedir(dd); - return CL_VIRUS; - } - + if (cli_vba_scandir(fname, virname, scanned, root, limits, options, reclev) == CL_VIRUS) { + ret = CL_VIRUS; + free(fname); + break; + } } free(fname); } @@ -739,7 +761,51 @@ static int cli_scandir(char *dirname, const char **virname, long int *scanned, c } closedir(dd); - return 0; + return ret; +} + +static int cli_scanole2(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev) +{ + const char *tmpdir; + char *dir, *fullname; + unsigned char *data; + int ret = CL_CLEAN, fd, i, data_len; + vba_project_t *vba_project; + + cli_dbgmsg("in cli_scanole2()\n"); + + tmpdir = getenv("TMPDIR"); + + if(tmpdir == NULL) +#ifdef P_tmpdir + tmpdir = P_tmpdir; +#else + tmpdir = "/tmp"; +#endif + + /* generate the temporary directory */ + dir = cl_gentemp(tmpdir); + if(mkdir(dir, 0700)) { + cli_errmsg("ScanOLE2 -> Can't create temporary directory %s\n", dir); + return CL_ETMPDIR; + } + + if((ret = cli_ole2_extract(desc, dir))) { + cli_errmsg("ScanOLE2 -> %s\n", cl_strerror(ret)); + cli_rmdirs(dir); + free(dir); + return ret; + } + + if((ret = cli_vba_scandir(dir, virname, scanned, root, limits, options, reclev)) != CL_VIRUS) { + if(cli_scandir(dir, virname, scanned, root, limits, options, reclev) == CL_VIRUS) { + ret = CL_VIRUS; + } + } + + cli_rmdirs(dir); + free(dir); + return ret; } static int cli_scanmail(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev) @@ -797,77 +863,74 @@ static int cli_magic_scandesc(int desc, const char **virname, long int *scanned, return -1; } - - if(SCAN_ARCHIVE || SCAN_MAIL) { - /* Need to examine file type */ - - if(SCAN_ARCHIVE && limits && limits->maxreclevel) - if(*reclev > limits->maxreclevel) - /* return CL_EMAXREC; */ - return CL_CLEAN; - - (*reclev)++; + if(SCAN_ARCHIVE && limits && limits->maxreclevel) + if(*reclev > limits->maxreclevel) + /* return CL_EMAXREC; */ + return CL_CLEAN; - lseek(desc, 0, SEEK_SET); - bread = read(desc, magic, MAGIC_BUFFER_SIZE); - magic[MAGIC_BUFFER_SIZE] = '\0'; /* terminate magic string properly */ - lseek(desc, 0, SEEK_SET); + (*reclev)++; + lseek(desc, 0, SEEK_SET); + bread = read(desc, magic, MAGIC_BUFFER_SIZE); + magic[MAGIC_BUFFER_SIZE] = '\0'; + lseek(desc, 0, SEEK_SET); + if (bread != MAGIC_BUFFER_SIZE) { + /* short read: No need to do magic */ + (*reclev)--; + return ret; + } - if (bread != MAGIC_BUFFER_SIZE) { - /* short read: No need to do magic */ - (*reclev)--; - return ret; - } - - type = cli_filetype(magic, bread); + type = cli_filetype(magic, bread); - switch(type) { - case CL_RARFILE: - if(!DISABLE_RAR && SCAN_ARCHIVE && !cli_scanrar_inuse) { - ret = cli_scanrar(desc, virname, scanned, root, limits, options, reclev); - } - break; + switch(type) { + case CL_RARFILE: + if(!DISABLE_RAR && SCAN_ARCHIVE && !cli_scanrar_inuse) + ret = cli_scanrar(desc, virname, scanned, root, limits, options, reclev); + break; - case CL_ZIPFILE: - if(SCAN_ARCHIVE) { - ret = cli_scanzip(desc, virname, scanned, root, limits, options, reclev); - } - break; + case CL_ZIPFILE: + if(SCAN_ARCHIVE) + ret = cli_scanzip(desc, virname, scanned, root, limits, options, reclev); + break; - case CL_GZFILE: - if(SCAN_ARCHIVE) { - ret = cli_scangzip(desc, virname, scanned, root, limits, options, reclev); - } - break; + case CL_GZFILE: + if(SCAN_ARCHIVE) + ret = cli_scangzip(desc, virname, scanned, root, limits, options, reclev); + break; - case CL_BZFILE: + case CL_BZFILE: #ifdef HAVE_BZLIB_H - if(SCAN_ARCHIVE) { - ret = cli_scanbzip(desc, virname, scanned, root, limits, options, reclev); - } + if(SCAN_ARCHIVE) + ret = cli_scanbzip(desc, virname, scanned, root, limits, options, reclev); #endif - break; + break; - case CL_MAILFILE: - if (SCAN_MAIL) { - ret = cli_scanmail(desc, virname, scanned, root, limits, options, reclev); - } - break; + case CL_MAILFILE: + if(SCAN_MAIL) + ret = cli_scanmail(desc, virname, scanned, root, limits, options, reclev); + break; - case CL_OLE2FILE: - if(SCAN_OLE2) { - ret = cli_scanole2(desc, virname, scanned, root, limits, options, reclev); - } - case CL_UNKNOWN_TYPE: - break; - } + case CL_OLE2FILE: + if(SCAN_OLE2) + ret = cli_scanole2(desc, virname, scanned, root, limits, options, reclev); + break; - (*reclev)--; + case CL_DATAFILE: + /* it could be a false positive and a standard DOS .COM file */ + { + struct stat s; + if(fstat(desc, &s) == 0 && S_ISREG(s.st_mode) && s.st_size < 65536) + type = CL_UNKNOWN_TYPE; + } + + case CL_UNKNOWN_TYPE: + break; } - if(ret != CL_VIRUS) { /* scan the raw file */ + (*reclev)--; + + if(type != CL_DATAFILE && ret != CL_VIRUS) { /* scan the raw file */ lseek(desc, 0, SEEK_SET); /* If archive scan didn't rewind desc */ if(cli_scandesc(desc, virname, scanned, root) == CL_VIRUS) { cli_dbgmsg("%s virus found in descriptor %d.\n", *virname, desc); diff --git a/clamav-devel/libclamav/scanners.h b/clamav-devel/libclamav/scanners.h index 6edb79f6d..0952e3bb7 100644 --- a/clamav-devel/libclamav/scanners.h +++ b/clamav-devel/libclamav/scanners.h @@ -22,6 +22,7 @@ typedef enum { CL_UNKNOWN_TYPE = 0, + CL_DATAFILE, CL_MAILFILE, CL_GZFILE, CL_ZIPFILE,