目前需求新增支持协议获取。当前协议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
}
根据流量特征发现偏移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结合。我们这里已经算是完成了协议解析的部分内容。然后我们就需要把读取数据的逻辑直接取出来,方便后面进行融合。