Парсинг вывод Nmap

проект для ознакомления, над которым я работаю, - это разбор через nmap результат.

(Я знаю, о -oG вариант, но я работаю с grep, awk, for и while петли здесь).

ниже то, что я пытаюсь разобрать:

Starting Nmap 7.60 ( https://nmap.org ) at 2017-12-05 11:26 EST
Nmap scan report for house.router.nick (192.168.1.1)


Host is up (0.00059s latency).
Not shown: 995 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
53/tcp   open  domain
427/tcp  open  svrloc
1900/tcp open  upnp

MAC Address: 50:C7:BF:A8:CF:C8 (Tp-link Technologies)


Nmap scan report for 192.168.1.2


Host is up (0.00034s latency).
Not shown: 996 closed ports
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
139/tcp   open  netbios-ssn
445/tcp   open  microsoft-ds

MAC Address: 48:F8:B3:C9:AE:BB (Cisco-Linksys)

то, что я хочу сделать это:

22/ssh
====
192.168.1.1
192.168.1.2

http
===
192.168.1.2

пока у меня есть это:

grep -E "tcp.*open" nmap.txt | awk '{ print  }' | sort | uniq

для жизни меня, я не могу понять, как получить это в петлю сортирует и получает желаемый результат сверху.

не могли бы вы помочь мне узнать и объяснить, почему вы пришли к решению, которое вы сделали? Нет смысла в получении потенциального решения, если я не могу понять логику этого.

2 ответов


вам лучше использовать язык программирования общего назначения (python, perl, awk), где вы можете захватить IP-адрес, когда увидите ключевые слова "отчет сканирования", а затем поддерживать структуру данных, отображающую имена служб в список IP-адресов, на которых работают эти службы.

например, учитывая этот вывод, этот Perl one-liner (предлагается без объяснения причин)

perl -ne '
    if (/Nmap scan report for .*?(\d+\.\d+\.\d+\.\d+)/) {
        $ip = 
    }
    elsif (/^(\d+)\/tcp\s+open\s+(.*)/) {
        push @{$services{"/"}}, $ip
    }
    END {
        for $svc (sort {$a <=> $b} keys %services) {
            printf "%s\n%s\n\n", $svc, join("\n", @{$services{$svc}})
        }
    }
'

производит

22/ssh
192.168.1.1
192.168.1.2

53/domain
192.168.1.1

80/http
192.168.1.2

139/netbios-ssn
192.168.1.2

427/svrloc
192.168.1.1

445/microsoft-ds
192.168.1.2

1900/upnp
192.168.1.1

$ cat tst.awk
BEGIN { FS="[[:space:]/]+" }

/Nmap scan report/ {
    ip = $NF
    gsub(/[()]/,"",ip)
}

/tcp.*open/ {
    key =  "/" 
    ips[key] = (key in ips ? ips[key] ORS : "") ip
}

END {
    for (key in ips) {
        print key
        print "===="
        print ips[key]
        print ""
    }
}

.

$ awk -f tst.awk file
80/http
====
192.168.1.2

1900/upnp
====
192.168.1.1

427/svrloc
====
192.168.1.1

445/microsoft-ds
====
192.168.1.2

53/domain
====
192.168.1.1

22/ssh
====
192.168.1.1
192.168.1.2

139/netbios-ssn
====
192.168.1.2

Я думаю, что это очень очевидно, что он делает, но если у вас есть какие-либо вопросы, возможно, после нескольких взглядов на страницу awk man, тогда не стесняйтесь спрашивать.

выше будет работать с использованием любого awk в любой оболочке в каждой системе UNIX.