#!/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;
}
}