mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-30 14:50:36 +00:00
8136bdad2f
Very primitive decoder that only decodes amd64 exceptions. Use it in vm/gce. Now crashes contain something more or less reasonable which is caught by manager as crash: BUG: first chance exception 0x80000003 &kd.stateChange64{state:0x3030, processorLevel:0x6, processor:0x0, numProcessors:0x2, thread:0xffff9c0bd015e080, pc:0xfffff8017615c380, exception:kd.exception64{code:0x80000003, flags:0x0, record:0x0, address:0xfffff8017615c380, numParams:0x1, unused:0x0, params:[15]uint64{ 0x0, 0x40, 0xfffff801768699e0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, firstChance:0x1}, report:kd.controlReport{ dr6:0xffff0ff0, dr7:0x400, eflags:0x86, numInstr:0x10, reportFlags:0x3, instr:[16]uint8{0xcc, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf, 0x1f, 0x84, 0x0, 0x0, 0x0, 0x0, 0x0}, cs:0x10, ds:0x2b, es:0x2b, fs:0x53}}
101 lines
2.2 KiB
Go
101 lines
2.2 KiB
Go
// 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
|
|
}
|