xref: /aosp_15_r20/external/AFLplusplus/utils/afl_proxy/afl-proxy.c (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1 /*
2    american fuzzy lop++ - afl-proxy skeleton example
3    ---------------------------------------------------
4 
5    Written by Marc Heuse <[email protected]>
6 
7    Copyright 2019-2024 AFLplusplus Project. All rights reserved.
8 
9    Licensed under the Apache License, Version 2.0 (the "License");
10    you may not use this file except in compliance with the License.
11    You may obtain a copy of the License at:
12 
13    http://www.apache.org/licenses/LICENSE-2.0
14 
15 
16    HOW-TO
17    ======
18 
19    You only need to change the while() loop of the main() to send the
20    data of buf[] with length len to the target and write the coverage
21    information to __afl_area_ptr[__afl_map_size]
22 
23 
24 */
25 
26 #ifdef __ANDROID__
27   #include "android-ashmem.h"
28 #endif
29 #include "config.h"
30 #include "types.h"
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <signal.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <assert.h>
38 #include <stdint.h>
39 #include <errno.h>
40 
41 #include <sys/mman.h>
42 #include <sys/shm.h>
43 #include <sys/wait.h>
44 #include <sys/types.h>
45 #include <fcntl.h>
46 
47 u8 *__afl_area_ptr;
48 
49 #ifdef __ANDROID__
50 u32 __afl_map_size = MAP_SIZE;
51 #else
52 __thread u32 __afl_map_size = MAP_SIZE;
53 #endif
54 
55 /* Error reporting to forkserver controller */
56 
send_forkserver_error(int error)57 void send_forkserver_error(int error) {
58 
59   u32 status;
60   if (!error || error > 0xffff) return;
61   status = (FS_OPT_ERROR | FS_OPT_SET_ERROR(error));
62   if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) return;
63 
64 }
65 
66 /* SHM setup. */
67 
__afl_map_shm(void)68 static void __afl_map_shm(void) {
69 
70   char *id_str = getenv(SHM_ENV_VAR);
71   char *ptr;
72 
73   /* NOTE TODO BUG FIXME: if you want to supply a variable sized map then
74      uncomment the following: */
75 
76   /*
77   if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) {
78 
79     u32 val = atoi(ptr);
80     if (val > 0) __afl_map_size = val;
81 
82   }
83 
84   */
85 
86   if (__afl_map_size > MAP_SIZE) {
87 
88     if (__afl_map_size > FS_OPT_MAX_MAPSIZE) {
89 
90       fprintf(stderr,
91               "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to "
92               "be able to run this instrumented program!\n",
93               __afl_map_size);
94       if (id_str) {
95 
96         send_forkserver_error(FS_ERROR_MAP_SIZE);
97         exit(-1);
98 
99       }
100 
101     } else {
102 
103       fprintf(stderr,
104               "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to "
105               "be able to run this instrumented program!\n",
106               __afl_map_size);
107 
108     }
109 
110   }
111 
112   if (id_str) {
113 
114 #ifdef USEMMAP
115     const char    *shm_file_path = id_str;
116     int            shm_fd = -1;
117     unsigned char *shm_base = NULL;
118 
119     /* create the shared memory segment as if it was a file */
120     shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
121     if (shm_fd == -1) {
122 
123       fprintf(stderr, "shm_open() failed\n");
124       send_forkserver_error(FS_ERROR_SHM_OPEN);
125       exit(1);
126 
127     }
128 
129     /* map the shared memory segment to the address space of the process */
130     shm_base =
131         mmap(0, __afl_map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
132 
133     if (shm_base == MAP_FAILED) {
134 
135       close(shm_fd);
136       shm_fd = -1;
137 
138       fprintf(stderr, "mmap() failed\n");
139       send_forkserver_error(FS_ERROR_MMAP);
140       exit(2);
141 
142     }
143 
144     __afl_area_ptr = shm_base;
145 #else
146     u32 shm_id = atoi(id_str);
147 
148     __afl_area_ptr = shmat(shm_id, 0, 0);
149 
150 #endif
151 
152     if (__afl_area_ptr == (void *)-1) {
153 
154       send_forkserver_error(FS_ERROR_SHMAT);
155       exit(1);
156 
157     }
158 
159     /* Write something into the bitmap so that the parent doesn't give up */
160 
161     __afl_area_ptr[0] = 1;
162 
163   }
164 
165 }
166 
167 /* Fork server logic. */
168 
__afl_start_forkserver(void)169 static void __afl_start_forkserver(void) {
170 
171   u8  tmp[4] = {0, 0, 0, 0};
172   u32 status = 0;
173 
174   if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
175     status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
176   if (status) status |= (FS_OPT_ENABLED);
177   memcpy(tmp, &status, 4);
178 
179   /* Phone home and tell the parent that we're OK. */
180 
181   if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
182 
183 }
184 
__afl_next_testcase(u8 * buf,u32 max_len)185 static u32 __afl_next_testcase(u8 *buf, u32 max_len) {
186 
187   s32 status, res = 0xffffff;
188 
189   /* Wait for parent by reading from the pipe. Abort if read fails. */
190   if (read(FORKSRV_FD, &status, 4) != 4) return 0;
191 
192   /* we have a testcase - read it */
193   status = read(0, buf, max_len);
194 
195   /* report that we are starting the target */
196   if (write(FORKSRV_FD + 1, &res, 4) != 4) return 0;
197 
198   return status;
199 
200 }
201 
__afl_end_testcase(void)202 static void __afl_end_testcase(void) {
203 
204   int status = 0xffffff;
205 
206   if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(1);
207 
208 }
209 
210 /* you just need to modify the while() loop in this main() */
211 
main(int argc,char * argv[])212 int main(int argc, char *argv[]) {
213 
214   /* This is were the testcase data is written into */
215   u8  buf[1024];  // this is the maximum size for a test case! set it!
216   s32 len;
217 
218   /* here you specify the map size you need that you are reporting to
219      afl-fuzz.  Any value is fine as long as it can be divided by 32. */
220   __afl_map_size = MAP_SIZE;  // default is 65536
221 
222   /* then we initialize the shared memory map and start the forkserver */
223   __afl_map_shm();
224   __afl_start_forkserver();
225 
226   while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) {
227 
228     if (len > 4) {  // the minimum data size you need for the target
229 
230       /* here you have to create the magic that feeds the buf/len to the
231          target and write the coverage to __afl_area_ptr */
232 
233       // ... the magic ...
234 
235       // remove this, this is just to make afl-fuzz not complain when run
236       if (buf[0] == 0xff)
237         __afl_area_ptr[1] = 1;
238       else
239         __afl_area_ptr[2] = 2;
240 
241     }
242 
243     /* report the test case is done and wait for the next */
244     __afl_end_testcase();
245 
246   }
247 
248   return 0;
249 
250 }
251 
252