【问题标题】:Decode SNMP PDUs - Where to Start? [closed]解码 SNMP PDU - 从哪里开始? [关闭]
【发布时间】:2014-04-10 20:20:33
【问题描述】:

您好,我在这里的第一个问题,需要一些指导。

我正在开发一个数据包嗅探器,主要是为了解码 SNMP PDU,但是我不完全确定该去哪里。

简单地说,我的数据包嗅探器可以从数据包中提取信息,但是我对数据有效负载字段感兴趣。它是用 C++ 编写的,我使用的是 winsock。

我应该怎么做? SNMP 字段是否在基本编码规则中编码,还是我必须深入研究 ASN.1?

我只是希望将数据有效负载字段中的那些 SNMP 字段解码为人类可读的形式。它们将被转储到文本文件中。所以我也会考虑解码 OID。我在使用 Wireshark 并使用 GETIF 查询我的 SNMP 节点时验证所有内容。

感谢任何指导。

编辑:

感谢 user1793963 解释得很好。对所有将其标记为过于宽泛的人表示歉意。

为了详细说明我最初的问题,任何人都可以解释 PDU 本身的初始部分。

示例:我的程序输出这些十六进制值 30 82 00 A3 02 01 00,即 SEQUENCE (30)、LENGTH (82) 和其他两个值。这是来自 GetRequest PDU。

GetResponse PDU 显示这些值 30 81 B7 02 01 00, SEQUENCE, 81 in LENGTH 和另一个值。

谁能解释以粗体标记的值。如果它使用简单的 TLV 结构,代表什么值?我所知道的是序列的开始 (30) 和 PDU 总长度 (即 82 和 81),我知道 02 01 00 在 LENGTH 和 VERSION 0 中是 INTEGER 1 但是我不明白 00 A3 (GetRequest) 和 B7 (获取响应)。这些值代表什么? 非常感谢。

我也在使用 Wireshark 来检查值,但是它们没有说明 PDU 序列的开始

【问题讨论】:

  • 从开源项目开始,比如Wireshark本身,或者net-snmp,或者snmp++。
  • 问题已编辑;现在关心序列的开始。
  • 0x82 的最高位是 1,这意味着它应该与下一个字节组合形成一个大于 127 的数字。0x82 0x00 = 10000010 00000000。最重要的位被丢弃(它们不是值的一部分),所以你留下了100000000 = 256。之后发生的事情看起来有点奇怪,一个长度为 2 的 get 请求?如果字节顺序正确,请尝试检查 Wireshark。
  • 嗯,有道理,非常感谢。此外,A3 似乎没有任何意义,因为十六进制 02 01 00 实际上是版本。其他一切都井井有条; SEQUENCE 之后的那些第一个十六进制值是让我绊倒的原因;他们似乎格格不入?如果我忽略版本字段之前的所有内容,我可以解码消息。所以我不确定。 Wireshark 证实了这一点;一切都按正确的顺序排列。
  • 供参考:我发现十六进制值 82 00 是以下值 A3 的长度(82 = 十进制 130 - 128 (MSB) = 2,打印出 00 和 A3,所以以下字段长度为 163 字节)。很奇怪,在 SEQUENCE 或 PDU-Type 字段之后指定字段长度时,似乎创建消息的任何内容都遵循 TLV。

标签: decode snmp asn.1 ber


【解决方案1】:

SNMP 数据包在 ASN.1 中编码,但它是一个非常简单的协议(至少对于 SNMP v1 和 v2.c,我对 v3 没有太多经验)。它使用简单的 TLV 结构:类型、长度、值。例如,字节0x4 0x6 0x70 0x75 0x62 0x6c 0x63 是一个长度为 6 且值为“public”的字符串(类型 4)。你可以找到here的类型列表。

我发现写出这样的包很有用:

1.  0x30 0x34
2.    0x2 0x1 0x1
3.    0x4 0x6 0x70 0x75 0x62 0x6c 0x63
4.    0xa2 0x27
5.      0x2 0x4 0x1 0x2 0x3 0x4 
6.      0x2 0x1 0x0
7.      0x2 0x1 0x0
8.      0x30 0x19
9.        0x30 0x17
10.         0x6 0x8 0x2b 0x6 0x1 0x2 0x1 0x1 0x2 0x0
11.         0x6 0xb 0x2b 0x6 0x1 0x4 0x1 0x85 0x22 0xd5 0xf 0x97 0x54

这是对我请求 OID 1.3.6.1.2.1.1.2.0 (sysObjectID) 的 get 请求的响应。

  1. 一个长度为 52 字节的列表(类型 0x30)
  2. 版本:SNMPv2.c (0=v1, 1=v2.c)
  3. 社区字符串:“public”。 (注意这是如何以明文形式发送的)
  4. 长度为 39 的 SNMP 获取响应
  5. 请求 ID,一个 32 位整数。
  6. 错误码,0表示没有错误。
  7. 错误索引。
  8. 长度为 25 的列表
  9. 长度为 23 的列表
  10. 长度为 8 的 OID:1.3.6.1.2.1.1.2.0
  11. 长度为 11 的 OID:1.3.6.1.4.1.674.10895.3028

正如您所见,整数和字符串很容易,但 OID 有点棘手。首先,前两部分(“1.3”)表示为单个字节(0x2b)。他们这样做是为了使每条消息缩短几个字节。

第二个问题是表示大于 255 的数字。为此,SNMP 仅使用 7 个最低有效位来存储数据,最高有效位是一个标志,表示数据在下一个字节中继续。小于 128 的数字存储在单个字节中。

  0x7f
= 0 111 1111
= 127

  0x85 0x22
= 1 000 0101, 0 010 0010
=   000 0101    010 0010
= 674

  0xc0 0x80 0x80 0x80
= 1 100 0000, 1 000 0000, 1 000 0000, 0 000 0000
=   100 0000    000 0000    000 0000    000 0000
= 0x8000000

如果 TLV 字段的长度大于 127,也可以使用此方法。

RFC1592 描述了消息的结构,请查看第 11 页的类似示例。

我还可以推荐使用 Wireshark 来分析数据包,它在将它们转换为可读的东西方面做得非常好。

【讨论】:

    猜你喜欢
    • 2012-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 2010-12-25
    • 2010-09-30
    相关资源
    最近更新 更多