-
Notifications
You must be signed in to change notification settings - Fork 0
/
fuzzxml.go
167 lines (157 loc) · 4.18 KB
/
fuzzxml.go
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package main
import (
"bufio"
"bytes"
"encoding/hex"
"flag"
"fmt"
"math/rand"
"os"
"os/exec"
"path/filepath"
"sync"
"syscall"
"time"
"github.com/fatih/color"
)
/*
define variables for our xml fuzzer
*/
var (
xmlfuzzer = "/opt/xmlfuzzer/xmlfuzzer"
radamsa = "/usr/bin/radamsa"
prefix = "fuzz_"
suffix = ".xml"
xmlArgs = []string{"-xsd", "/opt/xmlfuzzer/OfficeOpenXML-XMLSchema/vml-main.xsd", "-root-elem", "document", "-max-elem", "10"}
radamsaArgs = []string{"--seed", "12"}
/* flags for command line */
directory = "./"
version = "1.0"
ver = flag.Bool("v", false, "Show Version.")
xmlfuzzerBinaryArg = flag.String("xf", "", "Use xmlfuzzer tool - this flag does not require a seed")
radamsaBinaryArg = flag.String("ra", "", "Use Radamsa fuzzer tool.")
seedArg = flag.String("seed", "", "pass seed for the fuzzer by default will use /root/work/seed/xml-seed.xml .")
)
/*
define usage function
*/
func usage() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
fmt.Fprintf(os.Stderr, "\tfuzzxml [-seed] path_to_seed.xml [-ra|-xf] binary_to_be_fuzzed\n")
fmt.Fprintf(os.Stderr, "Flags:\n")
flag.PrintDefaults()
}
/*
* check error and panic
*/
func printError(err error) {
if err != nil {
os.Stderr.WriteString(fmt.Sprintf("==> Error: %s\n", err.Error()))
}
}
/*
* print the output
*/
func printOutput(outs []byte) {
if len(outs) > 0 {
fmt.Printf("==> Output: %s\n", string(outs))
}
}
/*
* generate xml files from xmlfuzz
*/
func generateXMLMutations(cmd string, wg *sync.WaitGroup, xmlArgs []string) <-chan string {
stringChan := make(chan string)
go func() {
duration := 10 * time.Millisecond
time.Sleep(duration)
command := exec.Command(cmd, xmlArgs...)
var out bytes.Buffer
command.Stdout = &out
err := command.Run()
printError(err)
// generating random name for the file
randBytes := make([]byte, 16)
rand.Read(randBytes)
xmlDumpFile := filepath.Join(os.TempDir(), prefix+hex.EncodeToString(randBytes)+suffix)
fileHandle, err := os.Create(xmlDumpFile)
// print error if any
printError(err)
writer := bufio.NewWriter(fileHandle)
// close file handle
defer fileHandle.Close()
fmt.Fprintln(writer, out.String())
writer.Flush()
stringChan <- xmlDumpFile
close(stringChan)
wg.Done()
fmt.Println("Generating XML is successfully completed, Duration:", duration)
}()
return stringChan
}
/*
* Fuzz the actual binary with the output generated by executeCommand()
*/
func fuzzBinary(receivedXMLFile <-chan string, wg *sync.WaitGroup, binary string) {
go func() {
duration := 10 * time.Millisecond
time.Sleep(duration)
for xmlFile := range receivedXMLFile {
// initiate waitStatus for the syscall
var waitStatus syscall.WaitStatus
command := exec.Command(binary, xmlFile)
var out bytes.Buffer
command.Stdout = &out
// run the command
err := command.Run()
// print error if any
printError(err)
color.Yellow("Now fuzzing %s using %s as input", binary, xmlFile)
// check the status Exit codes, if crash happens it will exit and keep the file in /tmp
if exitError, ok := err.(*exec.ExitError); ok {
waitStatus = exitError.Sys().(syscall.WaitStatus)
printOutput([]byte(fmt.Sprintf("%d", waitStatus.ExitStatus())))
os.Exit(1)
} else {
// just relax and fuzzing will continue
color.Red("Relax nothing yet ...")
printOutput([]byte(fmt.Sprintf("%d", waitStatus.ExitStatus())))
defer os.Remove(xmlFile)
}
}
wg.Done()
}()
}
func main() {
// parse the flags for usage
flag.Parse()
flag.Usage = usage
var wg sync.WaitGroup
// print version if the flag -v is provided
if *ver {
fmt.Println(version)
os.Exit(1)
}
if *xmlfuzzerBinaryArg != "" {
for {
generatedXML := generateXMLMutations(xmlfuzzer, &wg, xmlArgs)
wg.Add(1)
fuzzBinary(generatedXML, &wg, *xmlfuzzerBinaryArg)
wg.Wait()
fmt.Println("Done")
}
} else if *radamsaBinaryArg != "" && *seedArg != "" {
seed := append(radamsaArgs, *seedArg)
for {
wg.Add(1)
generatedXML := generateXMLMutations(radamsa, &wg, seed)
wg.Add(1)
fuzzBinary(generatedXML, &wg, *radamsaBinaryArg)
wg.Wait()
fmt.Println("Done")
}
} else {
usage()
os.Exit(1)
}
}