AFLplusplus / Grammar-Mutator

A grammar-based custom mutator for AFL++
Apache License 2.0
215 stars 18 forks source link

Grammar Mutator crashes due to null pointer dereference on write_tree_to_file #14

Closed MegaManSec closed 3 years ago

MegaManSec commented 3 years ago

A crash happens when writing some trees to file:

881 ret = write(fd, tree->ser_buf, tree->ser_len); (gdb) bt

0 0x00007ffff6a3a40a in write_tree_to_file (tree=0x0, filename=0x555555650788 "fuzzer/custom/trees/id:000110,sync:main-pexploit,src:000001,+cov") at tree.c:881

1 0x00007ffff6a38335 in afl_custom_queue_new_entry (data=0x55555564f6e0, filename_new_queue=0x55555a6e7720 "fuzzer/custom/queue/id:000110,sync:main-pexploit,src:000001,+cov", filename_orig_queue=0x55555565ac00 "fuzzer/custom/queue/id:000028,time:0,orig:34")

at grammar_mutator.c:563

2 0x00005555555926e6 in add_to_queue (afl=0x7ffff7655010, fname=0x55555a6e7720 "fuzzer/custom/queue/id:000110,sync:main-pexploit,src:000001,+cov", len=, passed_det=) at src/afl-fuzz-queue.c:473

3 0x0000555555562c91 in save_if_interesting (afl=afl@entry=0x7ffff7655010, mem=mem@entry=0x7ffff7ffb000, len=109, fault=0 '\000') at src/afl-fuzz-bitmap.c:516

4 0x000055555556ded3 in sync_fuzzers (afl=) at src/afl-fuzz-run.c:667

5 0x000055555555f578 in main (argc=, argv_orig=, envp=) at src/afl-fuzz.c:2037

0x00007ffff6a3a40a in write_tree_to_file (tree=0x0, filename=0x555555650a58 "fuzzer/custom/trees/id:000110,sync:main-pexploit,src:000001,+cov") at tree.c:881 881 ret = write(fd, tree->ser_buf, tree->ser_len); (gdb) p fd $4 = 14 (gdb) p tree->ser_buf Cannot access memory at address 0x20 (gdb) p tree $5 = (tree_t *) 0x0

As we can see, 'tree' here is NULL, and yet tree->ser_buf is dereferenced:

(gdb) l 876 return; 877 878 } 879 880 // Write the data 881 ret = write(fd, tree->ser_buf, tree->ser_len); 882 if (unlikely(ret < 0)) { 883 884 perror("Unable to write (write_tree_to_file)"); 885 return; (gdb) bt

0 0x00007ffff6a3a40a in write_tree_to_file (tree=0x0, filename=0x555555650a58 "fuzzer/custom/trees/id:000110,sync:main-pexploit,src:000001,+cov") at tree.c:881

1 0x00007ffff6a38335 in afl_custom_queue_new_entry (data=0x55555564f9b0, filename_new_queue=0x55555577e7f0 "fuzzer/custom/queue/id:000110,sync:main-pexploit,src:000001,+cov", filename_orig_queue=0x55555565af10 "fuzzer/custom/queue/id:000028,time:0,orig:34")

at grammar_mutator.c:563

2 0x00005555555926e6 in add_to_queue (afl=0x7ffff7655010, fname=0x55555577e7f0 "fuzzer/custom/queue/id:000110,sync:main-pexploit,src:000001,+cov", len=, passed_det=) at src/afl-fuzz-queue.c:473

3 0x0000555555562c91 in save_if_interesting (afl=afl@entry=0x7ffff7655010, mem=mem@entry=0x7ffff7ffb000, len=109, fault=0 '\000') at src/afl-fuzz-bitmap.c:516

4 0x000055555556ded3 in sync_fuzzers (afl=) at src/afl-fuzz-run.c:667

5 0x000055555555f578 in main (argc=, argv_orig=, envp=) at src/afl-fuzz.c:2037

My setup: AFL_IMPORT_FIRST=1 AFL_NO_AFFINITY=1 AFL_MAP_SIZE=137344 afl-fuzz -x dict.dict -i ~/Grammar-Mutator/seeds/ -o fuzzer -S custom ./program other children (and main) are not using grammar-mutator. fuzzer/custom/trees/ exists and is populated per the manual.

MegaManSec commented 3 years ago

ąlso fyi, there is actually some successful writes because the trees directory has some 'found' files in it in addition to the original ones.

h1994st commented 3 years ago

Hi @MegaManSec,

The grammar mutator currently requires the user to set AFL_CUSTOM_MUTATOR_ONLY to 1, as the mutation methods in AFL may destroy the grammar structure.

I guess one possible reason for your error is that you did not set this environment variable. Another potential reason may come from the multiple fuzzers (-M/-S sync mode). You mentioned that only one fuzzer used the grammar mutator, but the grammar mutator has not been well tested in such a hybrid way.

Maybe you can first try to enable grammar mutator for all fuzzers, or only keep the grammar mutator. I can also take a closer look at your issue during the weekend.


In your case, data->mutated_tree is NULL, while invoking afl_custom_queue_new_entry.

https://github.com/AFLplusplus/Grammar-Mutator/blob/b15459d289c399f8044264fae9f587c1ea66b123/src/grammar_mutator.c#L562-L563

However, data->mutated_tree should have been populated in afl_custom_fuzz. It looks like the newly generated interesting test case did not go through the fuzzing process, afl_custom_fuzz, of the grammar mutator.

https://github.com/AFLplusplus/Grammar-Mutator/blob/b15459d289c399f8044264fae9f587c1ea66b123/src/grammar_mutator.c#L517-L520

MegaManSec commented 3 years ago

Hi @h1994st Thanks for the suport.

I forgot to mention that I am using AFL_CUSTOM_MUTATOR_ONLY as well.

h1994st commented 3 years ago

Hi @MegaManSec

I tried to reproduce the crash but failed.

Would you mind providing more information about the crash, like the setup for main and all children fuzzers, dict.dict file, and your program under testing? Thanks!

h1994st commented 3 years ago

Hi @MegaManSec ,

Your issue looks similar to a recent issue that is reported in AFLplusplus: https://github.com/AFLplusplus/AFLplusplus/issues/867

There is also a fix here: https://github.com/AFLplusplus/AFLplusplus/commit/019b26de58a4e7eb4b95aab6425beba4efb853f4

You can use the latest AFLplusplus to see if it can address your problem.

MegaManSec commented 3 years ago

Hi @h1994st Sorry for the late response, I forgot about this completely; I stoped using the grammar mutator in the meantime.

I will try this patch some time in the future, but I am nearly certain that is indeed the issue. I will close this for now, unless I can replicate it in the future.

Thanks!

MegaManSec commented 3 years ago

Also the issues seems to happen at the exact same time no matter what (approx 50 seconds after starting). The sync phase is happening, afl-fuzz seems to hang (I can't even control-c out), then a segfault happens.

But actually, this seems to be a different issue now. From gdb, it seems there is some infinite recursion going on:

#764 0x00007fffeed762f8 in antlr4::atn::ParserATNSimulator::closureCheckingStopState(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#765 0x00007fffeed7a67a in antlr4::atn::ParserATNSimulator::closure_(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#766 0x00007fffeed763a5 in antlr4::atn::ParserATNSimulator::closureCheckingStopState(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#767 0x00007fffeed7a67a in antlr4::atn::ParserATNSimulator::closure_(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#768 0x00007fffeed763a5 in antlr4::atn::ParserATNSimulator::closureCheckingStopState(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#769 0x00007fffeed762f8 in antlr4::atn::ParserATNSimulator::closureCheckingStopState(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#770 0x00007fffeed7a67a in antlr4::atn::ParserATNSimulator::closure_(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#771 0x00007fffeed763a5 in antlr4::atn::ParserATNSimulator::closureCheckingStopState(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#772 0x00007fffeed7a67a in antlr4::atn::ParserATNSimulator::closure_(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#773 0x00007fffeed763a5 in antlr4::atn::ParserATNSimulator::closureCheckingStopState(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#774 0x00007fffeed762f8 in antlr4::atn::ParserATNSimulator::closureCheckingStopState(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#775 0x00007fffeed7a67a in antlr4::atn::ParserATNSimulator::closure_(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so
#776 0x00007fffeed763a5 in antlr4::atn::ParserATNSimulator::closureCheckingStopState(std::shared_ptr<antlr4::atn::ATNConfig> const&, antlr4::atn::ATNConfigSet*, std::unordered_set<std::shared_ptr<antlr4::atn::ATNConfig>, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<std::shared_ptr<antlr4::atn::ATNConfig> > >&, bool, bool, int, bool) () from /home/jrogers/Grammar-Mutator/libgrammarmutator-http.so

There are 12077 frames of this :).

Any suggestions?

h1994st commented 3 years ago

That's interesting.

It seems to be the problem of the parser. I will take a look.

MegaManSec commented 3 years ago

Yup; I used a slightly simpler grammar and it worked fine; original problem is fixed!

So this new problem is to do with the grammar; not really sure what the issue is though, but my guess is it's related to either <ANY> or <SPECIAL> or <CHAR>.

h1994st commented 3 years ago

Same here. The issue did not always appear on my side, but it is probably due to the grammar. I observed a long recursive call, while parsing <DIR>. With ambiguous grammars, the parser may not work well, so try to avoid triggering parsing. Especially, the HTTP grammar file has ambiguity, which makes the ANTLR parser hard to work.

I will close this issue, as the original problem is fixed. :)

MegaManSec commented 3 years ago

Yup, it works after some attempts. Thank you for the help.

vanhauser-thc commented 3 years ago

If there is still an issue with grammar then this still has to be fixed, or? “Use simpler grammar” can’t be the solution

MegaManSec commented 3 years ago

It is a different issue than the original post. I could make a new issue if necessary.

I also suspect it's an issue with antlr rather than with Grammar-Mutator.

Also note I deleted a comment in this issue because the project I am fuzzing does not have the resources to deal with other people looking for security issues right now (sorry)

vanhauser-thc commented 3 years ago

yes please make a new issue then :)