如何在 bash 或 awk 中逐字节读取十六进制转储?

如何在 bash 或 awk 中逐字节读取十六进制转储?

这是使用以下命令捕获的 IPv6 TCP 数据包的十六进制输出tcpdump

 6000 0000 0018 0620 0000 0000
 0000 0000 0000 0000 0000 0001 0000 0000
 0000 0000 0000 0000 0000 0002 *0026 0026
 0000 0001 0000 0002 {5}412 0065 0034 0000*
 6162 6364    

数据包本身位于*上面的 s 之间。表示{5}32 位字的数据包长度(因此它是 5 个字长 - 20 个字节)。我需要使用 bash/awk 脚本从此信息中提取 tcp 标头,因此脚本需要找到长度字节并使用它来知道还需要读取多少内容。我怎样才能在 bash 或 awk 中做到这一点?

答案1

这对于 Perl 或 Python 来说更像是一项工作,但您可以使用纯 bash 来完成。警告:未经测试。

ipv6_packet='6000 … 6364'
ipv6_packet=${ipv6_packet,,?}               # normalize hexadecimal digits to lowercase, just in case
ipv6_packet=${ipv6_packet//[!0-9a-f]/}      # remove whitespace and everything else that isn't a hex digit
tcp_packet=${ipv6_packet:80}                # all but the first 40 bytes (IPv6 header)
((tcp_data_offset=0x${tcp_packet:24:1}*4))  # data offset (25th nybble), converted from words to bytes
tcp_header=${tcp_packet:0:$tcp_data_offset} # that's the TCP header (still in hexdump form)

或者简称:

ipv6_packet=${ipv6_packet,,?}; ipv6_packet=${ipv6_packet//[!0-9a-f]/}
tcp_header=${ipv6_packet:80:$((0x${ipv6_packet:104:1}*4))}

相关内容