github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/kd/kd.go (about)

     1  // Copyright 2017 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  // Minimal KD protocol decoder.
     5  // KD protocol is used by windows to talk to debuggers. Here are some links:
     6  // https://github.com/radare/radare2/issues/1246#issuecomment-135565901
     7  // http://articles.sysprogs.org/kdvmware/kdcom/
     8  // https://doxygen.reactos.org/df/de3/windbgkd_8h_source.html
     9  package kd
    10  
    11  import (
    12  	"bytes"
    13  	"fmt"
    14  	"unsafe"
    15  )
    16  
    17  var (
    18  	dataHeader = []byte{0x30, 0x30, 0x30, 0x30}
    19  )
    20  
    21  const (
    22  	typStateChange64 = 7
    23  )
    24  
    25  type packet struct {
    26  	header uint32
    27  	typ    uint16
    28  	size   uint16
    29  	id     uint32
    30  	csum   uint32
    31  }
    32  
    33  func Decode(data []byte) (start, size int, decoded []byte) {
    34  	if len(data) < len(dataHeader) {
    35  		return
    36  	}
    37  	start = bytes.Index(data, dataHeader)
    38  	if start == -1 {
    39  		start = len(data) - len(dataHeader) - 1
    40  		return
    41  	}
    42  	packetSize := int(unsafe.Sizeof(packet{}))
    43  	if len(data)-start < packetSize {
    44  		return // incomplete header
    45  	}
    46  	// Note: assuming little-endian machine.
    47  	pkt := (*packet)(unsafe.Pointer(&data[start]))
    48  	if len(data)-start < packetSize+int(pkt.size) {
    49  		return // incomplete data
    50  	}
    51  	size = packetSize + int(pkt.size) // skip whole packet
    52  	if pkt.typ == typStateChange64 {
    53  		if int(pkt.size) < int(unsafe.Sizeof(stateChange64{})) {
    54  			return
    55  		}
    56  		payload := (*stateChange64)(unsafe.Pointer(&data[start+packetSize]))
    57  		chance := "second"
    58  		if payload.exception.firstChance != 0 {
    59  			chance = "first"
    60  		}
    61  		decoded = []byte(fmt.Sprintf("\n\nBUG: %v chance exception 0x%x\n\n%#v\n\n",
    62  			chance, payload.exception.code, payload))
    63  	}
    64  	return
    65  }
    66  
    67  type stateChange64 struct {
    68  	state          uint32
    69  	processorLevel uint16
    70  	processor      uint16
    71  	numProcessors  uint32
    72  	thread         uint64
    73  	pc             uint64
    74  	exception      exception64
    75  	report         controlReport
    76  }
    77  
    78  type exception64 struct {
    79  	code        uint32
    80  	flags       uint32
    81  	record      uint64
    82  	address     uint64
    83  	numParams   uint32
    84  	unused      uint32
    85  	params      [15]uint64
    86  	firstChance uint32
    87  }
    88  
    89  type controlReport struct {
    90  	dr6         uint64
    91  	dr7         uint64
    92  	eflags      uint32
    93  	numInstr    uint16
    94  	reportFlags uint16
    95  	instr       [16]byte
    96  	cs          uint16
    97  	ds          uint16
    98  	es          uint16
    99  	fs          uint16
   100  }