1
0

Add script artifact type

This commit is contained in:
dump_stack() 2023-03-22 20:56:44 +00:00
parent 5ece0e0f15
commit 105809ddec
Signed by: dump_stack
GPG Key ID: BE44DA8C062D87DC
6 changed files with 92 additions and 30 deletions

View File

@ -49,10 +49,12 @@ const (
KernelModule ArtifactType = iota KernelModule ArtifactType = iota
// KernelExploit is the privilege escalation exploit // KernelExploit is the privilege escalation exploit
KernelExploit KernelExploit
// Script for information gathering or automation
Script
) )
func (at ArtifactType) String() string { func (at ArtifactType) String() string {
return [...]string{"module", "exploit"}[at] return [...]string{"module", "exploit", "script"}[at]
} }
// UnmarshalTOML is for support github.com/naoina/toml // UnmarshalTOML is for support github.com/naoina/toml
@ -63,6 +65,8 @@ func (at *ArtifactType) UnmarshalTOML(data []byte) (err error) {
*at = KernelModule *at = KernelModule
} else if strings.Contains(stypelower, "exploit") { } else if strings.Contains(stypelower, "exploit") {
*at = KernelExploit *at = KernelExploit
} else if strings.Contains(stypelower, "script") {
*at = Script
} else { } else {
err = fmt.Errorf("Type %s is unsupported", stype) err = fmt.Errorf("Type %s is unsupported", stype)
} }
@ -77,6 +81,8 @@ func (at ArtifactType) MarshalTOML() (data []byte, err error) {
s = "module" s = "module"
case KernelExploit: case KernelExploit:
s = "exploit" s = "exploit"
case Script:
s = "script"
default: default:
err = fmt.Errorf("Cannot marshal %d", at) err = fmt.Errorf("Cannot marshal %d", at)
} }
@ -129,6 +135,8 @@ type Artifact struct {
SourcePath string SourcePath string
SupportedKernels []KernelMask SupportedKernels []KernelMask
Script string
Qemu struct { Qemu struct {
Cpus int Cpus int
Memory int Memory int

View File

@ -170,13 +170,21 @@ func (cmd *DebugCmd) Run(g *Globals) (err error) {
return return
} }
buildDir, outFile, output, err := build(tmp, ka, ki, g.Config.Docker.Timeout.Duration) var buildDir, outFile, output, remoteFile string
if ka.Type == config.Script {
err = q.CopyFile("root", ka.Script, ka.Script)
if err != nil {
return
}
} else {
buildDir, outFile, output, err = build(tmp, ka, ki, g.Config.Docker.Timeout.Duration)
if err != nil { if err != nil {
log.Print(err, output) log.Print(err, output)
return return
} }
remoteFile := "/tmp/exploit" remoteFile = "/tmp/exploit"
if ka.Type == config.KernelModule { if ka.Type == config.KernelModule {
remoteFile = "/tmp/module.ko" remoteFile = "/tmp/module.ko"
} }
@ -185,6 +193,7 @@ func (cmd *DebugCmd) Run(g *Globals) (err error) {
if err != nil { if err != nil {
return return
} }
}
// Copy all test files to the remote machine // Copy all test files to the remote machine
for _, f := range ka.TestFiles { for _, f := range ka.TestFiles {

View File

@ -0,0 +1,11 @@
# out-of-tree configuration file
# docs at https://out-of-tree.io
name = "out-of-tree script example"
type = "script"
script = "script.sh"
[[supported_kernels]]
distro_type = "Ubuntu"
distro_release = "22.04"
release_mask = ".*"

View File

@ -0,0 +1,3 @@
# out-of-tree script example
See .out-of-tree.toml

View File

@ -0,0 +1,5 @@
#!/bin/sh
uname -a
ls /proc | grep config

60
pew.go
View File

@ -266,6 +266,10 @@ func build(tmp string, ka config.Artifact, ki config.KernelInfo,
return return
} }
func runScript(q *qemu.System, script string) (output string, err error) {
return q.Command("root", script)
}
func testKernelModule(q *qemu.System, ka config.Artifact, func testKernelModule(q *qemu.System, ka config.Artifact,
test string) (output string, err error) { test string) (output string, err error) {
@ -300,12 +304,16 @@ func testKernelExploit(q *qemu.System, ka config.Artifact,
func genOkFail(name string, ok bool) (aurv aurora.Value) { func genOkFail(name string, ok bool) (aurv aurora.Value) {
state.Overall += 1 state.Overall += 1
s := " " + name
if name == "" {
s = ""
}
if ok { if ok {
state.Success += 1 state.Success += 1
s := " " + name + " SUCCESS " s += " SUCCESS "
aurv = aurora.BgGreen(aurora.Black(s)) aurv = aurora.BgGreen(aurora.Black(s))
} else { } else {
s := " " + name + " FAILURE " s += " FAILURE "
aurv = aurora.BgRed(aurora.White(aurora.Bold(s))) aurv = aurora.BgRed(aurora.White(aurora.Bold(s)))
} }
return return
@ -347,15 +355,19 @@ func dumpResult(q *qemu.System, ka config.Artifact, ki config.KernelInfo,
ki.DistroRelease, ki.KernelRelease) ki.DistroRelease, ki.KernelRelease)
colored := "" colored := ""
if ka.Type == config.KernelExploit { switch ka.Type {
case config.KernelExploit:
colored = aurora.Sprintf("[*] %40s: %s %s", distroInfo, colored = aurora.Sprintf("[*] %40s: %s %s", distroInfo,
genOkFail("BUILD", res.Build.Ok), genOkFail("BUILD", res.Build.Ok),
genOkFail("LPE", res.Test.Ok)) genOkFail("LPE", res.Test.Ok))
} else { case config.KernelModule:
colored = aurora.Sprintf("[*] %40s: %s %s %s", distroInfo, colored = aurora.Sprintf("[*] %40s: %s %s %s", distroInfo,
genOkFail("BUILD", res.Build.Ok), genOkFail("BUILD", res.Build.Ok),
genOkFail("INSMOD", res.Run.Ok), genOkFail("INSMOD", res.Run.Ok),
genOkFail("TEST", res.Test.Ok)) genOkFail("TEST", res.Test.Ok))
case config.Script:
colored = aurora.Sprintf("[*] %40s: %s", distroInfo,
genOkFail("", res.Test.Ok))
} }
additional := "" additional := ""
@ -398,6 +410,20 @@ func dumpResult(q *qemu.System, ka config.Artifact, ki config.KernelInfo,
func copyArtifactAndTest(slog zerolog.Logger, q *qemu.System, ka config.Artifact, func copyArtifactAndTest(slog zerolog.Logger, q *qemu.System, ka config.Artifact,
res *phasesResult, remoteTest string) (err error) { res *phasesResult, remoteTest string) (err error) {
// Copy all test files to the remote machine
for _, f := range ka.TestFiles {
if f.Local[0] != '/' {
if res.BuildDir != "" {
f.Local = res.BuildDir + "/" + f.Local
}
}
err = q.CopyFile(f.User, f.Local, f.Remote)
if err != nil {
slog.Error().Err(err).Msg("copy test file")
return
}
}
switch ka.Type { switch ka.Type {
case config.KernelModule: case config.KernelModule:
res.Run.Output, err = q.CopyAndInsmod(res.BuildArtifact) res.Run.Output, err = q.CopyAndInsmod(res.BuildArtifact)
@ -407,18 +433,6 @@ func copyArtifactAndTest(slog zerolog.Logger, q *qemu.System, ka config.Artifact
} }
res.Run.Ok = true res.Run.Ok = true
// Copy all test files to the remote machine
for _, f := range ka.TestFiles {
if f.Local[0] != '/' {
f.Local = res.BuildDir + "/" + f.Local
}
err = q.CopyFile(f.User, f.Local, f.Remote)
if err != nil {
slog.Error().Err(err).Msg("copy test file")
return
}
}
res.Test.Output, err = testKernelModule(q, ka, remoteTest) res.Test.Output, err = testKernelModule(q, ka, remoteTest)
if err != nil { if err != nil {
slog.Error().Err(err).Msg(res.Test.Output) slog.Error().Err(err).Msg(res.Test.Output)
@ -440,6 +454,15 @@ func copyArtifactAndTest(slog zerolog.Logger, q *qemu.System, ka config.Artifact
} }
res.Run.Ok = true // does not really used res.Run.Ok = true // does not really used
res.Test.Ok = true res.Test.Ok = true
case config.Script:
res.Test.Output, err = runScript(q, remoteTest)
if err != nil {
slog.Error().Err(err).Msg(res.Test.Output)
return
}
slog.Info().Msg(res.Test.Output)
res.Run.Ok = true
res.Test.Ok = true
default: default:
slog.Fatal().Msg("Unsupported artifact type") slog.Fatal().Msg("Unsupported artifact type")
} }
@ -568,7 +591,10 @@ func testArtifact(swg *sizedwaitgroup.SizedWaitGroup, ka config.Artifact,
result := phasesResult{} result := phasesResult{}
defer dumpResult(q, ka, ki, &result, dist, tag, binaryPath, db) defer dumpResult(q, ka, ki, &result, dist, tag, binaryPath, db)
if binaryPath == "" { if ka.Type == config.Script {
result.Build.Ok = true
testPath = ka.Script
} else if binaryPath == "" {
// TODO: build should return structure // TODO: build should return structure
start := time.Now() start := time.Now()
result.BuildDir, result.BuildArtifact, result.Build.Output, err = result.BuildDir, result.BuildArtifact, result.Build.Output, err =