add libaflppdesock

This commit is contained in:
vanhauser-thc
2025-05-25 11:04:00 +02:00
parent be00ea9f00
commit 8c1ab19ebe
4 changed files with 414 additions and 2 deletions

View File

@ -23,10 +23,12 @@
- MacOS aflpp driver compilation fix (-fsanitize=fuzzer implementation)
- Make AFL_DUMP_MAP_SIZE work even if the target has sanitizer issues
- qemuafl:
- better MIPS persistent mode support
- Better MIPS persistent mode support
- afl-cmin:
- new afl-cmin.py which is much faster, will be executed by default via
- New afl-cmin.py which is much faster, will be executed by default via
afl-cmin if it executes successfully (thanks to @kcwu!)
- New desocketing library: utils/libaflppdesock
- Likely works when all other desocketing options fail
### Version ++4.32c (release)

View File

@ -0,0 +1,12 @@
# For cross compilation modify this as needed
#GLIBC_PATH := /path/to/glibc-2.xx/build/local_install
#CROSS_CFLAGS := -mfloat-abi=soft -nostdlib -I$(GLIBC_PATH)/include -L$(GLIBC_PATH)/lib -Wl,-rpath=/lib -Wl,--dynamic-linker=/lib/ld-linux.so.3
all: libaflppdesock.so
libaflppdesock.so: libaflppdesock.c
$(CC) $(CROSS_CFLAGS) -shared -fPIC -o libaflppdesock.so libaflppdesock.c
clean:
rm -f libaflppdesock.so *~ core

View File

@ -0,0 +1,46 @@
# AFL++ TCP desocket library
Other desocketing solutions:
* https://github.com/zardus/preeny (desock and desock2)
* https://github.com/fkie-cad/libdesock
* https://github.com/zyingp/desockmulti
* https://github.com/vanhauser-thc/network-emulator
If these desocket solutions fail, then this one will likely easily work
for you - alass with slightly lower performance.
And it is easy to extend :-)
## Why might this solution work when others do not?
What makes this desocket library special is that only **only** intercepts
`accept()` calls bound to a specified port. Hence any other network stuff
the application does is still working as expected.
## How to use
`AFL_PRELOAD` this library and use the following environment variables:
* `DESOCK_PORT=8080` - required for intercepting incoming connections for fuzzing - sets the TCP port
* `DESOCK_FORK=1` - intercept and prevent forking
* `DESOCK_CLOSE_EXIT=1` - call _exit() when the desocketed file descriptor is `close`d or `shutdown`ed
* `DESOCK_DEBUG=1` - print debug information to `stderr`
** Internals
Currently the library intercepts the following calls:
```
shutdown
close
fork
accept
accept4
listen
bind
setsockopt
getsockopt
getpeername
getsockname
```
`

View File

@ -0,0 +1,352 @@
/* desocket library by Marc "vanHauser" Heuse <vh@thc.org>
*
* Use this library for fuzzing if preeny's desock and desock2 solutions
* do not work for you - these would provide faster performance.
*
*/
// default: file descriptor 0 for stdin
#define FUZZ_INPUT_FD 0
#include <dlfcn.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void *handle;
static bool do_fork, do_close, debug, running;
static int port = -1;
static int listen_fd = -1;
struct myin_addr {
unsigned int s_addr; // IPv4 address in network byte order
};
struct mysockaddr {
unsigned short int sin_family; // Address family: AF_INET
unsigned short int sin_port; // Port number (network byte order)
struct myin_addr sin_addr; // Internet address
char sin_zero[8]; // Padding (unused)
};
#define RTLD_LAZY 0x00001
unsigned short int htons(unsigned short int hostshort) {
return (hostshort << 8) | (hostshort >> 8);
}
static void __get_handle() {
if (!(handle = dlopen("libc.so", RTLD_NOW))) {
if (!(handle = dlopen("libc.so.6", RTLD_NOW))) {
if (!(handle = dlopen("libc-orig.so", RTLD_LAZY))) {
if (!(handle = dlopen("cygwin1.dll", RTLD_LAZY))) {
if (!(handle = dlopen("libc.so", RTLD_NOW))) {
fprintf(stderr, "DESOCK: can not find libc!\n");
exit(-1);
}
}
}
}
}
if (getenv("DESOCK_DEBUG")) { debug = true; }
if (getenv("DESOCK_PORT")) { port = atoi(getenv("DESOCK_PORT")); }
if (getenv("DESOCK_FORK")) { do_fork = true; }
if (getenv("DESOCK_CLOSE_EXIT")) { do_close = true; }
if (debug) fprintf(stderr, "DESOCK: initialized!\n");
}
int (*o_shutdown)(int socket, int how);
int shutdown(int socket, int how) {
if (port != -1 && socket == FUZZ_INPUT_FD && running) {
running = false;
if (do_close) {
if (debug) fprintf(stderr, "DESOCK: exiting\n");
_exit(0);
}
}
if (port == -1 && do_close) {
if (debug) fprintf(stderr, "DESOCK: exiting\n");
_exit(0);
}
if (!handle) { __get_handle(); }
if (!o_shutdown) { o_shutdown = dlsym(handle, "shutdown"); }
return o_shutdown(socket, how);
}
int (*o_close)(int socket);
int close(int socket) {
if (port != -1 && socket == FUZZ_INPUT_FD && running) {
running = false;
if (do_close) {
if (debug) fprintf(stderr, "DESOCK: exiting\n");
_exit(0);
}
}
if (listen_fd != -1 && socket == listen_fd) {
if (debug) fprintf(stderr, "DESOCK: close bind\n");
listen_fd = -1;
}
if (!handle) { __get_handle(); }
if (!o_close) { o_close = dlsym(handle, "close"); }
return o_close(socket);
}
int (*o_fork)(void);
int fork() {
if (do_fork) {
if (debug) fprintf(stderr, "DESOCK: fake fork\n");
return 0;
}
if (!handle) { __get_handle(); }
if (!o_fork) { o_fork = dlsym(handle, "fork"); }
return o_fork();
}
int (*o_accept)(int sockfd, struct mysockaddr *addr,
unsigned long int *addrlen);
int accept(int sockfd, struct mysockaddr *addr, unsigned long int *addrlen) {
if (!handle) { __get_handle(); }
if (!o_accept) { o_accept = dlsym(handle, "accept"); }
if (!running && sockfd == listen_fd) {
if (debug) fprintf(stderr, "DESOCK: intercepted accept on %d\n", sockfd);
if (addr && addrlen) {
// we need to fill this!
memset(addr, 0, *addrlen);
addr->sin_family = 2; // AF_INET
addr->sin_port = htons(1023); // Port 1023 in network byte order
addr->sin_addr.s_addr = 0x0100007f;
}
running = true;
return FUZZ_INPUT_FD;
}
return o_accept(sockfd, addr, addrlen);
}
int accept4(int sockfd, struct mysockaddr *addr, unsigned long int *addrlen,
int flags) {
return accept(sockfd, addr, addrlen); // ignore flags
}
int (*o_listen)(int sockfd, int backlog);
int listen(int sockfd, int backlog) {
if (!handle) { __get_handle(); }
if (!o_listen) { o_listen = dlsym(handle, "listen"); }
if (sockfd == listen_fd) {
if (debug) fprintf(stderr, "DESOCK: intercepted listen on %d\n", sockfd);
return 0;
}
return o_listen(sockfd, backlog);
}
int (*o_bind)(int sockfd, const struct mysockaddr *addr,
unsigned long int addrlen);
int bind(int sockfd, const struct mysockaddr *addr, unsigned long int addrlen) {
if (!handle) { __get_handle(); }
if (!o_bind) { o_bind = dlsym(handle, "bind"); }
if (addr->sin_port == htons(port)) {
if (debug) fprintf(stderr, "DESOCK: intercepted bind on %d\n", sockfd);
listen_fd = sockfd;
return 0;
}
return o_bind(sockfd, addr, addrlen);
}
int (*o_setsockopt)(int sockfd, int level, int optname, const void *optval,
unsigned long int optlen);
int setsockopt(int sockfd, int level, int optname, const void *optval,
unsigned long int optlen) {
if (!handle) { __get_handle(); }
if (!o_setsockopt) { o_setsockopt = dlsym(handle, "setsockopt"); }
if (listen_fd == sockfd) {
if (debug)
fprintf(stderr, "DESOCK: intercepted setsockopt on %d for %d\n", sockfd,
optname);
return 0;
}
return o_setsockopt(sockfd, level, optname, optval, optlen);
}
int (*o_getsockopt)(int sockfd, int level, int optname, void *optval,
unsigned long int *optlen);
int getsockopt(int sockfd, int level, int optname, void *optval,
unsigned long int *optlen) {
if (!handle) { __get_handle(); }
if (!o_getsockopt) { o_getsockopt = dlsym(handle, "getsockopt"); }
if (listen_fd == sockfd) {
if (debug)
fprintf(stderr, "DESOCK: intercepted getsockopt on %d for %d\n", sockfd,
optname);
int *o = (int *)optval;
if (o != NULL) {
*o = 1; // let's hope this is fine
}
return 0;
}
return o_getsockopt(sockfd, level, optname, optval, optlen);
}
int (*o_getpeername)(int sockfd, struct mysockaddr *addr,
unsigned long int *addrlen);
int getpeername(int sockfd, struct mysockaddr *addr,
unsigned long int *addrlen) {
if (!handle) { __get_handle(); }
if (!o_getpeername) { o_getpeername = dlsym(handle, "getpeername"); }
if (port != -1 && sockfd == FUZZ_INPUT_FD) {
if (debug) fprintf(stderr, "DESOCK: getpeername\n");
if (addr && addrlen) {
// we need to fill this!
memset(addr, 0, *addrlen);
addr->sin_family = 2; // AF_INET
addr->sin_port = htons(1023); // Port 1023 in network byte order
addr->sin_addr.s_addr = 0x0100007f;
}
return 0;
}
return o_getpeername(sockfd, addr, addrlen);
}
int (*o_getsockname)(int sockfd, struct mysockaddr *addr,
unsigned long int *addrlen);
int getsockname(int sockfd, struct mysockaddr *addr,
unsigned long int *addrlen) {
if (!handle) { __get_handle(); }
if (!o_getsockname) { o_getsockname = dlsym(handle, "getsockname"); }
if (port != -1 && sockfd == FUZZ_INPUT_FD) {
if (debug) fprintf(stderr, "DESOCK: getsockname\n");
if (addr && addrlen) {
// we need to fill this!
memset(addr, 0, *addrlen);
addr->sin_family = 2; // AF_INET
addr->sin_port = htons(port);
addr->sin_addr.s_addr = 0x0100007f;
}
return 0;
}
return o_getsockname(sockfd, addr, addrlen);
}
static FILE *(*o_fdopen)(int fd, const char *mode);
FILE *fdopen(int fd, const char *mode) {
if (!o_fdopen) {
if (!handle) { __get_handle(); }
o_fdopen = dlsym(handle, "fdopen");
if (!o_fdopen) {
fprintf(stderr, "%s(): can not find fdopen\n", dlerror());
exit(-1);
}
}
if (fd == FUZZ_INPUT_FD && strcmp(mode, "r") != 0) {
if (debug) fprintf(stderr, "DESOCK: intercepted fdopen(r+) for %d\n", fd);
return o_fdopen(fd, "r");
}
return o_fdopen(fd, mode);
}
/* TARGET SPECIFIC HOOKS - put extra needed code for your target here */