-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathstrategies.go
121 lines (96 loc) · 2.13 KB
/
strategies.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
package main
import (
"errors"
"math/rand"
)
// https://lcamtuf.blogspot.com/2014/08/binary-fuzzing-strategies-what-works.html
type Mutator interface {
Generate(data []byte, mapping map[int]int, name string) error
Synthesize(data []byte, name string) []byte
Remove(name string)
}
func NewStrats() map[string]Mutator {
strats := make(map[string]Mutator)
strats["bit_flip"] = NewBitFlip()
return strats
}
type ByteDelta struct {
Offset uint64
Value uint8
}
type RandByte struct {
Diffs map[string][]ByteDelta
}
func (rb *RandByte) Generate(data []byte, mapping map[int]int, name string) error {
if len(data) < 1 {
return errors.New("zero size data")
}
rb.Diffs[name] = make([]ByteDelta, 0)
count := 1 + int(rand.Uint64()%8)
for i := 0; i < count; i++ {
rb.Diffs[name] = append(rb.Diffs[name], ByteDelta{
Offset: rand.Uint64() % uint64(len(data)),
Value: uint8(rand.Uint32() & 0xFF),
})
}
return nil
}
func (rb *RandByte) Synthesize(data []byte, name string) []byte {
deltas, ok := rb.Diffs[name]
if !ok {
return data
}
sz := len(data)
bs := make([]byte, sz, sz)
copy(bs, data)
for _, bd := range deltas {
bs[bd.Offset] = bd.Value
}
return bs
}
func (rb *RandByte) Remove(name string) {
delete(rb.Diffs, name)
}
type BitFlip struct {
Flips map[string]uint64
}
func NewBitFlip() *BitFlip {
return &BitFlip{
Flips: make(map[string]uint64),
}
}
func (bf *BitFlip) Generate(data []byte, mapping map[int]int, name string) error {
bitc := uint64(len(data) * 8)
if len(mapping) > 0 {
bitc = uint64(len(mapping) * 8)
}
if bitc == 0 {
return errors.New("bitcount zero")
}
flip := rand.Uint64() % bitc
if len(mapping) > 0 {
byte := flip / 8
bit := flip % 8
byte = uint64(mapping[int(byte)])
flip = byte*8 + bit
}
bf.Flips[name] = flip
return nil
}
func (bf *BitFlip) Synthesize(data []byte, name string) []byte {
bitoff, ok := bf.Flips[name]
if !ok {
return data
}
// Flip a bit!
off := bitoff / 8
bit := bitoff % 8
sz := len(data)
bs := make([]byte, sz, sz)
copy(bs, data)
bs[off] = data[off] ^ (1 << bit)
return bs
}
func (bf *BitFlip) Remove(name string) {
delete(bf.Flips, name)
}