如何按“块”文本拆分解析的文本?

Posted

技术标签:

【中文标题】如何按“块”文本拆分解析的文本?【英文标题】:How can I split parsed text by "blocks" of text? 【发布时间】:2020-08-13 16:48:17 【问题描述】:

我正在编写一个运行 Nmap 网络扫描的 bash 脚本。在此之后,需要检查扫描并且需要提取相关位。

我需要从完成的扫描中提取 IP、MAC 和操作系统。问题是 Nmap 并不总是从扫描中获取操作系统,因此不会将其放入结果中。我需要在最终结果中关联 IP、MAC 和操作系统。

这是一个测试扫描的例子:

Nmap scan report for 192.168.0.1
Host is up (0.0029s latency).
Not shown: 990 closed ports
PORT      STATE SERVICE
PORT#    STATE    XXXXXXX
MAC Address: MA:CA:DR:ES:S0:03 (Unknown)
Device type: general purpose
Running: Linux 2.6.X|3.X
OS CPE: cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:3
OS details: Linux 2.6.32 - 3.13
Network Distance: 1 hop

Nmap scan report for 192.168.0.102
Host is up (0.0044s latency).
Not shown: 999 closed ports
PORT     STATE    SERVICE
PORT#    STATE    XXXXXXX
MAC Address: MA:CA:DR:ES:S0:02 (Sony Mobile Communications AB)
Too many fingerprints match this host to give specific OS details
Network Distance: 1 hop

Nmap scan report for 192.168.0.104
Host is up (0.00024s latency).
Not shown: 995 filtered ports
PORT     STATE SERVICE
PORT#    STATE XXXXXX
MAC Address: MA:CA:DR:ES:S0:01 (Micro-star Intl)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING): Microsoft Windows 2008 (91%)
OS CPE: cpe:/o:microsoft:windows_server_2008::sp1 cpe:/o:microsoft:windows_server_2008:r2
Aggressive OS guesses: Microsoft Windows Server 2008 SP1 or Windows Server 2008 R2 (91%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 1 hop

还要注意上面示例中的最后一个是如何找不到操作系统的,在这种情况下需要攻击性猜测

最终结果需要是一个文本文件,其内容如下:

192.168.0.1 - MA:CA:DR:ES:S0:03 - Linux 2.6.32 - 3.13
192.168.0.102 - MA:CA:DR:ES:S0:02 - Not found
192.168.0.104 - MA:CA:DR:ES:S0:01 - Microsoft Windows Server 2008 SP1 or Windows Server 2008 R2

我做了一些研究,但找不到任何解释我如何将 IP 与 mac 地址和文本块中的操作系统相关联的东西。

我有以下命令可用于简单扫描,其中 IP 和 Mac 地址彼此相邻

  while read line; do
    Mac="$(grep -oE '[A-Z0-9]2:[A-Z0-9]2:[A-Z0-9]2:[A-Z0-9]2:[A-Z0-9]2:[A-Z0-9]2' <<< "$line")"
    ip="$(grep -oE '[0-9]1,3\.[0-9]1,3\.[0-9]1,3\.[0-9]1,3' <<< "$line")"
    echo -e $ip'\t-\t '$Mac >>/path/to/results.txt
  done </path/to/testscan.txt

我对 bash 脚本相当陌生,如果我遗漏了一些明显的东西,我深表歉意。

任何有兴趣的人都可以使用 nmap 命令:

nmap -O --osscan-guess 192.168.0.0/24 -oN /path/to/testscan.txt

对不起,文字墙,我认为信息越多越好!

【问题讨论】:

如果您将您的 grep 解决方案与下面的 AWK 解决方案进行比较,您就会明白正则表达式不再适用于多行模式匹配。 【参考方案1】:

这很容易用awk解析:

BEGIN os_details="Not found"

/^Nmap scan report/      target=$5
/^MAC Address/           mac_address=$3
/^OS details/            os_details=substr($0, length("OS details: "))
/^Aggressive OS guesses/ 
    os_details=substr($0, length("Aggressive OS guesses: "))


# This matches the blank lines between hosts
/^$/ 
    printf "%s - %s - %s\n", target, mac_address, os_details
    target=""
    mac_address=""
    os_details="Not found"


END 
    printf "%s - %s - %s\n", target, mac_address, os_details

在您的示例数据上运行此程序可以得到:

192.168.0.1 - MA:CA:DR:ES:S0:03 -  Linux 2.6.32 - 3.13
192.168.0.102 - MA:CA:DR:ES:S0:02 - Not found
192.168.0.104 - MA:CA:DR:ES:S0:01 -  Microsoft Windows Server 2008 SP1 or Windows Server 2008 R2 (91%)

我必须纠正我认为您的示例数据中的错误...我在此处删除了 MAC Address 行之前的空白行:

Nmap scan report for 192.168.0.104
Host is up (0.00024s latency).
Not shown: 995 filtered ports
PORT     STATE SERVICE
PORT#    STATE XXXXXX

MAC Address: MA:CA:DR:ES:S0:01 (Micro-star Intl)

【讨论】:

已从输入中删除了不稳定的空白行。我完全同意你的观点,AWK 是解决这类问题的最佳工具。 空白行是一个错误。谢谢,我刚试过,它就像一个魅力。不知道 awk 有 BEGIN、END 块。以后会记住的!【参考方案2】:

使用nmap 的选项-oX(输出为XML 格式)解析可能更准确:

nmap -oX /path/to/testscan.xml ...
# or
nmap -oX - ... > /path/to/testscan.xml

然后您可以使用,例如,xmllint 通过 XPath 解析此 XML:

file="/path/to/testscan.xml"

get_details() 
    local file addr mac os
    file="$1"
    addr=$2
    mac=$(xmllint --xpath "string(//address[../address[@addr='$addr']][@addrtype='mac']/@addr)" "$file")
    os=$(xmllint --xpath "string(//os[../address[@addr='$addr']]/osmatch/@name)" "$file")
    : $mac:="No data"
    : $os:="No data"
    printf "%s - %s - %s\n" "$addr" "$mac" "$os"
   

for a in $(xmllint --xpath "//address[@addrtype='ipv4']/@addr" "$file" | grep -Po '\d+\.\d+\.\d+\.\d+'); do
    get_details "$file" $a
done

【讨论】:

以上是关于如何按“块”文本拆分解析的文本?的主要内容,如果未能解决你的问题,请参考以下文章

拆分:分解单块系统——《微服务设计》读书笔记

itextsharp:将文本块拆分为单词时单词被破坏

使用 Python 按行号将大文本文件拆分为较小的文本文件

在 Powershell 中,按记录类型拆分大型文本文件的最有效方法是啥?

为啥 hadoop 不能拆分一个大文本文件,然后使用 gzip 压缩拆分?

pandas 将excel中的一列文本数据拆分成多列 如何操作