Analisa o arquivo de saída do nmap para imprimir uma lista de IP com todas as portas abertas usando o awk

2

Eu gostaria de encontrar a lista de endereços IP com todas as portas abertas usando o comando awk .

Meu arquivo de saída do nmap é:

# Nmap 7.01 scan initiated Sat Mar 18 06:27:08 2017 as: nmap -oG output.txt -T4 -f -iL iplist.txt
Host: 10.0.0.99 ()    Status: Up
Host: 10.0.0.99 ()    Ports: 135/open/tcp//msrpc///, 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds///, 514/filtered/tcp//shell///, 554/open/tcp//rtsp///, 10243/open/tcp//unknown///    

Host: 192.168.0.1 ()    Status: Up
Host: 192.168.0.1 ()    Ports: 135/open/tcp//msrpc///, 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds///, 10243/open/tcp//unknown/// 

Host: 192.168.0.101 ()    Status: Up
Host: 192.168.0.101 ()    Status: Up
# Nmap done at Sat Mar 18 06:29:02 2017 -- 3 IP addresses (3 hosts up) scanned in 113.19 seconds

Resultado esperado:

10.0.0.99   135
10.0.0.99   139
10.0.0.99   445
10.0.0.99   514
10.0.0.99   554
10.0.0.99   10243
192.168.0.1 135
192.168.0.1 139
192.168.0.1 445 
192.168.0.1 10243

saída salva em outro arquivo (por exemplo, parse.txt)

    
por sknsk 18.03.2017 / 12:31

3 respostas

2

Você solicitou awk , mas isso é simples de fazer com o Perl, pois facilita a iteração em várias correspondências de uma expressão regular.

$ perl -ne '$host = $1 if /^Host: (\S+)/; while(m,(\d+)/open,g) 
    { print "$host\t$1\n" } ' < nmap.out 
10.0.0.99       135
10.0.0.99       139
...


perl -ne                       # Run the code for each input line
'$host = $1 if /^Host: (\S+)/  # If the line starts with "Host: ", 
                               # save the next non-whitespace string
while( m,(\d+)/open,g ) {      # Go through all matches of '<digits>/open'
                               # on the line, catching the digits
    print "$host\t$1\n"        # Print the saved hostname and the matched digits.
}'                              
    
por 18.03.2017 / 12:55
2

Uma abordagem do awk:

$ awk -F'[/ ]' '{h=$2; for(i=1;i<=NF;i++){if($i=="open"){print h,$(i-1)}}}' file 
10.0.0.99 135
10.0.0.99 139
10.0.0.99 445
10.0.0.99 554
10.0.0.99 10243
192.168.0.1 135
192.168.0.1 139
192.168.0.1 445
192.168.0.1 10243

O -F[/ ] define o separador do campo de entrada como / ou um espaço. Isso significa que o IP do host será $2 e tanto o número da porta quanto a palavra "aberto" estarão em seus próprios campos. Podemos, portanto, iterar todos os campos de uma linha ( for(i=1;i<=NF;i++){} ) e, se o campo atual for open , imprima o nome do host e o campo anterior (a porta): if($i=="open"){print h,$(i-1)} .

    
por 18.03.2017 / 14:28
0

I don't think I was able to put across my viewpoint clearly here. What I want to emphasize is that instead of having an explicit loop, we can piggyback on the regex m// to do the looping for us, below is the restructured regex for greater clarity:

perl -lne '
    /^
        Host: \s+ (\S+) \s+         # stuff $1 with hostname
        .+?:                        # seek the nearest colon :
        (?:                         # setup a loop
           \s+(\d+)\/open\/\S+      # this pattern should repeat
           (?{ print "$1\t$2" })    # print hostname+digits foreach turn
        )* # (?{ CODE }) does a code execution during regex search
    /x;
' yourfile
    
por 30.03.2017 / 12:47