Skip to content

Commit

Permalink
feat: work with []byte instead of strings
Browse files Browse the repository at this point in the history
  • Loading branch information
NSEcho committed Sep 14, 2023
1 parent b1c7246 commit 7434fa3
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 79 deletions.
12 changes: 6 additions & 6 deletions cmd/fuzz.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var fuzzCmd = &cobra.Command{
Use: "fuzz",
Short: "Fuzz URL scheme",
RunE: func(cmd *cobra.Command, args []string) error {
var validInputs []string
var validInputs [][]byte
var err error

base, err := cmd.Flags().GetString("base")
Expand Down Expand Up @@ -102,7 +102,7 @@ var fuzzCmd = &cobra.Command{

l.Infof("Attached to %s", app)

var lastInput string
var lastInput []byte

sess.On("detached", func(reason frida.SessionDetachReason, crash *frida.Crash) {
l.Infof("Session detached; reason=%s", reason.String())
Expand All @@ -112,7 +112,7 @@ var fuzzCmd = &cobra.Command{
if err != nil {
return err
}
f.WriteString(lastInput)
f.Write(lastInput)
return nil
}()
if err != nil {
Expand Down Expand Up @@ -149,13 +149,13 @@ var fuzzCmd = &cobra.Command{

l.Infof("Loaded script")

m := mutator.NewMutator(base, runs, fn, validInputs...)
m := mutator.NewMutator([]byte(base), runs, fn, validInputs...)
ch := m.Mutate()

for mutated := range ch {
lastInput = mutated.Input
//lastInput = mutated.Input
l.Infof("[%s] %s\n", color.New(color.FgCyan).Sprintf("%s", mutated.Mutation), mutated.Input)
_ = script.ExportsCall("fuzz", method, mutated.Input)
//_ = script.ExportsCall("fuzz", method, mutated.Input)
if timeout > 0 {
time.Sleep(time.Duration(timeout) * time.Second)
}
Expand Down
10 changes: 5 additions & 5 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ func Execute(sc string) error {
return rootCmd.Execute()
}

func readInputs(dirPath string) ([]string, error) {
func readInputs(dirPath string) ([][]byte, error) {
files, err := os.ReadDir(dirPath)
if err != nil {
return nil, err
}

var validInputs []string
var validInputs [][]byte

for _, fl := range files {
if fl.IsDir() {
Expand All @@ -54,13 +54,13 @@ func readInputs(dirPath string) ([]string, error) {
if err != nil {
return nil, err
}
validInputs = append(validInputs, string(data))
validInputs = append(validInputs, data)
}
return validInputs, nil
}

func crashSHA256(inp string) string {
func crashSHA256(inp []byte) string {
h := sha256.New()
h.Write([]byte(inp))
h.Write(inp)
return fmt.Sprintf("%x", h.Sum(nil))
}
6 changes: 3 additions & 3 deletions mutator/helpers.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package mutator

func (m *Mutator) getFuzzedInput() string {
func (m *Mutator) getFuzzedInput() []byte {
if m.multipleRounds {
if m.lastInput == "" {
if len(m.lastInput) == 0 {
m.lastInput = m.fetchInput()
}
return m.lastInput
}
return m.fetchInput()
}

func (m *Mutator) fetchInput() string {
func (m *Mutator) fetchInput() []byte {
if m.fuzzIdx == -1 || len(m.validInputs) == 0 {
return m.input
}
Expand Down
123 changes: 75 additions & 48 deletions mutator/mutations.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package mutator

import (
"strings"
"unicode"
"bytes"
)

type mutateFn func(m *Mutator) string
type mutateFn func(m *Mutator) []byte

var mutations = map[string]mutateFn{
"insert": insert,
Expand All @@ -19,89 +18,103 @@ var mutations = map[string]mutateFn{
}

// insert inserts random byte at random location inside the input
func insert(m *Mutator) string {
func insert(m *Mutator) []byte {
inp := m.getFuzzedInput()
pos := m.r.Intn(len(inp))
var char byte
for {
c := m.r.Intn(unicode.MaxASCII)
if unicode.IsPrint(rune(c)) {
char = byte(c)
break
char := byte(m.r.Intn(255))

res := make([]byte, len(inp)+1)

k := 0

for i := 0; i < len(inp); i++ {
if i == pos {
res[k] = char
res[k+1] = inp[i]
k += 2
} else {
res[k] = inp[i]
k++
}
}

return inp[:pos] + string(char) + inp[pos:]
return res
}

// del deletes random byte
func del(m *Mutator) string {
func del(m *Mutator) []byte {
inp := m.getFuzzedInput()
pos := m.r.Intn(len(inp))
return inp[:pos] + inp[pos+1:]
res := make([]byte, len(inp)-1)

k := 0
for i := 0; i < len(inp); i++ {
if i == pos {
continue
}
res[k] = inp[i]
k++
}

return res
}

// substitute substitutes byte at random position with random byte
func substitute(m *Mutator) string {
func substitute(m *Mutator) []byte {
inp := m.getFuzzedInput()
pos := m.r.Intn(len(inp))
var char byte
for {
c := m.r.Intn(unicode.MaxASCII)
if unicode.IsPrint(rune(c)) {
char = byte(c)
break
}
}
var res string
char := byte(m.r.Intn(255))

res := make([]byte, len(inp))

for i, c := range inp {
if i == pos {
res += string(char)
res[i] = char
} else {
res += string(c)
res[i] = c
}
}
return res
}

// byteOp takes random byte and random position inside the string
// and do arithmetic operation on them (+, -, *, /)
func byteOp(m *Mutator) string {
func byteOp(m *Mutator) []byte {
b := make([]byte, 1)
m.r.Read(b)
inp := m.getFuzzedInput()
pos := m.r.Intn(len(inp))

op := m.r.Intn(4)

res := make([]rune, len(inp))
res := make([]byte, len(inp))
for i, r := range inp {
if i == pos {
switch op {
case 0:
res[i] = r + rune(b[0])
res[i] = r + b[0]
case 1:
res[i] = r - rune(b[0])
res[i] = r - b[0]
case 2:
res[i] = r * rune(b[0])
res[i] = r * b[0]
default:
if b[0] != 0 {
res[i] = r / rune(b[0])
res[i] = r / b[0]
} else {
res[i] = r + rune(b[0])
res[i] = r + b[0]
}
}
} else {
res[i] = r
}
}

return string(res)
return res
}

// duplicateRange duplicates random range inside the original string random
// number of times
func duplicateRange(m *Mutator) string {
func duplicateRange(m *Mutator) []byte {
inp := m.getFuzzedInput()

start := m.r.Intn(len(inp))
Expand All @@ -115,62 +128,76 @@ func duplicateRange(m *Mutator) string {
}

rng := inp[start:end]
duplicatedBytes := bytes.Repeat(rng, countOfDuplications)

res := make([]byte, len(inp)+len(duplicatedBytes))

k := 0
for i := 0; i < end; i++ {
res[k] = inp[i]
k++
}

for i := 0; i < len(duplicatedBytes); i++ {
res[k] = duplicatedBytes[i]
k++
}

res := ""
res += inp[:start]
res += strings.Repeat(rng, countOfDuplications)
res += inp[end:]
for i := end; i < len(inp); i++ {
res[k] = inp[i]
k++
}

return res
}

// bitFlip flips the bit at random position inside random location inside input
func bitFlip(m *Mutator) string {
func bitFlip(m *Mutator) []byte {
inp := m.getFuzzedInput()

pos := m.r.Intn(len(inp))
bitPosition := m.r.Intn(8)

res := ""
res := make([]byte, len(inp))

for i, r := range inp {
if i == pos {
res += string(r ^ (1 << bitPosition))
res[i] = r ^ (1 << bitPosition)
} else {
res += string(r)
res[i] = r
}
}

return res
}

// bitmask applies random bitmask on random location inside the string
func bitmask(m *Mutator) string {
func bitmask(m *Mutator) []byte {
inp := m.getFuzzedInput()

pos := m.r.Intn(len(inp))
bm := m.r.Intn(255)

res := ""
res := make([]byte, len(inp))

for i, r := range inp {
if pos == i {
res += string(inp[i] ^ uint8(bm))
res[i] = inp[i] ^ uint8(bm)
} else {
res += string(r)
res[i] = r
}
}

return res
}

// duplicate duplicates original string random number of times (2 < 10)
func duplicate(m *Mutator) string {
func duplicate(m *Mutator) []byte {
inp := m.getFuzzedInput()

var count int
for count = m.r.Intn(10); count < 1; count = m.r.Intn(10) {
}

return strings.Repeat(inp, count)
return bytes.Repeat(inp, count)
}
Loading

0 comments on commit 7434fa3

Please sign in to comment.