AWK:从nmap输出中提取端口

问题描述

我编写了以下脚本,该脚本遍历了Nmap的输出,然后解析了分组为TCP / UDP的端口:

#!/bin/bash

TC=0;   #TCP Count
UC=0;   #UDP Count
if [ $# -eq 1 ];then

    cat $1 | gawk '/[0-9]+\/(tcp|udp)/{ match($1,/([0-9]+)\/(tcp|udp)/,arr); \
    if ( arr[2] == 'tcp') {
            if ( arr[1] in T == 0){         \   
    print "Insert ",arr[1]," to T"; \
    T[TC]=arr[1];
    TC++; 
            }   
    }   
    else if ( arr[2] == 'udp' && (arr[1] in U == 0)){       \   
    print "Insert "," to U"; 
    U[UC]=arr[1];
    UC++;
    }   
    }       
    END{
    print "U:"
    for (i in U){print U[i]}
    print "T:"
    for (j in T){print T[i]}
    }'  


    else
          echo 'nmap2ports <NMAP output File>'
    fi

awk中的 if条件语句永远不会对TCP和UDP都执行。 我只想尝试一下,如果端口是TCP(或UDP)并且不存在于TCP(或UDP)阵列中,则插入并在最后打印阵列。 因此,输出将类似于 [预期的输出]

U:
631
5353
17946
20031
T:
22
80

但是插入从未发生。 到目前为止,我已经尝试过:

if(!中的arr [1])

如果(arr [1]不在T中)

if(T中的arr [1] == 0)

样本输入文件

Nmap scan report for xx.xx.xx.xx                                                                                                                                                     
Host is up (0.47s latency).
Not shown: 1995 closed ports
PORT      STATE         SERVICE  VERSION
22/tcp    open          ssh      OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
80/tcp    open          http     Apache httpd 2.4.18 ((Ubuntu))
631/udp   open|filtered ipp
5353/udp  open|filtered zeroconf
17946/udp open|filtered unkNown
MAC Address: 00:50:56:87:9A:10 (VMware)
Aggressive OS guesses: Linux 3.12 (95%),Linux 3.13 (95%),Linux 3.16 (95%),Linux 3.2 - 4.9 (95%),Linux 4.4 (95%),Linux 4.8 (95%),Linux 4.9 (95%),Linux 3.18 (95%),Linux 3.8 - 3.11 (95%),Linux 4.2 (95%)
No exact OS matches for host (test conditions non-ideal).
Network distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Nmap scan report for xx.xx.xx.xx
Host is up (0.47s latency).
Not shown: 1996 closed ports
PORT      STATE         SERVICE         VERSION
80/tcp    open          http            Apache httpd 2.4.18 ((Ubuntu))
631/udp   open|filtered ipp
5353/udp  open|filtered zeroconf
20031/udp open|filtered bakbonenetvault
MAC Address: 00:50:56:87:E4:54 (VMware)
Aggressive OS guesses: Linux 3.13 (95%),Linux 4.2 (95%),ASUS RT-N56U WAP (Linux 3.4) (95%),Linux 3.12 (94%),Linux 3.8 - 3.11 (94%)
No exact OS matches for host (test conditions non-ideal).

[当前输出]

U:
T:

解决方法

请您尝试以下。

awk '
/^[0-9]+\/tcp/{
  sub(/\/.*/,"",$1)
  if(!tcpVal[$1]++){ a=""    }
}
/^[0-9]+\/udp/{
  sub(/\/.*/,$1)
  if(!udpVal[$1]++){ a=""    }
}
END{
  print "U:"
  for(i in udpVal) { print i }
  print "T:"
  for(j in tcpVal) { print j }
}' Input_file

说明: 添加以上详细说明。

awk '                             ##Starting awk program from here.
/^[0-9]+\/tcp/{                   ##Checking condition if line starts from digits then / and tcp then do following.
  sub(/\/.*/,$1)               ##Substituting from / till everything will NULL in 1st field.
  if(!tcpVal[$1]++){ a=""    }    ##Checking condition if $1 is NOT present in tcpVal array then place 
                                  ##it as an index in it and as a placeholder mentioning a to NULL.
}
/^[0-9]+\/udp/{                   ##Checking condition if line starts from digits / udp then do following.
  sub(/\/.*/,$1)               ##Substituting everything from / till last of line with NULL in $1.
  if(!udpVal[$1]++){ a=""    }    ##Checking condition if $1 is NOT present in udpVal array then place
                                  ##it as an index in it and as a placeholder mentioning a to NULL.
}
END{                              ##Starting END block of this specific awk program.
  print "U:"                      ##Printing U: here as per requested output.
  for(i in udpVal) { print i }    ##Traversing through array udpVal and printing index value(i).
  print "T:"                      ##Printing T: here as per requested output.
  for(j in tcpVal) { print j }    ##Traversing through array tcpVal and printing index value(i).
}' Input_file                     ##Mentioning Input_file name here.
,

以下经过重构和缩短的脚本也可能有效:

cat nmap.awk

match($1,/([0-9]+)\/(tcp|udp)/,arr) {
    !seen[arr[1],arr[2]]++ && ports[arr[2]][++n] = arr[1]
}       
END {
    print "U:"
    for (i in ports["udp"])
       print ports["udp"][i]

    print "T:"
    for (i in ports["tcp"])
       print ports["tcp"][i]
}

用作:

awk -f nmap.awk nmap.txt

U:
631
5353
17946
20031
T:
22
80