mirror of https://github.com/OISF/suricata
fuzz: adds eight fuzz targets
And ways to compile them with enable-fuzztargets at configure time Adds utility function in util-unittest-helperpull/4715/head
parent
1c8943dedd
commit
600b0d7c55
@ -0,0 +1,57 @@
|
||||
How to run fuzzing ?
|
||||
|
||||
1) With oss-fuzz
|
||||
- install docker
|
||||
- run git clone --branch suricata --depth 1 https://github.com/catenacyber/oss-fuzz
|
||||
(we will use the original google repo once we merge this)
|
||||
- change directory into cloned repository : cd oss-fuzz
|
||||
- run python infra/helper.py build_image suricata
|
||||
- run python infra/helper.py build_fuzzers --sanitizer address suricata
|
||||
You can use undefined sanitizer (memory sanitizer does not work yet see https://github.com/google/oss-fuzz/issues/2145#issuecomment-485781098
|
||||
- run python infra/helper.py run_fuzzer suricata fuzz_siginit
|
||||
(or another fuzz target, try ls build/out/suricata/fuzz_*)
|
||||
|
||||
To generate coverage :
|
||||
- run python infra/helper.py build_fuzzers --sanitizer=coverage suricata
|
||||
- get a corpus cf https://github.com/google/oss-fuzz/issues/2490
|
||||
- put your corpus in build/corpus/suricata/<fuzz_target_name>/
|
||||
- run python infra/helper.py coverage --no-corpus-download suricata
|
||||
|
||||
2) With libfuzzer
|
||||
|
||||
To compile the fuzz targets, you should do the following :
|
||||
```
|
||||
export CFLAGS="-g -fsanitize=address,fuzzer-no-link"
|
||||
export LDFLAGS="-g -fsanitize=address"
|
||||
export CC=clang
|
||||
./configure --enable-fuzztargets
|
||||
make
|
||||
```
|
||||
|
||||
You can specify other sanitizers here such as undefined and memory
|
||||
|
||||
Then you can run a target :
|
||||
./src/.libs/fuzz_target_x your_libfuzzer_options
|
||||
Where target_x is on file in `ls ./src/.libs/fuzz_*`
|
||||
|
||||
If your clang does not support the compile flag "-fsanitize=fuzzer" (MacOS), you can run these same commands but you need first to install libfuzzer as libFuzzingEngine and you need to add `export LIB_FUZZING_ENGINE=/path/to/libFuzzer.a` before calling configure command
|
||||
|
||||
To compile libFuzzer, you can do the following
|
||||
```
|
||||
svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer
|
||||
cd fuzzer
|
||||
./build.sh
|
||||
```
|
||||
|
||||
|
||||
3) With afl
|
||||
|
||||
To compile the fuzz targets, you simply need to run
|
||||
```
|
||||
CC=afl-gcc ./configure --enable-fuzztargets
|
||||
CC=afl-gcc make
|
||||
```
|
||||
You can rather use afl-clang if needed.
|
||||
|
||||
Then you can run afl as usual with each of the fuzz targets in ./src/.libs/
|
||||
afl-fuzz your_afl_options -- ./src/.libs/fuzz_target_x @@
|
||||
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Philippe Antoine <contact@catenacyber.fr>
|
||||
* fuzz target for AppLayerProtoDetectGetProto
|
||||
*/
|
||||
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "app-layer-detect-proto.h"
|
||||
#include "flow-util.h"
|
||||
#include "app-layer-parser.h"
|
||||
#include "util-unittest-helper.h"
|
||||
|
||||
#define HEADER_LEN 6
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
|
||||
AppLayerParserThreadCtx *alp_tctx = NULL;
|
||||
|
||||
/* input buffer is structured this way :
|
||||
* 6 bytes header,
|
||||
* then sequence of buffers separated by magic bytes 01 D5 CA 7A */
|
||||
|
||||
/* The 6 bytes header is
|
||||
* alproto
|
||||
* proto
|
||||
* source port (uint16_t)
|
||||
* destination port (uint16_t) */
|
||||
|
||||
const uint8_t separator[] = {0x01, 0xD5, 0xCA, 0x7A};
|
||||
SCInstance suricata;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
Flow * f;
|
||||
TcpSession ssn;
|
||||
const uint8_t * albuffer;
|
||||
uint8_t * alnext;
|
||||
size_t alsize;
|
||||
// used to find under and overflows
|
||||
// otherwise overflows do not fail as they read the next packet
|
||||
uint8_t * isolatedBuffer;
|
||||
|
||||
if (size < HEADER_LEN) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (alp_tctx == NULL) {
|
||||
//Redirects logs to /dev/null
|
||||
setenv("SC_LOG_OP_IFACE", "file", 0);
|
||||
setenv("SC_LOG_FILE", "/dev/null", 0);
|
||||
|
||||
InitGlobal();
|
||||
run_mode = RUNMODE_PCAP_FILE;
|
||||
GlobalsInitPreConfig();
|
||||
|
||||
//redirect logs to /tmp
|
||||
ConfigSetLogDirectory("/tmp/");
|
||||
|
||||
PostConfLoadedSetup(&suricata);
|
||||
alp_tctx = AppLayerParserThreadCtxAlloc();
|
||||
}
|
||||
|
||||
if (data[0] >= ALPROTO_MAX) {
|
||||
return 0;
|
||||
}
|
||||
//no UTHBuildFlow to have storage
|
||||
f = FlowAlloc();
|
||||
if (f == NULL) {
|
||||
return 0;
|
||||
}
|
||||
f->flags |= FLOW_IPV4;
|
||||
f->src.addr_data32[0] = 0x01020304;
|
||||
f->dst.addr_data32[0] = 0x05060708;
|
||||
f->sp = (data[2] << 8) | data[3];
|
||||
f->dp = (data[4] << 8) | data[5];
|
||||
f->proto = data[1];
|
||||
memset(&ssn, 0, sizeof(TcpSession));
|
||||
f->protoctx = &ssn;
|
||||
f->protomap = FlowGetProtoMapping(f->proto);
|
||||
f->alproto = data[0];
|
||||
|
||||
/*
|
||||
* We want to fuzz multiple calls to AppLayerParserParse
|
||||
* because some parts of the code are only reached after
|
||||
* multiple packets (in SMTP for example).
|
||||
* So we treat our input as a list of buffers with magic separator.
|
||||
*/
|
||||
albuffer = data + HEADER_LEN;
|
||||
alsize = size - HEADER_LEN;
|
||||
uint8_t flags = STREAM_START;
|
||||
int flip = 0;
|
||||
alnext = memmem(albuffer, alsize, separator, 4);
|
||||
while (alnext) {
|
||||
if (flip) {
|
||||
flags |= STREAM_TOCLIENT;
|
||||
flags &= ~(STREAM_TOSERVER);
|
||||
flip = 0;
|
||||
} else {
|
||||
flags |= STREAM_TOSERVER;
|
||||
flags &= ~(STREAM_TOCLIENT);
|
||||
flip = 1;
|
||||
}
|
||||
|
||||
if (alnext != albuffer) {
|
||||
// only if we have some data
|
||||
isolatedBuffer = malloc(alnext - albuffer);
|
||||
if (isolatedBuffer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(isolatedBuffer, albuffer, alnext - albuffer);
|
||||
(void) AppLayerParserParse(NULL, alp_tctx, f, f->alproto, flags, isolatedBuffer, alnext - albuffer);
|
||||
free(isolatedBuffer);
|
||||
flags &= ~(STREAM_START);
|
||||
}
|
||||
alsize -= alnext - albuffer + 4;
|
||||
albuffer = alnext + 4;
|
||||
if (alsize == 0) {
|
||||
break;
|
||||
}
|
||||
alnext = memmem(albuffer, alsize, separator, 4);
|
||||
}
|
||||
if (alsize > 0 ) {
|
||||
flags |= STREAM_EOF;
|
||||
isolatedBuffer = malloc(alsize);
|
||||
if (isolatedBuffer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(isolatedBuffer, albuffer, alsize);
|
||||
(void) AppLayerParserParse(NULL, alp_tctx, f, f->alproto, flags, isolatedBuffer, alsize);
|
||||
free(isolatedBuffer);
|
||||
}
|
||||
|
||||
FlowFree(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Philippe Antoine <contact@catenacyber.fr>
|
||||
* fuzz target for AppLayerProtoDetectGetProto
|
||||
*/
|
||||
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "app-layer-detect-proto.h"
|
||||
#include "flow-util.h"
|
||||
#include "app-layer-parser.h"
|
||||
#include "util-unittest-helper.h"
|
||||
|
||||
|
||||
#define HEADER_LEN 6
|
||||
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
|
||||
AppLayerProtoDetectThreadCtx *alpd_tctx = NULL;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
Flow *f;
|
||||
TcpSession ssn;
|
||||
bool reverse;
|
||||
|
||||
if (size < HEADER_LEN) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (alpd_tctx == NULL) {
|
||||
//global init
|
||||
InitGlobal();
|
||||
run_mode = RUNMODE_UNITTEST;
|
||||
MpmTableSetup();
|
||||
SpmTableSetup();
|
||||
AppLayerProtoDetectSetup();
|
||||
AppLayerParserSetup();
|
||||
AppLayerParserRegisterProtocolParsers();
|
||||
alpd_tctx = AppLayerProtoDetectGetCtxThread();
|
||||
}
|
||||
|
||||
f = UTHBuildFlow(AF_INET, "1.2.3.4", "5.6.7.8", (data[2] << 8) | data[3], (data[4] << 8) | data[5]);
|
||||
if (f == NULL) {
|
||||
return 0;
|
||||
}
|
||||
f->proto = data[1];
|
||||
memset(&ssn, 0, sizeof(TcpSession));
|
||||
f->protoctx = &ssn;
|
||||
f->protomap = FlowGetProtoMapping(f->proto);
|
||||
|
||||
AppLayerProtoDetectGetProto(alpd_tctx, f, data+HEADER_LEN, size-HEADER_LEN, f->proto, data[0], &reverse);
|
||||
UTHFreeFlow(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Philippe Antoine <contact@catenacyber.fr>
|
||||
* fuzz target for ConfYamlLoadString
|
||||
*/
|
||||
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "conf-yaml-loader.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
if (initialized == 0) {
|
||||
//Redirects logs to /dev/null
|
||||
setenv("SC_LOG_OP_IFACE", "file", 0);
|
||||
setenv("SC_LOG_FILE", "/dev/null", 0);
|
||||
//global init
|
||||
InitGlobal();
|
||||
run_mode = RUNMODE_UNITTEST;
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
ConfYamlLoadString((const char *) data, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Philippe Antoine <contact@catenacyber.fr>
|
||||
* fuzz target for DecodeDer
|
||||
*/
|
||||
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "util-decode-der.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
if (initialized == 0) {
|
||||
//Redirects logs to /dev/null
|
||||
setenv("SC_LOG_OP_IFACE", "file", 0);
|
||||
setenv("SC_LOG_FILE", "/dev/null", 0);
|
||||
//global init
|
||||
InitGlobal();
|
||||
run_mode = RUNMODE_UNITTEST;
|
||||
initialized = 1;
|
||||
}
|
||||
uint32_t errcode = 0;
|
||||
|
||||
Asn1Generic *a = DecodeDer(data, size, &errcode);
|
||||
DerFree(a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Philippe Antoine <contact@catenacyber.fr>
|
||||
* fuzz target for AppLayerProtoDetectGetProto
|
||||
*/
|
||||
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "app-layer-detect-proto.h"
|
||||
#include "defrag.h"
|
||||
#include "tm-modules.h"
|
||||
#include "tm-threads.h"
|
||||
#include "source-pcap-file.h"
|
||||
#include "util-unittest-helper.h"
|
||||
#include "conf-yaml-loader.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
|
||||
static int initialized = 0;
|
||||
SCInstance suricata;
|
||||
|
||||
const char configNoChecksum[] = "\
|
||||
%YAML 1.1\n\
|
||||
---\n\
|
||||
pcap-file:\n\
|
||||
\n\
|
||||
checksum-checks: no\n\
|
||||
";
|
||||
|
||||
ThreadVars *tv;
|
||||
DecodeThreadVars *dtv;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
void *ptv = NULL;
|
||||
|
||||
if (initialized == 0) {
|
||||
//Redirects logs to /dev/null
|
||||
setenv("SC_LOG_OP_IFACE", "file", 0);
|
||||
setenv("SC_LOG_FILE", "/dev/null", 0);
|
||||
|
||||
InitGlobal();
|
||||
run_mode = RUNMODE_PCAP_FILE;
|
||||
|
||||
//redirect logs to /tmp
|
||||
ConfigSetLogDirectory("/tmp/");
|
||||
//disables checksums validation for fuzzing
|
||||
if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
|
||||
abort();
|
||||
}
|
||||
|
||||
PostConfLoadedSetup(&suricata);
|
||||
|
||||
RunModeInitialize();
|
||||
TimeModeSetOffline();
|
||||
PcapFileGlobalInit();
|
||||
|
||||
tv = TmThreadCreatePacketHandler("fuzz",
|
||||
"packetpool", "packetpool",
|
||||
"packetpool", "packetpool",
|
||||
"pktacqloop");
|
||||
if (tv == NULL) {
|
||||
return 0;
|
||||
}
|
||||
TmModule *tm_module = TmModuleGetByName("ReceivePcapFile");
|
||||
if (tm_module == NULL) {
|
||||
return 0;
|
||||
}
|
||||
TmSlotSetFuncAppend(tv, tm_module, "/tmp/fuzz.pcap");
|
||||
tm_module = TmModuleGetByName("DecodePcapFile");
|
||||
if (tm_module == NULL) {
|
||||
return 0;
|
||||
}
|
||||
TmSlotSetFuncAppend(tv, tm_module, NULL);
|
||||
tmm_modules[TMM_DECODEPCAPFILE].ThreadInit(tv, NULL, (void **) &dtv);
|
||||
(void)SC_ATOMIC_SET(tv->tm_slots->slot_next->slot_data, dtv);
|
||||
|
||||
PacketPoolInit();
|
||||
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
//rewrite buffer to a file as libpcap does not have buffer inputs
|
||||
if (UTHbufferToFile("/tmp/fuzz.pcap", data, size) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tmm_modules[TMM_RECEIVEPCAPFILE].ThreadInit(tv, "/tmp/fuzz.pcap", &ptv) == TM_ECODE_OK && ptv != NULL) {
|
||||
suricata_ctl_flags = 0;
|
||||
tmm_modules[TMM_RECEIVEPCAPFILE].PktAcqLoop(tv, ptv, tv->tm_slots);
|
||||
tmm_modules[TMM_RECEIVEPCAPFILE].ThreadDeinit(tv, ptv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Philippe Antoine <contact@catenacyber.fr>
|
||||
* fuzz target for ConfYamlLoadString
|
||||
*/
|
||||
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "util-decode-mime.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
|
||||
static int initialized = 0;
|
||||
static int dummy = 0;
|
||||
|
||||
static int MimeParserDataFromFileCB(const uint8_t *chunk, uint32_t len,
|
||||
MimeDecParseState *state)
|
||||
{
|
||||
if (len > 0 && chunk[len-1] == 0) {
|
||||
// do not get optimizd away
|
||||
dummy++;
|
||||
}
|
||||
return MIME_DEC_OK;
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
if (initialized == 0) {
|
||||
//Redirects logs to /dev/null
|
||||
setenv("SC_LOG_OP_IFACE", "file", 0);
|
||||
setenv("SC_LOG_FILE", "/dev/null", 0);
|
||||
//global init
|
||||
InitGlobal();
|
||||
run_mode = RUNMODE_UNITTEST;
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
uint32_t line_count = 0;
|
||||
|
||||
MimeDecParseState *state = MimeDecInitParser(&line_count, MimeParserDataFromFileCB);
|
||||
MimeDecEntity *msg_head = state->msg;
|
||||
const uint8_t * buffer = data;
|
||||
while (1) {
|
||||
uint8_t * next = memchr(buffer, '\n', size);
|
||||
if (next == NULL) {
|
||||
(void) MimeDecParseLine(buffer, size, 1, state);
|
||||
break;
|
||||
} else {
|
||||
(void) MimeDecParseLine(buffer, next - buffer, 1, state);
|
||||
if (buffer + size < next + 1) {
|
||||
break;
|
||||
}
|
||||
size -= next - buffer + 1;
|
||||
buffer = next + 1;
|
||||
}
|
||||
}
|
||||
/* Completed */
|
||||
(void)MimeDecParseComplete(state);
|
||||
/* De Init parser */
|
||||
MimeDecDeInitParser(state);
|
||||
MimeDecFreeEntity(msg_head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Philippe Antoine <contact@catenacyber.fr>
|
||||
* fuzz target for SigInit
|
||||
*/
|
||||
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "util-reference-config.h"
|
||||
#include "util-classification-config.h"
|
||||
#include "detect-engine.h"
|
||||
#include "detect-parse.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
|
||||
DetectEngineCtx *de_ctx = NULL;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
if (de_ctx == NULL) {
|
||||
setenv("SC_LOG_OP_IFACE", "file", 0);
|
||||
setenv("SC_LOG_FILE", "/dev/null", 0);
|
||||
//global init
|
||||
InitGlobal();
|
||||
run_mode = RUNMODE_UNITTEST;
|
||||
MpmTableSetup();
|
||||
SpmTableSetup();
|
||||
SigTableSetup();
|
||||
SCReferenceConfInit();
|
||||
SCClassConfInit();
|
||||
de_ctx = DetectEngineCtxInit();
|
||||
}
|
||||
|
||||
char * buffer = malloc(size+1);
|
||||
if (buffer) {
|
||||
memcpy(buffer, data, size);
|
||||
//null terminate string
|
||||
buffer[size] = 0;
|
||||
Signature *s = SigInit(de_ctx, buffer);
|
||||
free(buffer);
|
||||
SigFree(s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,179 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Philippe Antoine <contact@catenacyber.fr>
|
||||
* fuzz target for AppLayerProtoDetectGetProto
|
||||
*/
|
||||
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "source-pcap-file.h"
|
||||
#include "detect-engine.h"
|
||||
#include "util-classification-config.h"
|
||||
#include "util-reference-config.h"
|
||||
#include "app-layer.h"
|
||||
#include "tm-queuehandlers.h"
|
||||
#include "util-cidr.h"
|
||||
#include "util-proto-name.h"
|
||||
#include "detect-engine-tag.h"
|
||||
#include "detect-engine-threshold.h"
|
||||
#include "host-bit.h"
|
||||
#include "ippair-bit.h"
|
||||
#include "app-layer-htp.h"
|
||||
#include "util-decode-asn1.h"
|
||||
#include "detect-fast-pattern.h"
|
||||
#include "util-unittest-helper.h"
|
||||
#include "conf-yaml-loader.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
|
||||
|
||||
static int initialized = 0;
|
||||
ThreadVars tv;
|
||||
DecodeThreadVars *dtv;
|
||||
//FlowWorkerThreadData
|
||||
void *fwd;
|
||||
SCInstance suricata;
|
||||
|
||||
const char configNoChecksum[] = "\
|
||||
%YAML 1.1\n\
|
||||
---\n\
|
||||
pcap-file:\n\
|
||||
\n\
|
||||
checksum-checks: no\n\
|
||||
\n\
|
||||
stream:\n\
|
||||
\n\
|
||||
checksum-validation: no\n\
|
||||
";
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
pcap_t * pkts;
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
const u_char *pkt;
|
||||
struct pcap_pkthdr *header;
|
||||
int r;
|
||||
Packet *p;
|
||||
size_t pos;
|
||||
|
||||
if (initialized == 0) {
|
||||
//Redirects logs to /dev/null
|
||||
setenv("SC_LOG_OP_IFACE", "file", 0);
|
||||
setenv("SC_LOG_FILE", "/dev/null", 0);
|
||||
|
||||
InitGlobal();
|
||||
|
||||
run_mode = RUNMODE_PCAP_FILE;
|
||||
//redirect logs to /tmp
|
||||
ConfigSetLogDirectory("/tmp/");
|
||||
//disables checksums validation for fuzzing
|
||||
if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
|
||||
abort();
|
||||
}
|
||||
suricata.sig_file = strdup("/tmp/fuzz.rules");
|
||||
suricata.sig_file_exclusive = 1;
|
||||
//loads rules after init
|
||||
suricata.delayed_detect = 1;
|
||||
|
||||
SupportFastPatternForSigMatchTypes();
|
||||
PostConfLoadedSetup(&suricata);
|
||||
|
||||
//dummy init before DetectEngineReload
|
||||
DetectEngineCtx * de_ctx = DetectEngineCtxInit();
|
||||
de_ctx->flags |= DE_QUIET;
|
||||
DetectEngineAddToMaster(de_ctx);
|
||||
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
dtv = DecodeThreadVarsAlloc(&tv);
|
||||
DecodeRegisterPerfCounters(dtv, &tv);
|
||||
tmm_modules[TMM_FLOWWORKER].ThreadInit(&tv, NULL, &fwd);
|
||||
StatsSetupPrivate(&tv);
|
||||
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
/* TODO add yaml config
|
||||
for (pos = 0; pos < size; pos++) {
|
||||
if (data[pos] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ConfYamlLoadString(data, pos) != 0) {
|
||||
return 0;
|
||||
}
|
||||
if (pos < size) {
|
||||
//skip zero
|
||||
pos++;
|
||||
}
|
||||
data += pos;
|
||||
size -= pos;*/
|
||||
|
||||
for (pos=0; pos < size; pos++) {
|
||||
if (data[pos] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos > 0 && pos < size) {
|
||||
// dump signatures to a file so as to reuse SigLoadSignatures
|
||||
if (UTHbufferToFile(suricata.sig_file, data, pos-1) < 0) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (UTHbufferToFile(suricata.sig_file, data, pos) < 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (DetectEngineReload(&suricata) < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (pos < size) {
|
||||
//skip zero
|
||||
pos++;
|
||||
}
|
||||
data += pos;
|
||||
size -= pos;
|
||||
|
||||
//rewrite buffer to a file as libpcap does not have buffer inputs
|
||||
if (UTHbufferToFile("/tmp/fuzz.pcap", data, size) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//initialize structure
|
||||
pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
|
||||
if (pkts == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//loop over packets
|
||||
r = pcap_next_ex(pkts, &header, &pkt);
|
||||
p = PacketGetFromAlloc();
|
||||
p->datalink = pcap_datalink(pkts);
|
||||
while (r > 0) {
|
||||
PacketCopyData(p, pkt, header->caplen);
|
||||
//DecodePcapFile
|
||||
TmEcode ecode = tmm_modules[TMM_DECODEPCAPFILE].Func(&tv, p, dtv);
|
||||
if (ecode == TM_ECODE_FAILED) {
|
||||
break;
|
||||
}
|
||||
Packet *extra_p = PacketDequeueNoLock(&tv.decode_pq);
|
||||
while (extra_p != NULL) {
|
||||
PacketFree(extra_p);
|
||||
extra_p = PacketDequeueNoLock(&tv.decode_pq);
|
||||
}
|
||||
tmm_modules[TMM_FLOWWORKER].Func(&tv, p, fwd);
|
||||
extra_p = PacketDequeueNoLock(&tv.decode_pq);
|
||||
while (extra_p != NULL) {
|
||||
PacketFree(extra_p);
|
||||
extra_p = PacketDequeueNoLock(&tv.decode_pq);
|
||||
}
|
||||
r = pcap_next_ex(pkts, &header, &pkt);
|
||||
}
|
||||
//close structure
|
||||
pcap_close(pkts);
|
||||
PacketFree(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
FILE * fp;
|
||||
uint8_t *data;
|
||||
size_t size;
|
||||
|
||||
if (argc != 2) {
|
||||
return 1;
|
||||
}
|
||||
//opens the file, get its size, and reads it into a buffer
|
||||
fp = fopen(argv[1], "rb");
|
||||
if (fp == NULL) {
|
||||
return 2;
|
||||
}
|
||||
if (fseek(fp, 0L, SEEK_END) != 0) {
|
||||
fclose(fp);
|
||||
return 2;
|
||||
}
|
||||
size = ftell(fp);
|
||||
if (size == (size_t) -1) {
|
||||
fclose(fp);
|
||||
return 2;
|
||||
}
|
||||
if (fseek(fp, 0L, SEEK_SET) != 0) {
|
||||
fclose(fp);
|
||||
return 2;
|
||||
}
|
||||
data = malloc(size);
|
||||
if (data == NULL) {
|
||||
fclose(fp);
|
||||
return 2;
|
||||
}
|
||||
if (fread(data, size, 1, fp) != 1) {
|
||||
fclose(fp);
|
||||
free(data);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//lauch fuzzer
|
||||
LLVMFuzzerTestOneInput(data, size);
|
||||
free(data);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue