Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oss-fuzz initialize #651

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions fuzzer/FUZZER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#### Export flags
```
export CC=clang
export CXX=clang++
export CFLAGS="-fsanitize=fuzzer-no-link,address -g -O2"
export LIB_FUZZING_ENGINE=-fsanitize=fuzzer
```

#### Compile application
```
./autogen.sh
./configure --disable-shared CC="$CC" CFLAGS="$CFLAGS" LDFLAGS="$CFLAGS"
make -j$(nproc)
```

#### Compile Fuzzer
```
cd fuzzer
make all
```

#### Run Fuzzer
```
mkdir coverage
unzip input.zip

FuzzClient coverage/ input/
FuzzServer coverage/ input/
```

#### Bug Reproduce
```
./FuzzClient crash-*
./FuzzServer crash-*
```
150 changes: 150 additions & 0 deletions fuzzer/FuzzClient.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* Copyright © 2008-2022 Stéphane Raimbault <[email protected]>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <modbus.h>
#include "unit-test.h"

#define PORT 8080
#define kMinInputLength 9
#define kMaxInputLength MODBUS_RTU_MAX_ADU_LENGTH

struct Fuzzer{
int socket;
uint16_t port;

uint64_t size;
uint8_t* buffer;

pthread_t thread;
};
typedef struct Fuzzer Fuzzer;

int client(Fuzzer *fuzzer);

void fuzzinit(Fuzzer *fuzzer){
struct sockaddr_in server_addr;
fuzzer->socket = socket(AF_INET, SOCK_STREAM, 0);

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(fuzzer->port);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

setsockopt(fuzzer->socket, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));

bind(fuzzer->socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
listen(fuzzer->socket,1);
}

void *Server(void *args){

Fuzzer *fuzzer = (Fuzzer*)args;
{
int client;
char clientData[10240];
struct sockaddr_in clientAddr;
uint32_t clientSZ = sizeof(clientAddr);

client = accept(fuzzer->socket, (struct sockaddr*)&clientAddr, &clientSZ);

send(client, fuzzer->buffer, fuzzer->size, 0);
recv(client, clientData, sizeof(clientData), 0);

send(client, fuzzer->buffer, fuzzer->size, 0);
recv(client, clientData, sizeof(clientData), 0);

shutdown(client,SHUT_RDWR);
close(client);
}
pthread_exit(NULL);
}

void clean(Fuzzer *fuzzer){
{//Server
shutdown(fuzzer->socket,SHUT_RDWR);
close(fuzzer->socket);
}
free(fuzzer);
}

extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {

if (size < kMinInputLength || size > kMaxInputLength){
return 0;
}

Fuzzer *fuzzer = (Fuzzer*)malloc(sizeof(Fuzzer));
fuzzer->port = PORT;
fuzzer->size = size;
fuzzer->buffer = (uint8_t *)data;

fuzzinit(fuzzer);

pthread_create(&fuzzer->thread, NULL,Server,fuzzer);
client(fuzzer);
pthread_join(fuzzer->thread, NULL);/* To Avoid UAF*/

clean(fuzzer);
return 0;
}

int client(Fuzzer *fuzzer){

uint8_t *tab_rp_bits = NULL;
uint16_t *tab_rp_registers = NULL;
modbus_t *ctx = NULL;
int nb_points;
int rc;

ctx = modbus_new_tcp("127.0.0.1", fuzzer->port);

if (ctx == NULL) {
fprintf(stderr, "Unable to allocate libmodbus context\n");
return -1;
}

if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}

/* Allocate and initialize the memory to store the bits */
nb_points = (UT_BITS_NB > UT_INPUT_BITS_NB) ? UT_BITS_NB : UT_INPUT_BITS_NB;
tab_rp_bits = (uint8_t *) malloc(nb_points * sizeof(uint8_t));
memset(tab_rp_bits, 0, nb_points * sizeof(uint8_t));

/* Allocate and initialize the memory to store the registers */
nb_points = (UT_REGISTERS_NB > UT_INPUT_REGISTERS_NB) ?
UT_REGISTERS_NB : UT_INPUT_REGISTERS_NB;
tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t));
memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));

//Read
rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, UT_BITS_NB, tab_rp_bits);

rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
UT_REGISTERS_NB, tab_rp_registers);

/* Free the memory */
free(tab_rp_bits);
free(tab_rp_registers);

/* Close the connection */
modbus_close(ctx);
modbus_free(ctx);

return rc;
}
133 changes: 133 additions & 0 deletions fuzzer/FuzzServer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright © 2008-2022 Stéphane Raimbault <[email protected]>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <stddef.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

#include <modbus.h>
#include "unit-test.h"

#define PORT 8080
#define kMinInputLength 9
#define kMaxInputLength MODBUS_RTU_MAX_ADU_LENGTH

struct Fuzzer{
int socket;
uint16_t port;

uint64_t size;
uint8_t* buffer;

pthread_t thread;
};
typedef struct Fuzzer Fuzzer;

int server(Fuzzer *fuzzer);

void *client(void *args){

Fuzzer *fuzzer = (Fuzzer*)args;
int sockfd;
struct sockaddr_in serv_addr;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(fuzzer->port);
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

while(1){/* Try until connect*/
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
continue;
}else{
break;
}
}

send(sockfd,fuzzer->buffer,fuzzer->size,0);

close(sockfd);
pthread_exit(NULL);
}

extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {

if (size < kMinInputLength || size > kMaxInputLength){
return 0;
}

Fuzzer *fuzzer = (Fuzzer*)malloc(sizeof(Fuzzer));
fuzzer->port = PORT;

fuzzer->size = size;
fuzzer->buffer = (uint8_t *)data;

pthread_create(&fuzzer->thread, NULL,client,fuzzer);
server(fuzzer);
pthread_join(fuzzer->thread, NULL); /* Avoid UAF*/

free(fuzzer);
return 0;
}

int server(Fuzzer *fuzzer)
{
int s = -1;
modbus_t *ctx;
modbus_mapping_t *mb_mapping;
int rc;
int i;
uint8_t *query;

ctx = modbus_new_tcp("127.0.0.1", fuzzer->port);
query = malloc(MODBUS_TCP_MAX_ADU_LENGTH);

mb_mapping = modbus_mapping_new_start_address(
UT_BITS_ADDRESS, UT_BITS_NB,
UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB,
UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_MAX,
UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB);
if (mb_mapping == NULL) {
fprintf(stderr, "Failed to allocate the mapping: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return -1;
}

/* Initialize input values that's can be only done server side. */
modbus_set_bits_from_bytes(mb_mapping->tab_input_bits, 0, UT_INPUT_BITS_NB,
UT_INPUT_BITS_TAB);

/* Initialize values of INPUT REGISTERS */
for (i=0; i < UT_INPUT_REGISTERS_NB; i++) {
mb_mapping->tab_input_registers[i] = UT_INPUT_REGISTERS_TAB[i];
}

s = modbus_tcp_listen(ctx, 1);
modbus_tcp_accept(ctx, &s);

rc = modbus_receive(ctx, query);

if (s != -1) {
close(s);
}

modbus_mapping_free(mb_mapping);
free(query);
/* For RTU */
modbus_close(ctx);
modbus_free(ctx);

return rc;
}
26 changes: 26 additions & 0 deletions fuzzer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
TARGET=Fuzzer

CLIENTEXE=FuzzClient
SERVEREXE=FuzzServer

INC=-I../src/
LIB=../src/libmodbus.la
EXTCFLAGS= -Wall -Wextra
LIBTOOL=libtool --mode=link --tag=CXX

all: $(TARGET)

CPFILE:
cp ../tests/unit-test.h .

$(TARGET): CPFILE
$(CC) $(EXTCFLAGS) $(CFLAGS) $(INC) -c $(CLIENTEXE).c
$(CC) $(EXTCFLAGS) $(CFLAGS) $(INC) -c $(SERVEREXE).c

$(LIBTOOL) $(CXX) $(LDFLAGS) $(CFLAGS) $(LIB) $(LIB_FUZZING_ENGINE) $(CLIENTEXE).o -o $(CLIENTEXE)
$(LIBTOOL) $(CXX) $(LDFLAGS) $(CFLAGS) $(LIB) $(LIB_FUZZING_ENGINE) $(SERVEREXE).o -o $(SERVEREXE)

clean:
rm $(CLIENTEXE) $(SERVEREXE) *.o

.PHONY: all clean
Binary file added fuzzer/input.zip
Binary file not shown.