[Golang] packetbeat 二次开发-初探(一)

项目背景

目前需求新增支持协议获取。当前协议Kerberos

代码研究-初始化代码

新增协议只需要在这里进行新增即可。但是我们需要了解如何新增其中的代码逻辑方便我们后期进行移植。
packetbeat/protos

做个简单的~
先新建个Kerberos协议的文件

kerberos.go
初始化结构体

type kerberosPlugin struct {
     
	ports                     []int
	sendRequest               bool
	sendResponse              bool
	maxBodyLength             int
	parseHeaders              bool
	parseArguments            bool
	hideConnectionInformation bool
	transactions              *common.Cache
	transactionTimeout        time.Duration
	results                   protos.Reporter
}

初始化函数

func (krb *kerberosPlugin) init(results protos.Reporter, config *kerberosConfig) error {
     
	krb.setFromConfig(config)

	krb.results = results
	return nil
}

获取接口

// GetPorts lists the port numbers the kerberos protocol analyser will handle.
func (krb *kerberosPlugin) GetPorts() []int {
     
	return krb.ports
}

分析Kerberos流量

根据流量特征发现偏移4个byte最后一个byte是后面数据的byte数量从头开始分析

首先从头部Kerberos流量头部数据进行分析。第一个字节为标识请求类型

var HeaderTypes = map[byte]string {
     
	0x6a: "ASREQ",
	0x6b: "ASREP",
	0x6c: "TGSREQ",
	0x6d: "TGSREP",
	0x6e: "APERQ",
	0x6f: "APERP",
	0x74: "KRBSafe",
	0x75: "KRBPriv",
	0x76: "KRBCred",
	0x7e: "KRBError",
}

验证数据内容
开头第二个byte如果是0x81,说明后面取一个byte。如果是0x82,说明后面取两个byte利用大端的去相加两个byte。得出来的这个值是整个数据包不包含开头标识位的body长度。

// 基础头部数据转换
func FromBytes(data []byte) (kerberos, error) {
     
	var krbHeader kerberos
	var beacon uint8

	MsgType, err := CheckMap(data[0], HeaderTypes)
	if err == nil {
     
		return kerberos{
     }, fmt.Errorf("Data Error !!")
	}

	krbHeader.MsgType = MsgType

	if data[1] == 0x81 {
      //1 byte
		krbHeader.DataLength = uint16(data[2])
		beacon = 10
	} else if data[1] == 0x82 {
      //2 byte
		l := binary.BigEndian.Uint16(data[2:4])
		if l != uint16(len(data[4:])) {
     

			return kerberos{
     }, fmt.Errorf("Data Error !!")
		}
		krbHeader.DataLength = binary.BigEndian.Uint16(data[2:4])
		beacon = 12
	}
	if data[beacon] == 0x05 {
     
		krbHeader.PVNO = 0x05
	} else {
     
		return kerberos{
     }, fmt.Errorf("Data Error !!")
	}
	return krbHeader, nil
}

func CheckMap(data byte, m map[byte]string) (string, error) {
     
	v, ok := m[data]
	if ok != true {
     
		fmt.Printf("异常数据: %+v,", data)
		return "", fmt.Errorf("异常数据")
	}
	return v, nil
}

因为对应的结构体不同。我们在开头进行判断还需要推送到目标的转换代码中。

func (krb *kerberosPlugin) FromBytes(data []byte) ( error) {
     
	var krbHeader kerberos
	var beacon uint8

	MsgType, err := CheckMap(data[0], MsgTypes)
	if err != nil {
     
		return  fmt.Errorf("Data Error !! MsgType Error!!")
	}
	krbHeader.MsgType = MsgType

	if data[1] == 0x81 {
      //1 byte
		krbHeader.DataLength = uint16(data[2])
		beacon = 10
	} else if data[1] == 0x82 {
      //2 byte
		l := binary.BigEndian.Uint16(data[2:4])
		if l != uint16(len(data[4:])) {
     
			return  fmt.Errorf("Data Error !! DataLength Error!!")
		}
		krbHeader.DataLength = binary.BigEndian.Uint16(data[2:4])
		beacon = 12
	}
	if data[beacon] == 0x05 {
     
		krbHeader.PVNO = 0x05
	} else {
     
		return  fmt.Errorf("Data  Error !! beacon Error!!")
	}
	if krbHeader.MsgType == "ASREQ"{
     
		krb.toAsReq(fmt.Sprintf("%x",data))
	}else if krbHeader.MsgType == "ASREP" {
     
		krb.toAsRep(fmt.Sprintf("%x",data))
	}else if krbHeader.MsgType == "TGSREQ" {
     
		krb.toTgsReq(fmt.Sprintf("%x",data))
	}else if krbHeader.MsgType == "TGSREP" {
     
		krb.toTgsRep(fmt.Sprintf("%x",data))
	}else if krbHeader.MsgType == "APREQ" {
     
		krb.toApReq(fmt.Sprintf("%x",data))
	}else if krbHeader.MsgType == "APREP" {
     
		krb.toApRep(fmt.Sprintf("%x",data))
	}else if krbHeader.MsgType == "KRBSafe" {
     
		krb.toKRBSafe(fmt.Sprintf("%x",data))
	}else if krbHeader.MsgType == "KRBPriv" {
     
		krb.toKRBPriv(fmt.Sprintf("%x",data))
	}else if krbHeader.MsgType == "KRBCred" {
     
		krb.toKRBCred(fmt.Sprintf("%x",data))
	}else if krbHeader.MsgType == "KRBError" {
     
		krb.toKRBError(fmt.Sprintf("%x",data))
	}
	return  nil
}

转换代码

func  (krb *kerberosPlugin) toAsReq(s string)  {
     
	var a messages.ASReq
	b, err := hex.DecodeString(s)
	if err != nil {
     
		fmt.Println("Test vector read error: %v", err)
	}
	err = a.Unmarshal(b)
	if err != nil {
     
		fmt.Println("Unmarshal error: %v", err)
	}
	fmt.Printf("%+v",a)
	return
}

func (krb *kerberosPlugin) toAsRep(s string)  {
     
	var a messages.ASRep
	b, err := hex.DecodeString(s)
	if err != nil {
     
		fmt.Println("Test vector read error: %v", err)
	}
	err = a.Unmarshal(b)
	if err != nil {
     
		fmt.Println("Unmarshal error: %v", err)
	}
	fmt.Printf("%+v",a)
	return
}

因为我们这个代码目的是和HIDS结合。我们这里已经算是完成了协议解析的部分内容。然后我们就需要把读取数据的逻辑直接取出来,方便后面进行融合。

你可能感兴趣的:(golang,packetbeat,安全,安全,企业安全)