deepstate icon indicating copy to clipboard operation
deepstate copied to clipboard

Investigate a fuzzer-friendly serialization

Open neuromancer opened this issue 6 years ago • 1 comments

http://llvm.org/devmtg/2017-10/slides/Serebryany-Structure-aware%20fuzzing%20for%20Clang%20and%20LLVM%20with%20libprotobuf-mutator.pdf https://github.com/google/libprotobuf-mutator

neuromancer avatar Dec 29 '19 00:12 neuromancer

To some extent, we try to do this with DeepState_InputPath, seen here, which enables us to parse out a filename rather than read it out completely, and can be useful here when software under test consumes a filename input to create some type of structure.

/* .. what we can currently do in DeepState */
TEST(Test, SimpleMutationExample) {
    const char * js_file = DeepState_InputPath();
    JSObj *deser = ParseSourceToJS(js_file, ...);

    ASSERT(deser.isValid() == 1);
    deser.doStuff();
}

While this makes the framework kind of structure-aware, it's by no means as effective as using custom mutators with LLVM.

For improvements on the grammar/structure generation aspect of DeepState, we may want to take inspiration from binaryen and how it fuzzes WASM, where random AFL-generated input cases can act as seeds to a codegen routine (ie DeepState_Mutator), which then generates valid structured source in some shape or form.

/* .. what we may ideally want for better structure-awareness */

class MyMutator: DeepStateMutator {
    using T = JSObj;

    public:
        
        /* some internal routine would store and parse a CFG */
        std::string grammar_source("some_typeof_grammar.bnf");

        /* once a structure is generated, user implements this to parse with library under test and validate it */
        T ParseValidate() {}

    private:

       /* use DeepState input somehow as a sort-of RNG for how we will randomly recurse CFG. This 
        * would ideally be a default method in parent.  */
        void Map(unsigned char *seed, size_t max_size) {}
}

TEST(Test, BetterMutationExample) {

    /* generates completely random input, assume no presence of dictionaries, etc. */
    char *input = DeepState_C(input_size);

   /* constructor would invoke all functionality of mutator, and return final deserialized object */
    MyMutator m(input, source_size);
    JSObj *deser = m.ParseValidate();

    //ASSERT(deser.isValid() == 1);
    deser.doStuff();
}

ex0dus-0x avatar Dec 30 '19 17:12 ex0dus-0x