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