【问题标题】:Parsing nmap output解析 nmap 输出
【发布时间】:2019-01-22 17:32:10
【问题描述】:

我正在做的一个熟悉自己的项目是解析 nmap 结果。

(我知道-oG 选项,但我正在使用grepawkforwhile 循环)。

以下是我要解析的内容:

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 $3 }' | sort | uniq

对于我的生活,我无法弄清楚如何将它变成一个循环并从上面获得所需的输出。

能否请您帮助我了解并解释您为什么会找到您所做的解决方案?如果我无法理解其背后的逻辑,那么获得潜在的解决方案毫无意义。

【问题讨论】:

  • 您当前收到的输出是什么?
  • 目前,这是我得到的域 http microsoft-ds netbios-ssn ssh svrloc
  • 您将不得不更全面/清楚地描述您的需求,因为有多种方法可以从该输入中获取输出,但我怀疑其中只有一种是您真正想要做的。
  • 为什么不显示其他 tcp.*open 匹配项,在哪里只过滤 ssh 或 22?
  • edit 您的问题包含所有相关信息,请勿将其分散到可能遗漏的 cmets 中。一些不清楚的事情,例如 - 为什么每个服务类型只使用 ssh 而不是单独的列表?如果一个IP只有http怎么办?为什么只有端口 22 而不是每个端口和服务的列表。等等等等……

标签: bash parsing awk grep nmap


【解决方案1】:

最好使用通用编程语言(python、perl、awk)为您提供服务,您可以在看到“扫描报告”关键字时捕获 IP 地址,然后维护映射服务名称的数据结构到运行这些服务的 IP 地址列表。

例如,给定输出,这个 perl 单行(提供没有解释)

perl -ne '
    if (/Nmap scan report for .*?(\d+\.\d+\.\d+\.\d+)/) {
        $ip = $1
    }
    elsif (/^(\d+)\/tcp\s+open\s+(.*)/) {
        push @{$services{"$1/$2"}}, $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

【讨论】:

  • 非常感谢!我很感激。如果我学习 perl,我至少可以在 *nix 系统中调用它。我从没想过要使用 perl。干杯!
【解决方案2】:
$ cat tst.awk
BEGIN { FS="[[:space:]/]+" }

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

/tcp.*open/ {
    key = $1 "/" $4
    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 手册页后有任何问题,请随时提问。

以上内容可以在每个 UNIX 系统上的任何 shell 中使用任何 awk。

【讨论】:

  • 我阅读了手册页。必须承认,似乎 awk 将成为我的首选。它似乎比 perl 更具可读性(用于重新访问代码)。但是,如果我错了,请纠正我,因为我将尝试解释您的建议在做什么。 1. 在从要读取的文件中获取输入之前,使用 awk 的 BEGIN 和 END 部分进行评估/格式化。 2. 从 IP 周围删除 () 并将其替换为空,并将其设置为 IP 变量。 3. 查找“tcp.*open”正则表达式并将“密钥”格式化为数字/服务。 4. 遍历每个部分,如果匹配则打印出来
  • 您不会对 perl 语法有这种感觉(请参阅zoitz.com/comics/perl_small.png)。 awk 也是所有 UNIX 系统的标准配置,perl 没有。是的,就是这样,除了需要明确的是,BEGIN 在打开任何输入文件之前执行,END 在读取所有输入文件之后执行。两者之间的内容在隐式while read 循环中执行,该循环一次读取每一行并填充ips[] 数组,以便我们可以循环它在END 部分中的索引并打印相关内容(每个端口/服务对的 IP 地址)
猜你喜欢
  • 1970-01-01
  • 2015-09-15
  • 2016-07-15
  • 1970-01-01
  • 1970-01-01
  • 2020-04-29
  • 2021-02-23
  • 2020-12-17
  • 2014-10-19
相关资源
最近更新 更多