欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

通過perl實現(xiàn)一個簡單的NIDS

 更新時間:2013年02月09日 21:43:57   作者:  
使用perl實現(xiàn)一個簡單的NIDS,有需要的朋友可以參考下

隨著對網(wǎng)絡(luò)安全需求的深入開發(fā),基于網(wǎng)絡(luò)的入侵檢測技術(shù)已經(jīng)成為一個重要且有意思的研究方向。想學(xué)習(xí)NIDS技術(shù)除了去讀一些現(xiàn)成的資料和一些開源系統(tǒng)的源碼,最好的辦法莫過于自己去寫一個NIDS程序,只有那樣才能真正體會到一些NIDS的實現(xiàn)需求和設(shè)計妙處。

本質(zhì)上說NIDS只是一種網(wǎng)絡(luò)流量的分析工具,通過對網(wǎng)絡(luò)流量的分析識別出一些已知或未知的攻擊行為,一個最簡單的NIDS完成的主要工作也就是抓包->協(xié)議解碼->匹配,眾所周知PERL是極其強大的腳本語言,尤其是它的字符串處理能力可以方便地實現(xiàn)對于網(wǎng)絡(luò)流量中惡意特征進行匹配。當(dāng)然PERL畢竟只是腳本語言,它的執(zhí)行效率不允許用于真正大流量生產(chǎn)性環(huán)境,但PERL的簡單易學(xué)及強大功能對于實現(xiàn)一個簡單的NIDS達到學(xué)習(xí)的目的無疑是非常好的,下面我介紹一個用PERL實現(xiàn)的簡單NIDS框架,我們將在Linux下實現(xiàn)它,在其他操作系統(tǒng)上類似。

PERL的一個強大特性就在于它海量的CPAN模塊庫,很多你想實現(xiàn)的功能都可以找到現(xiàn)成的模塊,你所要做的只是安裝上那些模塊即可,關(guān)于PERL的模塊及面向?qū)ο筇匦缘墓芾砗褪褂迷谶@就不介紹了,請參看相關(guān)資料,比如O'REILLY出版的《高級Perl編程》。在用PERL編寫網(wǎng)絡(luò)流量分析腳本之前,需要安裝一些底層的抓包及基本的數(shù)據(jù)包解碼模塊,包括如下這些:
http://www.tcpdump.org/release/libpcap-0.8.1.tar.gz
底層基本的抓包庫。

http://www.cpan.org/authors/id/T/TI/TIMPOTTER/Net-Pcap-0.04.tar.gz
libpcap的PERL接口。

http://www.cpan.org/authors/id/T/TI/TIMPOTTER/Net-PcapUtils-0.01.tar.gz
Net-Pcap模塊的wrapper,包裝Net-Pcap的函數(shù),可以更方便地在PERL里調(diào)用抓包。

http://www.cpan.org/authors/id/T/TI/TIMPOTTER/NetPacket-0.03.tar.gz
用于基本的IP/TCP/UDP等包解碼的模塊,剝除各種協(xié)議頭,抽取各個字段。

下面的代碼演示了一個帶有基本SMB和FTP協(xié)議解碼模塊的最簡單NIDS框架,此程序?qū)崿F(xiàn)最簡單的NIDS功能,面向單包,不關(guān)心包的狀態(tài),不具備高級的商業(yè)NIDS產(chǎn)品諸如流重組,包狀態(tài)及應(yīng)用層協(xié)議的跟蹤等功能。為了提高檢測的準(zhǔn)確性,與Snort直接匹配數(shù)據(jù)區(qū)不同的是,這個腳本實現(xiàn)了兩個應(yīng)用層協(xié)議:SMB、FTP的簡單解碼,解碼完全是面向NIDS的需要,代碼也沒有經(jīng)過仔細(xì)的測試可能存在問題。

(一)perl-ids.pl 實現(xiàn)抓包及檢測分析的主程序。

復(fù)制代碼 代碼如下:

#!/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 $
#
# 引用所有相關(guān)的模塊
use Net::PcapUtils;
use NetPacket::Ethernet 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;
}
# 抓包循環(huán)
sub SniffLoop {
# 進入工作目錄
chdir ("$workingdir");
# 打開日志文件
open (ATTACKLOG,">> $attacklog");
open (MONITORLOG,">> $monitorlog");
# 設(shè)置文件讀寫為非緩沖模式
select(ATTACKLOG); $ ++; select(MONITORLOG); $ ++; select(STDOUT); $ ++;
# 設(shè)置信號處理函數(shù),因為程序運行于后臺,退出時需要利用信號處理函數(shù)做些清理工作
$SIG{"INT"} = 'HandleINT';
$SIG{"TERM"} = 'HandleTERM';
# 進入抓包回調(diào)函數(shù)
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協(xié)議
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,認(rèn)為是SMB協(xié)議包,做相應(yīng)的檢查
SmbClientCheck ($ip->{src_ip},$tcp->{src_port},$ip->{dest_ip},$tcp->{dest_port},$tcp->{data});
} elsif ($tcp->{dest_port} == 21) {
# 如果目的端口是21,認(rèn)為是FTP協(xié)議,做相應(yīng)的檢查
FtpClientCheck ($ip->{src_ip},$tcp->{src_port},$ip->{dest_ip},$tcp->{dest_port},$tcp->{data});
} else {}
# UDP協(xié)議
} elsif ($ip->{proto} == IP_PROTO_UDP) {
} else {}
}
sub SmbClientCheck {
my ($src_ip,$src_port,$dest_ip,$dst_port,$data) = @_;
# 調(diào)用SMB解碼模塊解碼
$smb = NetPacket::SMB->decode($data);
# 如果解碼成功
if ($smb->{valid}) {
# 示例檢測新近公布eeye的那個ASN.1解碼錯誤導(dǎo)致的堆破壞漏洞
# BID:9633,9635 CVEID:CAN-2003-0818 NSFOCUSID:6000
# 如果SMB命令是Session Setup AndX
if ($smb->{cmd} == 0x73) {
# 如果設(shè)置了Extended Security Negotiation位,表示有包里有Security Blob
if ($smb->{flags2} & F2_EXTSECURINEG) {
# 用正則表達式匹配通常會在攻擊包里出現(xiàn)的OID及引發(fā)錯誤的畸形數(shù)據(jù)串
# 由于不是從原理上檢測加之ASN.1編碼的靈活性,這樣的檢測會導(dǎo)致漏報
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) = @_;
# 調(diào)用FTP解碼模塊解碼
$ftp = NetPacket::FTP->decode($data);
# 如果解碼成功
if ($ftp->{valid}) {
# 示例檢測新近公布的Serv-U < 5.0.0.4版FTP服務(wù)器MDTM命令溢出攻擊
# BID:9751 NSFOCUSID:6078
# 遍歷從數(shù)據(jù)包里解碼出來的FTP命令及其參數(shù)
for (my $i = 1;$i <= $ftp->{cmdcount};$i++) {
my $cmd = "cmd"."$i";
my $para = "para"."$i";
# 如果FTP命令是MDTM
if (uc($ftp->{$cmd}) eq "MDTM") {
# 用正則表達式匹配引發(fā)溢出的參數(shù)串,這里體現(xiàn)了正則
# 表達式的強大,用此匹配可以從原理上檢測到畸形參數(shù)串
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 %s:%s -> %s:%s %s ",$nowtime,$src_ip,$src_port,$dest_ip,$dst_port,$message);
printf ("%s %s:%s -> %s:%s %s ",$nowtime,$src_ip,$src_port,$dest_ip,$dst_port,$message);
}
# 記錄監(jiān)控信息
sub LogMonitor {
my ($src_ip,$src_port,$dest_ip,$dst_port,$message) = @_;
my $nowtime = localtime;
printf MONITORLOG ("%s %s:%s -> %s:%s %s ",$nowtime,$src_ip,$src_port,$dest_ip,$dst_port,$message);
printf ("%s %s:%s -> %s:%s %s ",$nowtime,$src_ip,$src_port,$dest_ip,$dst_port,$message);
}
# INT信號處理例程
sub HandleINT {
CleanUp ();
exit (0);
}
# TERM信號處理例程
sub HandleTERM {
CleanUp ();
exit (0);
}
# 清理,主要工作是關(guān)閉文件句柄
sub CleanUp {
close (ATTACKLOG); close (MONITORLOG);
}

(二)FTP.pm FTP協(xié)議解碼模塊,抽取數(shù)據(jù)包里的FTP命令及相應(yīng)的參數(shù),此文件需要拷貝到NetPacket系列模塊所在的目錄,通常是在/usr/lib/perl5/site_perl/5.x.x/NetPacket/

復(fù)制代碼 代碼如下:

#
# NetPacket::FTP - Decode FTP packets
#
# Comments/suggestions to stardust at xfocus dot org
#
#
# $Id: FTP.pm,v 1.16 2004/03/03 l1:16:20 stardust Exp $
#
package NetPacket::FTP;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
use NetPacket;
my $myclass;
BEGIN {
$myclass = __PACKAGE__;
$VERSION = "0.01";
}
sub Version () { "$myclass v$VERSION" }
BEGIN {
@ISA = qw(Exporter NetPacket);
# Items to export into callers namespace by default
# (move infrequently used names to @EXPORT_OK below)
@EXPORT = qw(
);
# Other items we are prepared to export if requested
@EXPORT_OK = qw(
);
# Tags:
%EXPORT_TAGS = (
ALL => [@EXPORT, @EXPORT_OK],
);
}
#
# Decode the packet
#
# FTP協(xié)議文本參看RFC959,http://www.ietf.org/rfc/rfc0959.txt
# 常見的FTP命令
my @ftp_cmds = qw(ABOR ACCT ALLO APPE CDUP CWD DELE HELP LIST MKD MODE NLST
NOOP PASS PASV PORT PWD QUIT REIN REST RETR RMD RNFR RNTO
SITE SMNT STAT STOR STOU STRU SYST TYPE USER XCUP XCWD XMKD
XPWD XRMD LPRT LPSV ADAT AUTH CCC CONF ENC MIC PBSZ PROT
FEAT OPTS EPRT EPSV LANG MDTM MLSD MLST SIZE DIGT CLNT MACB
);
sub decode {
my $class = shift;
my($data) = @_;
my $self = {};
my $cmdhead = 0;
my $cmdtail = 0;
my @parts = ();
my $cmdcount = 0;
my $returnindex = 0;
my $data_len = length($data);
# 如果數(shù)據(jù)長度過短則不處理
if ($data_len >= 4) {
# 一個包里的FTP命令個數(shù)
$self->{cmdcount} = 0;
# 搜索回車,之前認(rèn)為是一個命令行,需要注意的是一個包里可能包含多個FTP命令
while ( (($returnindex = index ($data,"x0a",$cmdhead)) >=0)    (($returnindex < 0) && (($data_len - $cmdhead) >= 4))) {
# 調(diào)整一個命令行串尾指針
if ($returnindex < 0) {
$cmdtail = $data_len -1;
} else {
$cmdtail = $returnindex;
}
if ((my $cmdlen = ($cmdtail - $cmdhead + 1)) >= 4) {
# 取出命令行串
my $cmdline = substr($data,$cmdhead,$cmdlen);
# 從命令行里拆分出命令名和它的參數(shù)串
if (splitcmd($cmdline,@parts)) {
$self->{cmdcount}++;
my $cmdindex = "cmd"."$self->{cmdcount}";
my $paraindex = "para"."$self->{cmdcount}";
# 記錄到要返回到主程序的對象
$self->{$cmdindex} = $parts[0];
$self->{$paraindex} = $parts[1];
}
}
# 調(diào)整命令行串頭指針
$cmdhead = $cmdtail + 1;
}
# 如果命令個數(shù)大于0,則說明解碼是有效的
if ($self->{cmdcount} == 0) {
$self->{valid} = 0;
} else {
$self->{valid} = 1;
}
} else {
$self->{valid} = 0;
}
# 返回對象
bless($self, $class);
return $self;
}
sub splitcmd {
my ($cmdline,$parts) = @_;
# 去除行尾的回車
chomp($cmdline);
# 用正則表達式抽取出命令名字和參數(shù),既然效率不是考慮的主要問題就“毫無顧忌”地使用正則表達式,因為方便
if ($cmdline =~ m/^s*([a-zA-Z]{3,4})s+(.*)/) {
my $valid_cmd = 0;
# 檢查抽出來的命令名字是否是一個已知的合法FTP命令
for (my $i=0;$i<@ftp_cmds;$i++) {
if ($ftp_cmds[$i] eq uc($1)) {
$valid_cmd = 1;
last;
}
}
# 如果是合法的命令則返回給調(diào)用函數(shù)
if ($valid_cmd) {
${$parts}[0] = $1;
${$parts}[1] = $2;
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
#
# Module initialisation
#
1;
# autoloaded methods go after the END token (&& pod) below
__END__

(三)SMB.pm 對SMB包頭結(jié)構(gòu)的簡單解碼模塊,此文件需要拷貝到NetPacket系列模塊所在的目錄,通常是在/usr/lib/perl5/site_perl/5.x.x/NetPacket/

復(fù)制代碼 代碼如下:

#
# NetPacket::SMB - Decode SMB packets
#
# Comments/suggestions to stardust at xfocus dot org
#
#
# $Id: SMB.pm,v 1.16 2004/02/23 12:25:17 stardust Exp $
#
package NetPacket::SMB;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
use NetPacket;
my $myclass;
# SMB flags
use constant F2_LONGNAMEALLW => 0x0001;
use constant F2_EXTATTRIBUTE => 0x0002;
use constant F2_SECURITYSIGN => 0x0004;
use constant F2_LONGNAMEUSED => 0x0040;
use constant F2_EXTSECURINEG => 0x0800;
use constant F2_DONTRESOLDFS => 0x1000;
use constant F2_EXECONLYREAD => 0x2000;
use constant F2_ERRORCODTYPE => 0x4000;
use constant F2_UNICODSTRING => 0x8000;
use constant F_LOCKANDREAD => 0x01;
use constant F_RCVBUFFPOST => 0x02;
use constant F_CASESENSITV => 0x08;
use constant F_CANONICPATH => 0x10;
use constant F_OPLOCKSREQU => 0x20;
use constant F_NOTIFYONOPN => 0x40;
use constant F_REQUERESPON => 0x80;
BEGIN {
$myclass = __PACKAGE__;
$VERSION = "0.01";
}
sub Version () { "$myclass v$VERSION" }
BEGIN {
@ISA = qw(Exporter NetPacket);
# Items to export into callers namespace by default
# (move infrequently used names to @EXPORT_OK below)
@EXPORT = qw(F2_LONGNAMEALLW F2_EXTATTRIBUTE F2_SECURITYSIGN
F2_LONGNAMEUSED F2_EXTSECURINEG F2_DONTRESOLDFS
F2_EXECONLYREAD F2_ERRORCODTYPE F2_UNICODSTRING
F_LOCKANDREAD F_RCVBUFFPOST F_CASESENSITV
F_CANONICPATH F_OPLOCKSREQU F_NOTIFYONOPN
F_REQUERESPON
);
# Other items we are prepared to export if requested
@EXPORT_OK = qw(smb_strip
);
# Tags:
%EXPORT_TAGS = (
ALL => [@EXPORT, @EXPORT_OK],
strip => [qw(smb_strip)],
);
}
#
# Strip header from packet and return the data contained in it
#
undef &smb_strip;
*smb_strip = &strip;
# 剝除SMB頭的函數(shù)
sub strip {
my ($data) = @_;
my $smb_obj = NetPacket::SMB->decode($data);
return $smb_obj->{data};
}
#
# Decode the packet
#
sub decode {
my $class = shift;
my($data) = @_;
my $self = {};
my $data_len = 0;
my $temp = "";
$data_len = length ($data);
# 如果數(shù)據(jù)區(qū)長度小于39字節(jié)(4+32+3),則認(rèn)為不是一個可解碼的SMB包
if ($data_len < 39) {
$self->{valid} = 0;
} else {
# 取SMB的標(biāo)志串
my $smb_mark = substr ($data,4,4);
# 是否符合標(biāo)志串
if ($smb_mark ne "xffx53x4dx42") {
$self->{valid} = 0;
} else {
$self->{valid} = 1;
# Decode SMB packet
if (defined($data)) {
# 用PERL的unpack函數(shù)解碼32字節(jié)長的SMB頭結(jié)構(gòu),頭結(jié)構(gòu)可
# 參考 http://www.cs.uml.edu/~bill/cs592/cifs.chm
# 感謝小四(scz at nsfocus dot com)對于SMB頭結(jié)構(gòu)中字段字節(jié)序的提醒
($self->{nbt_type}, $self->{nbt_flag}, $self->{nbt_len},
$self->{mark}, $self->{cmd}, $self->{status},
$self->{flags}, $self->{flags2}, $self->{ext},
$self->{ext2}, $self->{ext3}, $self->{tid},
$self->{pid}, $self->{uid}, $self->{mid},
$self->{data}) = unpack("CCna4CVCvVVVvvvva*", $data);
($self->{wordcount},$temp) = unpack("Ca*",$self->{data});
if ((36 + 1 + $self->{wordcount} * 2) <= ($data_len - 2)) {
# 解碼SMB結(jié)構(gòu)下的wordcount字節(jié)及bytecount字節(jié)數(shù)據(jù)
my $wordbytes = $self->{wordcount} * 2;
($self->{wordcount},$self->{words},$self->{bytecount},$self->{bytes}) = unpack("C"."a"."$wordbytes"."va*",$self->{data});
} else {
($self->{wordcount},$self->{words}) = unpack("Ca*",$self->{data});
$self->{bytecount} = -1; $self->{bytes} = "";
}
}
}
}
# 返回對象
bless($self, $class);
return $self;
}
#
# Module initialisation
#
1;
# autoloaded methods go after the END token (&& pod) below
__END__

相關(guān)文章

  • Perl中chomp和chop的區(qū)別介紹

    Perl中chomp和chop的區(qū)別介紹

    chomp是用來刪除換行符,chop是用來刪除最后一個字符
    2013-02-02
  • perl的logwrapper使用實例代碼

    perl的logwrapper使用實例代碼

    perl的logwrapper可以對任何的函數(shù)將標(biāo)準(zhǔn)輸出和錯誤輸出重定向到對應(yīng)的log文件
    2013-02-02
  • Perl 哈希Hash用法之入門教程

    Perl 哈希Hash用法之入門教程

    本文和大家重點討論一下Perl Hash的用法,哈希是一種數(shù)據(jù)結(jié)構(gòu),和數(shù)組類似,但是,和數(shù)組不同的是,其索引不是數(shù)字,而是名字。也就是說,索引(這里,我們將它叫key)不是數(shù)字而是任意的唯一的字符串
    2013-02-02
  • perl數(shù)組的多數(shù)字下標(biāo)示例代碼

    perl數(shù)組的多數(shù)字下標(biāo)示例代碼

    perl數(shù)組中正常的下標(biāo)運算,想必大家都比較熟悉,這里不作說明。本文想說的是perl數(shù)組下標(biāo)的多數(shù)字取值,可以極大的方便數(shù)組的操作
    2013-02-02
  • Windows10下安裝配置 perl 環(huán)境的詳細(xì)教程

    Windows10下安裝配置 perl 環(huán)境的詳細(xì)教程

    Perl 最重要的特性是Perl內(nèi)部集成了正則表達式的功能,以及巨大的第三方代碼庫CPAN。這篇文章主要介紹了Windows10下安裝配置 perl 環(huán)境的詳細(xì)教程,需要的朋友可以參考下
    2020-12-12
  • perl Socket編程實例代碼

    perl Socket編程實例代碼

    Perl的networking 功能非常強大,基本上用c/c++能做的事perl都能做,而且做得更輕松方便,甚至可以只用10來行代碼就完成了c/c++要幾十上百甚至幾百行才能完成得好的工作
    2013-02-02
  • perl大文件讀取處理的模塊介紹

    perl大文件讀取處理的模塊介紹

    perl CPAN中有一個Tie-File 模塊極大方便了對大文件的操作
    2013-02-02
  • Perl List::Util模塊使用實例

    Perl List::Util模塊使用實例

    這篇文章主要介紹了Perl List::Util模塊使用實例,本文給出掃描符合條件的某個列表并取出第一個符合條件的、求1到1000之間的和 、求一組數(shù)字的最大值與最小值等實用功能代碼,需要的朋友可以參考下
    2015-06-06
  • 使用 use re debug 查看正則表達式的匹配過程

    使用 use re debug 查看正則表達式的匹配過程

    使用 use re 'debug' 查看正則表達式的匹配過程,參見如下的代碼
    2013-02-02
  • Perl哈希表用法解析

    Perl哈希表用法解析

    Perl語言有很多值得學(xué)習(xí)的地方,那么你對Perl哈希表的概念是否熟悉呢,這里和大家分享一下,希望本文的介紹能讓你有所收獲
    2013-02-02

最新評論