用PERL实现一个简单的NIDS(2)

发表于:2007-06-23来源:作者:点击数: 标签:
用PERL实现一个简单的NIDS perl-ids.pl 实现抓包及检测分析的主程序。 -------- 8 -------------- #!/usr/bin/perl # # Comments/suggestions to stardust at xfocus dot org # # # $Id: perl-ids.pl,v 1.16 2004/03/04 21:51:12 stardust Exp $ # # 引用所

   
  用PERL实现一个简单的NIDS
    perl-ids.pl
实现抓包及检测分析的主程序。
-------- 8< --------------
#!/usr/bin/perl
#
# Comments/suggestions to stardust at xfocus dot org
#
#

# $Id: perl-ids.pl,v 1.16 2004/03/04 21:51:12 stardust Exp $
#

# 引用所有相关的模块
use Net::PcapUtils;
use NetPacket::Ethe.net qw(:strip);
use NetPacket::TCP;
use NetPacket::IP qw(:protos);
use NetPacket::SMB;
use NetPacket::FTP;

# 定义日志文件名
$workingdir = "./";
$attacklog = "attack.log";
$monitorlog = "monitor.log";

# 以后台进程方式运行
daemon ();

sub daemon {
unless (fork) {
SniffLoop ();
exit 0;
}
exit 1;
}

# 抓包循环
sub SniffLoop {

# 进入工作目录
chdir ("$workingdir");
# 打开日志文件
open (ATTACKLOG,">> $attacklog");
open (MONITORLOG,">> $monitorlog");
# 设置文件读写为非缓冲模式
select(ATTACKLOG); $ ++; select(MONITORLOG); $ ++; select(STDOUT); $ ++;

# 设置信号处理函数,因为程序运行于后台,退出时需要利用信号处理函数做些清理工作
$SIG{"INT"} = 'HandleINT';
$SIG{"TERM"} = 'HandleTERM';

# 进入抓包回调函数
Net::PcapUtils::loop(\&sniffit, SNAPLEN => 1800, Promisc => 1, FILTER => 'tcp or udp', DEV => 'eth0');
}

sub sniffit {
my ($args,$header,$packet) = @_;
# 解码IP包
$ip = NetPacket::IP->decode(eth_strip($packet));

# TCP协议
if ($ip->{proto} == IP_PROTO_TCP) {
# 解码TCP包
$tcp = NetPacket::TCP->decode($ip->{data});

# 检查来自SMB客户端的包
if (($tcp->{dest_port} == 139)    ($tcp->{dest_port} == 445)) {
# 如果目的端口是139或445,认为是SMB协议包,做相应的检查
SmbClientCheck ($ip->{src_ip},$tcp->{src_port},$ip->{dest_ip},$tcp->{dest_port},$tcp->{data});

} elsif ($tcp->{dest_port} == 21) {
# 如果目的端口是21,认为是FTP协议,做相应的检查
FtpClientCheck ($ip->{src_ip},$tcp->{src_port},$ip->{dest_ip},$tcp->{dest_port},$tcp->{data});

} else {}
# UDP协议
} elsif ($ip->{proto} == IP_PROTO_UDP) {
} else {}
}

sub SmbClientCheck {
my ($src_ip,$src_port,$dest_ip,$dst_port,$data) = @_;

# 调用SMB解码模块解码
$smb = NetPacket::SMB->decode($data);

# 如果解码成功
if ($smb->{valid}) {
# 示例检测新近公布eeye的那个ASN.1解码错误导致的堆破坏漏洞
# BID:9633,9635 CVEID:CAN-2003-0818 NSFOCUSID:6000

# 如果SMB命令是Session Setup AndX
if ($smb->{cmd} == 0x73) {
# 如果设置了Extended Security Negotiation位,表示有包里有Security Blob
if ($smb->{flags2} & F2_EXTSECURINEG) {
# 用正则表达式匹配通常会在攻击包里出现的OID及引发错误的畸形数据串
# 由于不是从原理上检测加之ASN.1编码的灵活性,这样的检测会导致漏报
if (($smb->{bytecount} > 0) && ($smb->{bytes} =~ m/\x06\x06\x2b\x06\x01\x05\x05\x02.*[\xa1\x05\x23\x03\x03\x01\x07 \x84\xff\xff\xff]/)) {
# 记入日志文件
LogAlert ($src_ip,$src_port,$dest_ip,$dst_port,"ASN.1 malform encode attack!");
}
}
}
}
}

sub FtpClientCheck {
my ($src_ip,$src_port,$dest_ip,$dst_port,$data) = @_;

# 调用FTP解码模块解码
$ftp = NetPacket::FTP->decode($data);

# 如果解码成功
if ($ftp->{valid}) {
# 示例检测新近公布的Serv-U < 5.0.0.4版FTP服务器MDTM命令溢出攻击
# BID:9751 NSFOCUSID:6078

# 遍历从数据包里解码出来的FTP命令及其参数
for (my $i = 1;$i <= $ftp->{cmdcount};$i++) {
my $cmd = "cmd"."$i";
my $para = "para"."$i";
# 如果FTP命令是MDTM
if (uc($ftp->{$cmd}) eq "MDTM") {
# 用正则表达式匹配引发溢出的参数串,这里体现了正则
# 表达式的强大,用此匹配可以从原理上检测到畸形参数串
if ($ftp->{$para} =~ m/\d{14}[+ -]\S{5,}\s+\S{1,}/) {
LogAlert ($src_ip,$src_port,$dest_ip,$dst_port,"Serv-U < v5.0.0.4 MDTM command long timezone string overflow attack!");
}
}
}
}
}

# 记录攻击告警
sub LogAlert {
my ($src_ip,$src_port,$dest_ip,$dst_port,$message) = @_;

my $nowtime = localtime;
printf ATTACKLOG ("%s\t%s:%s -> %s:%s\t%s\n",$nowtime,$src_ip,$src_port,$dest_ip,$dst_port,$message);
printf ("%s\t%s:%s -> %s:%s\t%s\n",$nowtime,$src_ip,$src_port,$dest_ip,$dst_port,$message);
}

# 记录监控信息
sub LogMonitor {
my ($src_ip,$src_port,$dest_ip,$dst_port,$message) = @_;

my $nowtime = localtime;
printf MONITORLOG ("%s\t%s:%s -> %s:%s\t%s\n",$nowtime,$src_ip,$src_port,$dest_ip,$dst_port,$message);
printf ("%s\t%s:%s -> %s:%s\t%s\n",$nowtime,$src_ip,$src_port,$dest_ip,$dst_port,$message);
}

# INT信号处理例程
sub HandleINT {

CleanUp ();
exit (0);
}

# TERM信号处理例程
sub HandleTERM {

CleanUp ();
exit (0);
}

# 清理,主要工作是关闭文件句柄
sub CleanUp {
close (ATTACKLOG); close (MONITORLOG);
}
-------- 8< --------------

原文转自:http://www.ltesting.net