#! /usr/bin/perl
#
# 本程式用來濾除 /var/spool/mail 信包檔中的 "求職信" 病毒。
# 想法如下:
# 信件尚未放入 /var/spool/mail 之前, 您可以用 procmail 來濾除,
# 但先前已餵入 /var/spool/mail 中的病毒信件, 怎麼辦呢? 因此, 才有這隻程式的產生.
#
# 不過, 本人無法保證它一定會百分之百濾除;
# 使用前您應該自己對執行時可能承擔的風險先考慮清楚!
# 若有任何損失, 本人概不負責.
#
# 使用前, 您應先將 /var/spool/mail 這個目錄予以備份.
# (註: 若是 FreeBSD, 則可能是 /var/mail 這個目錄)
# 例如:
# cp -Rp /var/spool/mail /tmp/save.mail
# su - 成 root 身份
# 將本程式放入 /var/spool/mail 中, chmod 755 filter_mail.pl
# 執行 ./filter_mail.pl
# 它會將 /var/spool/mail 中的信包檔在 /tmp/filt_msg_tmp 目錄中, 一封一封解開.
# 然後予以過濾寫回. 執行結束之後, /var/spool/mail 中的權限仍然會保持原樣.
# 所有解開的信件檔, 都在 /tmp/filt_msg_tmp 目錄中, 若一切正常, 可以將該目錄刪除.
# 若有不正常, 可自行用 cat 指令將信件檔組合回去, 或將原先備份的信包檔蓋回去.
#
# 本程式稍加修改, 即可用來過濾其它的病毒.
#
# 版權宣告:
# Copyright (c) 2002 by OLS3(ols3@www.tnc.edu.tw) 04/20/2002
# 本程式為 GPL 軟體.
# 發佈這一程式的目的是希望它有用,但沒有任何擔保。
# 甚至沒有適合特定目的而隱含的擔保。
# 更詳細的情況請參考 GNU 通用公共許可證。
# 當您修改和重新發佈本軟體時,請保留版權宣告的文字部份。
#
# $Id: chapF.sgml,v 1.1.1.1 2003/08/14 00:26:12 ols3 Exp $
use strict;
show_title();
while(my $msg_file=<*>) {
if ($msg_file eq 'filter_mail.pl') { next;}
print "Processing spool mail ---> $msg_file\n";
open(FHD, "$msg_file") || die;
flock(FHD, 2);
# 將信包檔的每一封信分開存放, 以數字為檔名, 放在 /tmp/filt_msg_tmp/使用者帳號/ 目錄下
split_msg(\*FHD, $msg_file);
flock(FHD, 8);
close(FHD);
# 處理這些信件
proc_msg($msg_file);
print "Done! \n";
}
sub show_title {
system("clear");
print <<HERE;
/*--------------------------------------------*/
/* Filter spool mail v1.0.1 (GPL) */
/* Copyright (c) 2002 written by OLS3 */
/*--------------------------------------------*/
HERE
}
sub split_msg {
my $fh = shift;
my $user_id=shift;
my $count=1;
my $s=1;
my $bline='ols3Tp1iz2a134598132308abcdefghijk123pisa#############';
my $line;
my $msg_start='^From\s.*?@?.*?\s+?\w+\s\w+\s\d+\s\d+:\d+:\d+\s\d+';
my $msg_name='';
my $t2_dir = "/tmp/filt_msg_tmp";
my $tmp_dir = "$t2_dir/$user_id/";
if (! -e $t2_dir) { mkdir $t2_dir, 0777; }
if (! -e $tmp_dir) { mkdir $tmp_dir, 0777; }
my $k=1;
while($line = <$fh>) {
print print_process_status($k);
# 處理第一封信件
if ($s == 1) {
$msg_name= $tmp_dir . $count . '.msg';
open(FH, "> $msg_name")||die;
$s=0;
}
if (($line =~ /$msg_start/) && !$bline) {
# 關檔結束寫入上一封信
close(FH);
# 開檔寫入新的一封信
$count++;
$msg_name= $tmp_dir . $count . '.msg';
open(FH, "> $msg_name")||die;
}
$bline=$line;
chomp $bline;
print FH $line || die;
$k++;
}
close(FH);
}
sub get_ugid {
my @attr=stat(shift);
return @attr[4,5];
}
sub proc_msg {
my $msgf=shift;
my ($uid, $gid)=get_ugid($msgf);
# 刪除信包檔
if (-e $msgf) {
unlink $msgf;
}
# 開一個空檔
open(FHE, "> $msgf");
close(FHE);
# 修改屬性
chown($uid, $gid, "$msgf");
chmod 0660, $msgf;
open(FHE, ">> $msgf");
flock(FHE, 2);
my $i=1;
while(my $fn=glob("/tmp/filt_msg_tmp/$msgf/*.msg")) {
print print_process_status($i);
if (!filt_msg($fn)) {
open(F, "$fn") || die;
while(<F>) {
print FHE;
}
close(F);
} else {
print "find virus! delete $fn !\n";
}
$i++;
}
flock(FHE, 8);
close(FHE);
}
sub filt_msg {
my $msg=shift;
my ($sm, $fm, $bm);
my $s_001 = "\<iframe.*?src=.*?height=3D0.*?width=3D0\>";
my $t_001 = '^Content-Type: application/octet-stream';
my $t_002 = '^Content-Type: audio/x-midi';
my $t_003 = '^Content-Type: audio/x-wav';
my $f_001 = 'name=.*?\.scr';
my $f_002 = 'name=.*?\.exe';
my $f_003 = 'name=.*?\.pif';
my $f_004 = 'name=.*?\.bat';
open(FHD_msg, "$msg") || die "open msg error!\n";
while(my $line=<FHD_msg>) {
if ($line =~ /$s_001/) { $sm=1; }
if ($line =~ /$t_001|$t_002|$t_003/) { $fm=1; }
if ($line =~ /$f_001|$f_002|$f_003|$f_004/) { $bm=1;}
if ($sm || ($fm && $bm)) { return 1; }
}
return 0;
}
sub print_process_status {
my $i=shift;
my $j = $i % 4;
SWITCH : {
$j == 0 && do { print STDERR " (|)\r"; last SWITCH; };
$j == 1 && do { print STDERR " (/)\r"; last SWITCH; };
$j == 2 && do { print STDERR " (-)\r"; last SWITCH; };
$j == 3 && do { print STDERR " (\\)\r"; last SWITCH; };
}
}
|