douyan1453 2018-07-30 12:28
浏览 54
已采纳

将自定义层添加到捕获的数据包失败

I am trying to implement my own decoding layer ontop of TCP, so far it only works when I create a packet without any Eth/IP/TCP header and set its layer to my custom layer manually. The data of the custom protocol is inside an ordinary TCP payload.

How do I decode only the payload of the TCP layer as another layer?

package main

import (
    "fmt"
    "github.com/google/gopacket"
    "github.com/google/gopacket/pcap"
)

var (
    pcapFile string = "capt.pcap"
    handle   *pcap.Handle
    err      error
)

type CustomLayer struct {
    SomeByte    byte
    AnotherByte byte
    restOfData  []byte
}

var CustomLayerType = gopacket.RegisterLayerType(
    2001,
    gopacket.LayerTypeMetadata{
        "CustomLayerType",
        gopacket.DecodeFunc(decodeCustomLayer),
    },
)

func (l CustomLayer) LayerType() gopacket.LayerType {
    return CustomLayerType
}

func (l CustomLayer) LayerContents() []byte {
    return []byte{l.SomeByte, l.AnotherByte}
}

func (l CustomLayer) LayerPayload() []byte {
    return l.restOfData
}

func decodeCustomLayer(data []byte, p gopacket.PacketBuilder) error {
    p.AddLayer(&CustomLayer{data[0], data[1], data[2:]})

    // nil means this is the last layer. No more decoding
    return nil
}

func main() {
    handle, err = pcap.OpenOffline(pcapFile)
    if err != nil {
        log.Fatal(err)
    }
    defer handle.Close()

    packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
    for packet := range packetSource.Packets() {
        tcpLayer := packet.Layer(layers.LayerTypeTCP)
        if tcpLayer != nil {
            fmt.Println("TCP layer detected.")
            tcp, _ := tcpLayer.(*layers.TCP)
            fmt.Println("Sequence number: ", tcp.Seq)
            customLayer := packet.Layer(CustomLayerType)
            if customLayer != nil { // always nil
                customLayerContent, _ := customLayer.(*CustomLayer)
                // Now we can access the elements of the custom struct
                fmt.Println("Payload: ", customLayerContent.LayerPayload())
                fmt.Println("SomeByte element:", customLayerContent.SomeByte)
                fmt.Println("AnotherByte element:", customLayerContent.AnotherByte)
            }
        }
        fmt.Println()
    }
}

Most of the code is from this great post by devdungeon.

  • 写回答

1条回答 默认 最新

  • dqn8235 2018-07-31 08:54
    关注

    As no one responded I am going to answer it myself now.

    Basically we have 3 options to handle this:

    1. Create an extended TCP layer that handles our additional bytes and override default one by setting layers.LinkTypeMetadata[layers.LinkTypeTCP] to our extended version. Have a look at this example.

    2. Create a new packet from the TCP payload using gopacket.NewPacket setting firstLayerDecoder to CustomLayerType and decode it normally.

    3. As you mostly don't need an actual layer but instead a filled CustomLayer struct simply write a DecodeBytesToCustomStruct function where you pass TCP payload. This way we can even return multiple structs from one packets payload which wouldn't be possible otherwise.

    Omit all CustomLayer code from above.

    type CustomStruct struct {
        SomeByte    byte
        AnotherByte byte
        restOfData  []byte
    }
    
    func (customStruct *CustomStruct) DecodeStructFromBytes(data []byte) error { 
        customStruct.SomeByte = data[0]
        customStruct.AnotherByte = data[1]
        customStruct.restOfData = data[2:]
        return nil
    }
    

    In your main.go

    for packet := range packetSource.Packets() {
        tcpLayer := packet.Layer(layers.LayerTypeTCP)
        if tcpLayer != nil {
            tcp, _ := tcpLayer.(*layers.TCP)
            if tcp.Payload != nil && len(tcpLayer.Payload) > 0 {
                customStruct := CustomStruct{}
                customStruct.DecodeStructFromBytes(tcp.Payload)
                fmt.Println("SomeByte element:", customStruct.SomeByte)
            }
        }
    }
    

    tcp.Payload is the same as packet.ApplicationLayer().Payload()

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥25 关于##爬虫##的问题,如何解决?:
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员
  • ¥15 matlab生成电测深三层曲线模型代码
  • ¥50 随机森林与房贷信用风险模型
  • ¥50 buildozer打包kivy app失败
  • ¥30 在vs2022里运行python代码
  • ¥15 不同尺寸货物如何寻找合适的包装箱型谱
  • ¥15 求解 yolo算法问题
  • ¥15 虚拟机打包apk出现错误