正在尝试解构此tcpdump bpf样式的筛选器,需要一些帮助:
'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
它取自here
为更好地了解正在发生的事情而采取的步骤:
1. Lets convert the 0x47455420 to ascii
===> GET
===> tcp[((tcp[12:1] & 0xf0) >> 2):4] = GET
2. Examine the inner tcp filter: (tcp[12:1] & 0xf0)
===> the 0xf0 == 0000 0000 1111 0000 ===> I suppose it is save to discard the upper zeros so I can write 1111 0000
===> tcp[12:1] == 08 (start filtering from byte 13 (0 based indexing, so you could also say start with the byte that has index 12) for 1 byte, so only 13th byte);
===> 08 == 0000 1000
===> 0000 1000 & 1111 0000 == 0000 (bitwise and = if both are 1 then end result is one)
这就是我困惑的地方。我在上面提供的超链接中的解释是
multiply it by four ( (tcp[12:1] & 0xf0)>>2 ) which should give the tcp header length
如果是零就不可能了。拜托:
帮我找出计算中的错误(也许我在混合TCP和IP头?);
为我的逻辑是否正确提供一些指导。
这是数据包:
19:10:30.091065 IP (tos 0x0, ttl 63, id 40127, offset 0, flags [DF], proto TCP (6), length 2786)
10.240.35.81.47856 > 172.17.13.201.8080: Flags [P.], cksum 0xf2ef (incorrect -> 0xb8f8), seq 2263020471:2263023205, ack 4187927811, win 28, options [nop,nop,TS val 1906863883 ecr 214445688], length 2734
0x0000: 1a17 8e8a a3a0 026d 627d 049c 0800 4500 .......mb}....E.
0,1 2,3 ... ... ... ... 12,13 ... <=== byte indexes
1,2 3,4 ... ... ... ... 13,14 ... <=== counting how many bytes
0x0010: 0ae2 9cbf 4000 3f06 ac3b 0af0 2351 ac11 ....@.?..;..#Q.. <=== 0x0010 number correctly identifies that the first two diggits are the 16th byte
16,17 ... ...
0x0020: 0dc9 baf0 1f90 86e2 f3b7 f99e b503 8018 ................
0x0030: 001c f2ef 0000 0101 080a 71a8 6f0b 0cc8 ..........q.o...
0x0040: 2e78 4745 5420 2f69 636f 6e73 2f75 6e6b .xGET./icons/unk
0x0050: 6e6f 776e 2e67 6966 2048 5454 502f 312e nown.gif.HTTP/1.
0x0060: 310d 0a68 6f73 743a 2070 6870 2d6d 696e 1..host:.php-min
最佳答案
tcp[12:1]
是从TCP头开始的偏移量为12字节的字节;12不是从数据包开始的偏移量,而是从TCP头开始的偏移量(它是tcp[12:1]
、不是ether[12:1]
或类似的东西)。“1”是所引用的字节数。
根据TCP的规范RFC 793,从the TCP header开始的偏移量为12字节的字节包含上4位中的数据偏移量,下4位是保留位。数据偏移量是“TCP报头中32位字的数目”,它“指示数据的起始位置”。
数据包中的数据显示为一个字节对序列。如果表示为单个字节的序列,则更容易理解,因此:
0x0000: 1a 17 8e 8a a3 a0 02 6d 62 7d 04 9c 08 00 45 00
eth dest eth src etype IP hdr
数据包的前6个字节是以太网目标地址。
接下来的6个字节是以太网源地址。
后面的2个字节是以太网类型值;它是big-endian,所以它的值是0x0800,它是IPv4的以太网类型值。
接下来的2个字节是IPv4头的前2个字节。根据IPv4的规范RFC 791,the IPv4 header的第一个字节包含IP版本在上4位,头长度在下4位。该字节的值为0x45,因此IP版本为4(对于IPv4,应该是4),头长度为5。头的长度“是32位字的互联网头的长度”,所以是5个32位字,或者20个字节。
所以,现在,让我们跳过IPv4头并转到TCP头:
0x0020: 0d c9 ba f0 1f 90 86 e2 f3 b7 f9 9e b5 03 80 18
TCP header 12 13
所以TCP头的字节12是0x80。0x80&0xf0为0x80,0x80>>2为0x20,即32;这与该字节的高位4位一致,即32位字中的数据偏移量,即8*4=32。
因此,对于此数据包,
tcp[((tcp[12:1] & 0xf0) >> 2):4]
,即从TCP头开始偏移32的4个字节。从TCP头开始的32字节是:
0x0040: 2e78 4745 5420 2f69 636f 6e73 2f75 6e6b
^
这里是HTTP请求的“get”头,从TCP段数据的开头开始。有问题的te 4字节是“get”。
因此,
tcp[32:4]
中的12不是从数据包开始的偏移量,而是从TCP头开始的偏移量(它是tcp[12:1]
,而不是tcp[12:1]
或类似的东西)。在回答有关数据包字节和字节是什么的问题时:
0x0000: 1a 17 8e 8a a3 a0: Ethernet destination
02 6d 62 7d 04 9c: Ethernet source
08 00: Ethernet type/length field - 0x0800 = IPv4
所以包的前14(0x000e)字节是以太网头。
在这个数据包中,ethernet type/length字段是0x0800,因此ethernet头后面的ethernet负载是一个以ipv4头开头的ipv4数据包:
45: IPv4 version/header length
00: IPv4 Type of Service/Differentiated Service
0x0010: 0a e2: IPv4 total length
9c bf: IPv4 identification
40 00: IPv4 flags/fragment offset
3f: IPv4 time-to-live
06: IPv4 (next) protocol - 6 = TCP
ac 3b: IPv4 header checksum
0a f0 23 51: IPv4 source address
ac 11: first 2 bytes of IPv4 destination address
0x0020: 0d c9: second 2 bytes of IPv4 destination address
IPv4头长度为5,因此IPv4头为20字节。这是ipv4头的最小长度;它不能更小,但可以更大,如果在头的固定长度部分之后有ipv4选项的话。在这种情况下没有。
由于“协议”字段的值为6,因此IPv4负载是一个TCP数据包:
ba f0: TCP source port (47856)
1f 90: TCP destination port (8080)
86 e2 f3 b7: TCP sequence number
f9 9e b5 03: TCP acknowledgment number
80: TCP data offset + reserved bits
18: reserved bits + TCP flags
0x0030: 00 1c: TCP window
f2 ef: TCP checksum
00 00: TCP urgent pointer
这是TCP头的20字节固定长度部分;但是,TCP头的长度是32字节,因此头中还有12个字节的TCP选项:
01: TCP No-Operation option
01: TCP No-Operation option
08 0a 71 a8 6f 0b 0c c8: first 8 bytes of TCP Timestamp option
0x0040: 2e 78: last 2 bytes of TCP Timestamp option
TCP头的长度必须是32位的倍数,即4字节的倍数;TCP选项的长度不能是4字节的倍数-TCP时间戳选项的长度为10字节-因此无操作选项用于填充。
所以这32个字节是TCP头;接下来是TCP有效负载。显然,这是在http连接上(数据包被发送到端口8080,这是一个备用http端口),这是http get请求的开始:
47 45 54 20 2f 69 63 6f 6e 73 2f 75 6e 6b
0x0050: 6e 6f 77 6e 2e 67 69 66 20 48 54 54 50 2f 31 2e
0x0060: 31 0d 0a 68 6f 73 74 3a 20 70 68 70 2d 6d 69 6e
所以:
由于这是在未处于监控模式的以太网或Wi-Fi网络上捕获的(或在使用以太网头或适配器或驱动程序提供“假以太网”头的其他类型网络上,如Wi-Fi),数据包将从以太网头开始;
由于以太网类型值为0x0800,后面跟着一个IPv4头;
由于ipv4协议值是6,它后面跟着一个tcp报头;
由于其中一个TCP端口号是HTTP(8080)通常使用的端口号,它后面可能紧跟着某种类型的HTTP数据(但这并不能保证——TCP端口号更像是提示)。
对于同一个网络上的arp,您将再次有一个以太网报头(这个
ether[12:1]
是以太网广播地址,所以包正在广播,就像arp请求通常是那样),以太网类型是0x0806,这是arp的以太网类型值。对于同一网络上的ICMP,您将再次拥有一个以太网头,并且您还将拥有一个IPv4头,因此以太网类型将为0x0800。对于icmp,ipv4头中protocol字段的值将为1。
关于networking - 在TCPdump中解构BPF过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28392766/