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
168
169
170
171
172
173
|
#include "../../include/afl-fuzz.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define INIT_BUF_SIZE 4096
#define SOCKET_NAME "/tmp/atnwalk.socket"
// handshake constants
const uint8_t SERVER_ARE_YOU_ALIVE = 42;
const uint8_t SERVER_YES_I_AM_ALIVE = 213;
// control bits
const uint8_t SERVER_DECODE_BIT = 0b00000001;
const uint8_t SERVER_ENCODE_BIT = 0b00000010;
const uint8_t SERVER_MUTATE_BIT = 0b00000100;
const uint8_t SERVER_CROSSOVER_BIT = 0b00001000;
typedef struct atnwalk_mutator {
uint8_t *decoded_buf;
size_t decoded_size;
} atnwalk_mutator_t;
int read_all(int fd, uint8_t *buf, size_t buf_size) {
int n;
size_t offset = 0;
while (offset < buf_size) {
n = read(fd, buf + offset, buf_size - offset);
if (n == -1) {
return 0;
}
offset += n;
}
return 1;
}
int write_all(int fd, uint8_t *buf, size_t buf_size) {
int n;
size_t offset = 0;
while (offset < buf_size) {
n = write(fd, buf + offset, buf_size - offset);
if (n == -1) {
return 0;
}
offset += n;
}
return 1;
}
/**
* Initialize this custom mutator
*
* @param[in] afl a pointer to the internal state object. Can be ignored for
* now.
* @param[in] seed A seed for this mutator - the same seed should always mutate
* in the same way.
* @return Pointer to the data object this custom mutator instance should use.
* There may be multiple instances of this mutator in one afl-fuzz run!
* Return NULL on error.
*/
atnwalk_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
srand(seed);
atnwalk_mutator_t *data = (atnwalk_mutator_t *) malloc(sizeof(atnwalk_mutator_t));
if (!data) {
perror("afl_custom_init alloc");
return NULL;
}
data->decoded_buf = (uint8_t *) malloc(INIT_BUF_SIZE);
data->decoded_size = INIT_BUF_SIZE;
return data;
}
// TODO: implement
/**
* Perform custom mutations on a given input
*
* (Optional for now. Required in the future)
*
* @param[in] data pointer returned in afl_custom_init for this fuzz case
* @param[in] buf Pointer to input data to be mutated
* @param[in] buf_size Size of input data
* @param[out] out_buf the buffer we will work on. we can reuse *buf. NULL on
* error.
* @param[in] add_buf Buffer containing the additional test case
* @param[in] add_buf_size Size of the additional test case
* @param[in] max_size Maximum size of the mutated output. The mutation must not
* produce data larger than max_size.
* @return Size of the mutated output.
*/
size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf,
uint8_t *add_buf, size_t add_buf_size, size_t max_size) {
struct sockaddr_un addr;
int fd_socket;
ssize_t n;
uint8_t buffer[5];
// initialize the socket
fd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd_socket == -1) {
perror("socket");
*out_buf = NULL;
return 0;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) {
perror("atnwalk server is down");
*out_buf = NULL;
return 0;
}
if (!write_all(fd_socket, buffer, 5)) {
perror("write to atnwalk server failed");
*out_buf = NULL;
return 0;
}
if (read_all(fd_socket, buffer, 5)) {
perror("read to atnwalk server failed");
exit(EXIT_FAILURE);
}
close(fd_socket);
}
// TODO: implement
/**
* A post-processing function to use right before AFL writes the test case to
* disk in order to execute the target.
*
* (Optional) If this functionality is not needed, simply don't define this
* function.
*
* @param[in] data pointer returned in afl_custom_init for this fuzz case
* @param[in] buf Buffer containing the test case to be executed
* @param[in] buf_size Size of the test case
* @param[out] out_buf Pointer to the buffer containing the test case after
* processing. External library should allocate memory for out_buf.
* The buf pointer may be reused (up to the given buf_size);
* @return Size of the output buffer after processing or the needed amount.
* A return of 0 indicates an error.
*/
size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) {
data->decoded_buf[0] = 'p';
data->decoded_buf[1] = 'u';
data->decoded_buf[2] = 't';
data->decoded_buf[3] = 's';
data->decoded_buf[4] = ' ';
data->decoded_buf[5] = ';';
data->decoded_buf[6] = '\n';
return 7;
}
// TODO: implement
/**
* Deinitialize everything
*
* @param data The data ptr from afl_custom_init
*/
void afl_custom_deinit(atnwalk_mutator_t *data) {
free(data->decoded_buf);
free(data);
}
|