Awk:从 nmap 输出中提取端口

Awk: extracting ports from nmap output

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

的端口
#!/bin/bash

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

    cat  | gawk '/[0-9]+\/(tcp|udp)/{ match(,/([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 ",arr[1]," 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] in T)

if ( arr[1] not in T)

if ( arr[1] in T == 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 3.16 (95%), Linux 3.2 - 4.9 (95%), Linux 4.2 (95%), Linux 3.18 (95%), Linux 4.8 (95%), ASUS RT-N56U WAP (Linux 3.4) (95%), Linux 4.9 (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(/\/.*/,"",)
  if(!tcpVal[]++){ a=""    }
}
/^[0-9]+\/udp/{
  sub(/\/.*/,"",)
  if(!udpVal[]++){ 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(/\/.*/,"",)               ##Substituting from / till everything will NULL in 1st field.
  if(!tcpVal[]++){ a=""    }    ##Checking condition if  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(/\/.*/,"",)               ##Substituting everything from / till last of line with NULL in .
  if(!udpVal[]++){ a=""    }    ##Checking condition if  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(, /([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