aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/kd/kd.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/kd/kd.go')
-rw-r--r--pkg/kd/kd.go100
1 files changed, 100 insertions, 0 deletions
diff --git a/pkg/kd/kd.go b/pkg/kd/kd.go
new file mode 100644
index 000000000..e700d9762
--- /dev/null
+++ b/pkg/kd/kd.go
@@ -0,0 +1,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
+}