The LangSec Journey by Prashant Anantharaman and Dr. Sergey Bratus
Jul 14, 2017 • 2 min read

Introduction

The goal of this tutorial is to provide a primer to fuzz-test parsers written in hammer. In order to go about this, we will look at 2 simple cpp files; one simply meant to test libfuzzer, and another with a hammer parser.

The LangSec philosophy is to completely recognize all input to conform to a formal language before performing any processing of the input. In order to achieve this, for an input, we define a parser to make sure the input conforms to the language.

libFuzzer is a coverage guided fuzzing engine. In this tutorial we will see how to use libFuzzer with the Hammer parser-combinator toolkit.

Setting up the environment

Why Hammer

Download our sample CPP programs – fuzz_me.cc and fuzz_me_with_hammer.cc.

In the fuzz_me.cc file, you should see the method below. As you may have noticed, there is a buffer overflow here and this is caught when we compile and run it.

void ProcessData(const uint8_t *Data, size_t DataSize)
 {       
      return DataSize >= 3 &&
      Data[0] == 'F' &&
      Data[1] == 'U' &&
      Data[2] == 'Z' &&
      Data[3] == 'Z';
 }

We run the following commands to compile and run fuzz_me.cc.

clang++ -g -fsanitize=address -fsanitize-coverage=trace-pc-guard fuzz_me.cc libFuzzer.a
./a.out

Let us now look at the fuzz_test_with_hammer.cc. In this file, we want to make sure that we recognize the input fully before performing any processing. In order to do this, we write a simple hammer parser to recognize the input that is expected by this particular program.

void ValidateInput(const uint8_t *Data, size_t DataSize) 
  {
    HParser *parser = h_sequence(h_ch('F'),
    	    h_ch('U'),
            h_ch('Z'),
            h_ch('Z'),
            h_end_p(), NULL);
    const HParseResult *result;
    result = h_parse(parser, Data, 4); 
    if(result)
    {
      ProcessData(Data, DataSize);
    }
  }

In the above method, the h_parse() method returns a null if parsing was unsuccessful.

clang++ -g -lhammer -fsanitize=address -fsanitize-coverage=trace-pc-guard fuzz_me_with_hammer.cc libFuzzer.a
./a.out -detect_leaks=0

When we run the cpp file fuzz_me_with_hammer.cc, we see that nothing interesting happers here when we included a hammer parser to recognize the input strictly before any processing.