perl寫的一個端口掃描

#!/usr/bin/perl -w
use IO::Socket; #載如IO::Socket包
use threads;
use threads::shared;

my $thread_number: shared = 0;

#############################請求參數設置##################################
$timeout = 20; #超時值
$pause = 0;
$scan_mysqlver = 0; #是否掃mysql的版本,端口掃描的控制由-mysql參數控制
#############################請求參數設置##################################


###########################################################################
##     選擇工作模式     ##
###########################################################################
START_scanport:
## 初始化數據##
my @tasks = ();
$thread_number=0;
$timeout = 0.4;
###########
print "----------------------------------------------------------\n";
print "                端口掃描工具: 楓影:2510072*\n";
print "----------------------------------------------------------\n";
print "    [指定端口]  192.168.1.1 21,22,80,3389\n";
print "    [連續端口]  192.168.1.1 1-65535\n";
print "    [C段掃描]  192.168.1.1-255 80\n";
print "    [B段掃描]  192.168.1.1-192.168.255.255 80,3389\n";
print "    [-mysql]  192.168.1.1 3306 -mysql\n";
print "    [exit]  退出程序\n";
print "----------------------------------------------------------\n";
$choice = <STDIN>; #獲取從鍵盤輸入的字符
chomp $choice;
if ($choice =~ m/\s+/) { #檢測輸入的字符中是否有空格,沒有測斷爲出錯
 my ($host_ip,$port) = split (/\s+/, $choice);
 if ($choice =~ m/\-mysql/i) {
  $scan_mysqlver = 1;
 }else{
  $scan_mysqlver = 0;
 }
 if ($host_ip =~ m/\-/) { #IP段掃描
  my ($host_Fip,$host_Bip) = split (/\-/, $host_ip); #用-來分割IP,保存爲$host_Fip(前)和$host_Bip(後)
  if ($host_Bip =~ m/\./) { #B段掃描(192.168.1.1-192.168.255)
   #開始斷判IP是否合法及B段範圍
   if (check_ip($host_Fip) == 1 && check_ip($host_Bip) == 1){ #前面IP段合法,後IP段也合法
    $host_Fip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
    my $A1 = $1;
    my $A2 = $2;
    my $A3 = $3;
    my $A4 = $4;
    $host_Bip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
    if ($A1==$1 && $A2 == $2){
     my @ip_B=($A3 .. $3); #B段範圍
     my @ip_C=($A4 .. $4); #C段範圍
     if ($port =~ m/\-/) { #檢測端口類型是否連續
      my ($port_x,$port_y) = split (/\-/, $port); #將1-65535這種分割成1跟65535
      my @port_list = ($port_x .. $port_y);
      print "初始化任務中...\n";
      foreach my $ip_BD (@ip_B) { #B段IP
       foreach my $ip_CD (@ip_C) { #C段IP
        foreach my $po (@port_list) { #端口
         push(@tasks,"$A1.$A2.$ip_BD.$ip_CD $po"); #組成新的任務
        }
       }
      }
      print "初始化完成\n";

      for(0..10) {
       $trl[$_] = threads->create(\&connect_try,@tasks);
      }
      for(0..10) {
       $trl[$_]->join;
      }
     }else{#選擇性端口掃描
      my (@port_list) = split (/\,/, $port);
      print "初始化任務中...\n";
      foreach my $ip_BD (@ip_B) { #B段IP
       foreach my $ip_CD (@ip_C) { #C段IP
        foreach my $po (@port_list) { #端口
         push(@tasks,"$A1.$A2.$ip_BD.$ip_CD $po"); #組成新的任務
        }
       }
      }
      print "初始化完成\n";

      for(0..10) {
       $trl[$_] = threads->create(\&connect_try,@tasks);
      }
      for(0..10) {
       $trl[$_]->join;
      }
     }
    }else{
     print "IP輸入有誤!(只支持B段跟C段)請重新輸入\n";
     goto START_scanport;
    }

   }else{
    print "IP輸入有誤!請重新輸入\n";
    goto START_scanport;
   }
  }
  else
  { #C段掃描(192.168.1.1-255)
   #開始斷判IP是否合法及C段範圍
   if (check_ip($host_Fip) == 1 && $host_Bip>1 && $host_Bip<256){ #前面IP段合法,並且後面的地址小於256
    $host_Fip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
    my $host_d = "$1.$2.$3"; #取出IP段地址
    my $Xip = $4;
    my $Yip = $host_Bip;
    my @tasks;
    if ($port =~ m/\-/) { #檢測端口類型是否連續

     my ($port_x,$port_y) = split (/\-/, $port); #將1-65535這種分割成1跟65535
     my @port_list = ($port_x .. $port_y);
     print "初始化任務中...\n";
     foreach my $po (@port_list) {
      for (my $i=$Xip;$i<$Yip+1;$i++) {
       push(@tasks,"$host_d.$i $po");
      }
     }
     print "初始化完成\n";

     for(0..10) {
      $trl[$_] = threads->create(\&connect_try,@tasks);
     }
     for(0..10) {
      $trl[$_]->join;
     }
    }else{#選擇性端口掃描
     my (@port_list) = split (/\,/, $port);
     print "初始化任務中...\n";
     foreach my $po (@port_list) {
      for (my $i=$Xip;$i<$Yip+1;$i++) {
       push(@tasks,"$host_d.$i $po");
      }
     }
     print "初始化完成\n";

     for(0..10) {
      $trl[$_] = threads->create(\&connect_try,@tasks);
     }
     for(0..10) {
      $trl[$_]->join;
     }
    }
   }else{
    print "IP輸入有誤!請重新輸入\n";
    goto START_scanport;
   }
  }
 }
 else #單IP掃描
 { #檢測端口及IP是否合法
  if (check_ip($host_ip) == 1)
  { #IP合法,開始掃描
   if ($port =~ m/\-/) { #檢測端口類型是否連續
    my ($port_x,$port_y) = split (/\-/, $port); #將1-65535這種分割成1跟65535
    my @port_list=($port_x .. $port_y);
    print "初始化任務中...\n";
    foreach my $po (@port_list) {
     push(@tasks,"$host_ip $po");
    }
    print "初始化完成\n";
    for(0..10) {
     $trl[$_] = threads->create(\&connect_try,@tasks);
    }
    for(0..10) {
     $trl[$_]->join;
    }
   }else{ #選擇性端口掃描
    my @port_list = ();
    if ($port =~ m/\,/) { #檢測是否單端口
     @port_list= split (/\,/, $port);
    }else{
     push(@port_list,"$port");
    }

    print "初始化任務中...\n";
    foreach my $po (@port_list) {
     push(@tasks,"$host_ip $po");
    }
    print "初始化完成\n";

    for(0..10) {
     $trl[$_] = threads->create(\&connect_try,@tasks);
    }
    for(0..10) {
     $trl[$_]->join;
    }

   }

  }else{
   print "IP地址不合法!請重新輸入\n";
  goto START_scanport;} #返回到端口掃描界面
 }
 print ":)順利的完成所有任務!\n";
 goto START_scanport; #返回到端口掃描界面
}else{
 if ($choice eq 'exit') {
  print "選擇返回\n";
  exit; #跳到START_global
 }else{
  system('cls');
  print "輸入參數有誤!請重新輸入\n";
 goto START_scanport;} #返回到端口掃描界面
}


sub check_ip{
 my $intFlag = 0;
 if ($_[0] =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/){
  if($1>0 && $1<256 && $2>-1&& $2<256 && $3>-1 && $3<256 && $4>-1 && $4<256){
   $intFlag = 1;
  }
  else
  {
   $intFlag = 0;
  }
 }
}


sub connect_try{ #連接測試
 my (@task_list) = @_;
 $size = @task_list;
 $| = 1;
 
 while ($thread_number < $size){
  {lock($thread_number);
  $thread_number++;
  }
  
 
 my $task_li = $task_list[$thread_number-1];
 my ($host,$port) = split (/\s/, $task_li);

 my $sock = IO::Socket::INET->new(Proto=>'tcp',PeerAddr=>$host, PeerPort=>$port,Timeout=>$timeout);
 if($sock){
  if ($scan_mysqlver == 1){ #判斷是否掃mysql
   my $select = IO::Select->new( $sock );
   my @writes = $select->can_read(0.4);
   my $mysqlver = '';
   my $res = '';
   if( scalar( @writes ) > 0 ){
    print $sock "test\n"; #test coms and start a chat    
    $res= <$sock>;
    $res = $res . <$sock>;
    $res = $res . <$sock>;
    $res = $res . <$sock>;
    my $bds = "\n(.*?)\0" ;
    if ($res =~ m/$bds/img){
     print "$1\n";
    }
   }
  print $host." ".$port." 開放\n";
  }else{
   print $host." ".$port." 開放\n";
  }
  close $sock;
 }
 print $task_li . "\r";
 sleep $pause;
 }
}


發佈了38 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章