通过perl实现一个简单的NIDS

2019-10-01 13:23:31王冬梅

$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/x06x06x2bx06x01x05x05x02.*[xa1x05x23x03x03x01x07 x84xffxffxff]/)) {
# 记入日志文件
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命令溢出攻击