diff --git a/debug.go b/debug.go index 051a2c1..9ffbf65 100644 --- a/debug.go +++ b/debug.go @@ -83,7 +83,7 @@ func interactive(q *qemu.QemuSystem) (err error) { } func debugHandler(kcfg config.KernelConfig, workPath, kernRegex, gdb string, - dockerTimeout time.Duration) (err error) { + dockerTimeout time.Duration, kaslr, smep, smap bool) (err error) { ka, err := config.ReadArtifactConfig(workPath + "/.out-of-tree.toml") if err != nil { @@ -104,6 +104,22 @@ func debugHandler(kcfg config.KernelConfig, workPath, kernRegex, gdb string, if err != nil { return } + + q.SetKASLR(kaslr) + q.SetSMEP(smep) + q.SetSMAP(smap) + + redgreen := func(name string, enabled bool) aurora.Value { + if enabled { + return aurora.BgGreen(aurora.Black(name)) + } + + return aurora.BgRed(aurora.Gray(aurora.Bold(name))) + } + + fmt.Printf("[*] %s %s %s\n", redgreen("KASLR", kaslr), + redgreen("SMEP", smep), redgreen("SMAP", smap)) + q.Debug(gdb) coloredGdbAddress := aurora.BgGreen(aurora.Black(gdb)) fmt.Printf("[*] gdb runned on %s\n", coloredGdbAddress) @@ -139,6 +155,9 @@ func debugHandler(kcfg config.KernelConfig, workPath, kernRegex, gdb string, coloredRemoteFile := aurora.BgGreen(aurora.Black(remoteFile)) fmt.Printf("[*] build result copied to %s\n", coloredRemoteFile) + fmt.Printf("\n%s\n", q.GetSshCommand()) + fmt.Printf("gdb -ex 'target remote %s'\n\n", gdb) + err = interactive(q) return } diff --git a/main.go b/main.go index e9065db..5239188 100644 --- a/main.go +++ b/main.go @@ -163,6 +163,10 @@ func main() { debugFlagGDB := debugCommand.Flag("gdb", "Set gdb listen address") debugGDB := debugFlagGDB.Default("tcp::1234").String() + kaslr := debugCommand.Flag("enable-kaslr", "Enable KASLR").Default("false").Bool() + nosmep := debugCommand.Flag("disable-smep", "Disable SMEP").Default("false").Bool() + nosmap := debugCommand.Flag("disable-smap", "Disable SMAP").Default("false").Bool() + bootstrapCommand := app.Command("bootstrap", "Create directories && download images") @@ -251,7 +255,7 @@ func main() { err = genConfig(config.KernelExploit) case debugCommand.FullCommand(): err = debugHandler(kcfg, *path, *debugKernel, *debugGDB, - *dockerTimeout) + *dockerTimeout, *kaslr, !*nosmep, !*nosmap) case bootstrapCommand.FullCommand(): err = bootstrapHandler() case logQueryCommand.FullCommand(): diff --git a/qemu/qemu-kernel.go b/qemu/qemu-kernel.go index 64e2397..82e3c04 100644 --- a/qemu/qemu-kernel.go +++ b/qemu/qemu-kernel.go @@ -71,6 +71,10 @@ type QemuSystem struct { debug bool gdb string // tcp::1234 + noKASLR bool + noSMEP bool + noSMAP bool + // Timeout works after Start invocation Timeout time.Duration KilledByTimeout bool @@ -181,17 +185,30 @@ func (q *QemuSystem) Start() (err error) { qemuArgs := []string{"-snapshot", "-nographic", "-hda", q.drivePath, "-kernel", q.kernel.KernelPath, - "-append", "root=/dev/sda ignore_loglevel console=ttyS0 rw", "-smp", fmt.Sprintf("%d", q.Cpus), "-m", fmt.Sprintf("%d", q.Memory), "-device", "e1000,netdev=n1", "-netdev", "user,id=n1," + hostfwd, } + cmdline := "root=/dev/sda ignore_loglevel console=ttyS0 rw" + if q.debug { qemuArgs = append(qemuArgs, "-gdb", q.gdb) } + if q.noKASLR { + cmdline += " nokaslr" + } + + if q.noSMEP { + cmdline += " nosmep" + } + + if q.noSMAP { + cmdline += " nosmap" + } + if q.kernel.InitrdPath != "" { qemuArgs = append(qemuArgs, "-initrd", q.kernel.InitrdPath) } @@ -204,6 +221,8 @@ func (q *QemuSystem) Start() (err error) { qemuArgs = append(qemuArgs, "-accel", "hvf", "-cpu", "host") } + qemuArgs = append(qemuArgs, "-append", cmdline) + q.cmd = exec.Command("qemu-system-"+string(q.arch), qemuArgs...) if q.pipe.stdin, err = q.cmd.StdinPipe(); err != nil { @@ -354,6 +373,21 @@ func (q *QemuSystem) Debug(conn string) { q.gdb = conn } +// SetKASLR is changing KASLR state through kernel boot args +func (q *QemuSystem) SetKASLR(state bool) { + q.noKASLR = !state +} + +// SetSMEP is changing SMEP state through kernel boot args +func (q *QemuSystem) SetSMEP(state bool) { + q.noSMEP = !state +} + +// SetSMAP is changing SMAP state through kernel boot args +func (q *QemuSystem) SetSMAP(state bool) { + q.noSMAP = !state +} + // GetSshCommand returns command for connect to qemu machine over ssh func (q QemuSystem) GetSshCommand() (cmd string) { addrPort := strings.Split(q.sshAddrPort, ":")