fuzzing a child process

836 views
Skip to first unread message

whifr...@gmail.com

unread,
Apr 25, 2018, 4:17:50 PM4/25/18
to afl-users
hello,

i am trying to fuzz a program (child) which i can only call by another program (parent) with fork() and execlp().
child and parent are communicating via sockets. parent gets the AFL fuzzing inputs and sends it to child. both programs are instrumented by afl-gcc.

AFL <-stdin-> parent <-socket-> child

i found forum posts suggesting to modify the parent so it would abort() if the child crashes with SIGABRT or SIGSEGV.
but i am wondering if that would be ineffective in my setup because AFL would not be able to "see" the child code instrumented by afl-gcc.
is there a way to accomplish that AFL "sees" the instrumented code of child?

regards,
samuel

Marc Heuse

unread,
Apr 25, 2018, 4:35:15 PM4/25/18
to afl-...@googlegroups.com, whifr...@gmail.com
Hi Samuel,

this is not a setup where you have the benefit of AFL.
AFL is good because it sees what paths the input takes in the target
program (roughly).
I am not sure of the specifics of your setup but my guess is that AFL
only sees the path data form the parent and none of the client, hence
basically what you are doing is dumb fuzzing.

as you have instrumented the client with gcc it means you have the
source code for the client ... so it should be really easy to modify the
client so you can execute it directly.

e.g. just modifying the client that the read from socket is not the
socket it creates but from fd 0 - that could already be enough.

Regards,
Marc
> --
> You received this message because you are subscribed to the Google
> Groups "afl-users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to afl-users+...@googlegroups.com
> <mailto:afl-users+...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout.

--
--
Marc Heuse
www.mh-sec.de

PGP: AF3D 1D4C D810 F0BB 977D 3807 C7EE D0A0 6BE9 F573

Jacopo Corbetta

unread,
Apr 25, 2018, 6:54:49 PM4/25/18
to afl-...@googlegroups.com
Hi!

If you are indeed looking to fuzz both processes together, you might be interested in https://github.com/mechaphish/multiafl

Basically, we had an intermediate process keep track of children and relay status back and forth. AFL then works unchanged.

We implemented it for CGC, so that code uses our qemu and creates the sockets itself. It should be fairly easy to remove this part.

We also made the shared memory bigger (and had each guy touch only its half / third / ...), but you may not need this.

Hope it's useful, and happy fuzzing :)
Jacopo


--
You received this message because you are subscribed to the Google Groups "afl-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to afl-users+...@googlegroups.com.

whifr...@gmail.com

unread,
Apr 27, 2018, 4:26:37 AM4/27/18
to afl-users
Hi,
thanks for the fast answers. i will look into the multiafl tool.

Regards,
samuel

Jakub Wilk

unread,
Apr 30, 2018, 11:00:33 AM4/30/18
to afl-...@googlegroups.com
* whifr...@gmail.com, 2018-04-25, 13:17:
Instrumentation should work across fork+exec out of the box, as long as
both programs are instrumented.

Of course it's going to be slow, and (as you noted) you have to take
care of propagating child crashes to the parent.

--
Jakub Wilk

whifr...@gmail.com

unread,
May 12, 2018, 3:39:49 AM5/12/18
to afl-users
Hello Jakub,

thanks for the answer. i just saw it today, that's why i repley so late.
i guess there are other problems besides afl not seeing crashes from child processes of fuzzing targets. afl does not get coverage from the child process, although it is instrumented with afl-gcc.

for example:

parent.c:
======
//get data from stdin and initialize command.
sprintf(command,"exec echo %s | ./child ", data);
int pid = fork();
if (pid==0){
      execlp("/bin/sh", "sh", "-c", command, NULL);
      exit(1);
}
return 0;
======

and

child.c:
======
//parse data from stdin
if (strstr(data,"a")){
     if (strstr(data,"b")){
         //a total of e.g. 16 if statements
         raise(SIGSEGV);
     }
}
======

if i fuzz child directly, i get 16 paths after less than 2 minutes.
if i fuzz parent, i get 8 paths. if parent is not instrumented with afl-gcc, but child is, i only get 1 path.

am i missing something?

thanks in advance!

regards,
samuel

Jakub Wilk

unread,
May 12, 2018, 5:14:59 AM5/12/18
to afl-...@googlegroups.com
Complete example code would have been helpful...

* whifr...@gmail.com, 2018-05-12, 00:39:
>parent.c:
>======
>//get data from stdin and initialize command.
>sprintf(command,"exec echo %s | ./child ", data);

I hope you sanitized the input first; otherwise there's a shell
injection vulnerability here.

>int pid = fork();
>if (pid==0){
> execlp("/bin/sh", "sh", "-c", command, NULL);
> exit(1);
>}
>return 0;

You didn't wait for the child process to finish. (Low stability ratio
should have given you a clue that something is wrong.)

I've attached complete C sources that I used for testing.

>if i fuzz child directly, i get 16 paths after less than 2 minutes.

Yup.

>if i fuzz parent, i get 8 paths.

I get 20 eventually, but obviously it takes much more time.

>if parent is not instrumented with afl-gcc, but child is, i only get 1
>path.

That's weird. If I try this, I get:

[-] PROGRAM ABORT : No instrumentation detected
Location : check_binary(), afl-fuzz.c:6920

And this is not just AFL being overly cautious. The parent has to be
instrumented for the forkserver to start correctly.

--
Jakub Wilk
parent.c
child.c

whifr...@gmail.com

unread,
Jun 4, 2018, 10:33:56 AM6/4/18
to afl-users
Hello Jakub,
thanks for the help, you were right. I looked into my setup and found the problem, it was unrelated to AFL.
The other question:
Setting AFL_SKIP_BIN_CHECK=1 and AFL_NO_FORKSRV=1 makes it possible to fuzz non-instrumented binarys which execute instrumented child programs.
One can see the coverage from the child
I was able to start AFL with that command and a test file containing 10 A's:

AFL_SKIP_BIN_CHECK=1 AFL_NO_FORKSRV=1 AFL_SKIP_CPUFREQ=1 afl-fuzz -i in -o out -m 4096 -- ./parent

i attached my source code...

Regards,
Samuel
parent.c
child.c

Jakub Wilk

unread,
Jun 6, 2018, 12:06:36 PM6/6/18
to afl-...@googlegroups.com
* whifr...@gmail.com, 2018-06-04, 07:33:
>The other question:
>Setting AFL_SKIP_BIN_CHECK=1 and AFL_NO_FORKSRV=1 makes it possible to
>fuzz non-instrumented binarys which execute instrumented child
>programs.
>One can see the coverage from the child
>I was able to start AFL with that command and a test file containing 10 A's:
>
>AFL_SKIP_BIN_CHECK=1 AFL_NO_FORKSRV=1 AFL_SKIP_CPUFREQ=1 afl-fuzz -i in
>-o out -m 4096 -- ./parent
>
>i attached my source code...

So what's your question? :)

--
Jakub Wilk

whifr...@gmail.com

unread,
Jun 11, 2018, 4:02:33 AM6/11/18
to afl-users
There is none, i just wanted to end this thread properly and say thanks :-)
Reply all
Reply to author
Forward
0 new messages