使用grep,awk或sed过滤nmap输出

时间:2013-11-26 15:22:44

标签: sed awk filtering nmap

我使用NMAP,我在大型网络上运行扫描以查看开放端口。输出文件是2MB,但我想过滤掉所有关闭端口的所有IP地址。

 
 Nmap scan report for 10.x.x.x
 Host is up (0.048s latency).
 Not shown: 998 closed ports
 PORT   STATE SERVICE
 22/tcp open  ssh
 23/tcp open  telnet

 Nmap scan report for 10.x.x.x
 Host is up (0.046s latency).
 All 1000 scanned ports on 10.x.x.x are closed

 Nmap scan report for 10.x.x.x
 Host is up (0.045s latency).
 All 1000 scanned ports on 10.x.x.x are closed

应输出到仅输出到:

 Nmap scan report for 10.x.x.x
 Host is up (0.048s latency).
 Not shown: 998 closed ports
 PORT   STATE SERVICE
 22/tcp open  ssh
 23/tcp open  telnet

修改

结果就像

 Nmap scan report for 10.x.x.x
 Host is up (0.048s latency).
 Not shown: 998 closed ports
 PORT   STATE SERVICE
 22/tcp open  ssh
 23/tcp open  telnet
 Nmap scan report for 10.x.x.x
 Host is up (0.046s latency).
 All 1000 scanned ports on 10.x.x.x are closed
 Nmap scan report for 10.x.x.x
 Host is up (0.045s latency).
 All 1000 scanned ports on 10.x.x.x are closed

有些新内容未正确复制

修改 感谢大家。我觉得awk很棒很容易做到。

3 个答案:

答案 0 :(得分:4)

正如我所看到的,你正在尝试对你的nmap输出应用一些智能过滤,而不仅仅是一个简单的“grep”。

由于您的nmap命令(根据您的注释而不是您的问题)指向子网而不是单个主机,因此您需要单独解释输出的每个部分。但这种解释对于正则表达来说太复杂了。 (PREG可能会成为可能,但是编写起来非常困难并且几乎不可能阅读。)像awk这样的工具是这项任务的更好选择。

例如:

nmap 10.10.0.0/16 | awk '
  /^Nmap scan report for/ {
    if (open) {
      print output;
    }
    output="";
    open=0;
  }

  {
    output=output $0 "\n";
  }

  $2 == "open" {
    open=1;
  }

  END {
    if (open) {
      print output;
    }
  }
'

awk很容易阅读,但你应该知道它的操作方法是将每行输入与看起来像condition { action }的表达式相匹配。如果条件的计算结果为true,则执行该操作。因此,第一个条件是一个正则表达式,用于查找主机节的开头,并且操作包含在花括号中。第二个条件缺失,因此假定所有行都是“真”。在处理完所有输入行之后,最后一个条件匹配,并且在扫描的最后一个主机包括开放端口时是必要的。

这种事情可以更密集地表达,但我已经写了很长时间,以便你可以更容易地看到逻辑如何工作。更严格的代码将伴随着练习。

请注意,您可以将awk脚本放入一个单独的文件中,您可以使用awk的-f选项进行引用。请阅读the man page了解详情。

如果您不想将awk部分保留在自己的文件中,也可以将整个内容放入自己的shell脚本中。你应该能够很容易地找到看起来很容易的例子 - 无论如何,它都超出了这个问题的范围。

答案 1 :(得分:1)

你可以尝试

awk -f filter.awk input.txt

其中input.txtnmap的输出,而filter.awk是:

/^Nmap/ {
    if (block)
        if (!match(block,/are closed/))
            print block
    block=$0
    next
}

{
    if (block)
        block=block RS $0
    else
        block=$0
}

答案 2 :(得分:0)

虽然看起来你有答案,但我会从Nmap方面解决这个问题。 Nmap有很多不同的output options,因此事先仔细规划可以使这类问题变得简单易行。

首先,如果您只希望主机具有开放端口,则可以使用--open运行扫描,这将隐藏所有已关闭和已过滤的端口以及没有开放端口的主机。这意味着您的输出将完全符合您的要求而无需过滤。缺点是你丢失了一些信息;有时候知道哪些主机存在很重要,即使他们没有服务也是如此。

接下来,Nmap有几种输出格式。正常输出(-oN)主要是您在屏幕上看到的内容。滚动浏览很好,但正如您所看到的,使用grep,sed,awk等进行文本处理或过滤非常糟糕。我发现最有用的输出选项是-oA,它可以保存3个不同的文件:a普通.nmap文件,“greppable”.gnmap文件,以及所有格式的母亲.xml文件。

Greppable format非常适合快速查询,例如“哪些IP端口22打开?”它每个主机有一行,带有严格的分隔符。缺点是不推荐使用:Nmap的任何新功能都不会集成到greppable格式中。以下列出了-oG中缺少的一些内容:NSE脚本输出,traceroute信息,多个主机名,端口状态原因,ttls。您可以使用greppable格式回答您的问题,如下所示:

grep '[0-9]/open' myscan.gnmap

XML output是最完整的格式,包括甚至不适合正常输出的信息。它也是XML,能够在命令行上进行处理。这是使用xmlstarlet的示例查询(尽管还有许多其他工具可以完成这项工作):

xmlstarlet sel -t -m "//host[ports/port/state/@state='open']" -v "address[@addrtype='ipv4']/@addr" -n myscan.xml