Document probing samples

This commit is contained in:
Lucian Petrut
2026-09-08 14:41:24 +00:00
parent f70a1d485e
commit 14ed40548e
7 changed files with 853 additions and 1 deletions
+235
View File
@@ -0,0 +1,235 @@
#define _GNU_SOURCE
#include <dlfcn.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/uio.h>
#include <unistd.h>
static FILE *out;
static pthread_mutex_t log_mu = PTHREAD_MUTEX_INITIALIZER;
static int log_fd = -1;
static int ready;
static ssize_t (*real_write)(int, const void *, size_t);
static ssize_t (*real_read)(int, void *, size_t);
static ssize_t (*real_send)(int, const void *, size_t, int);
static ssize_t (*real_recv)(int, void *, size_t, int);
static ssize_t (*real_writev)(int, const struct iovec *, int);
static ssize_t (*real_readv)(int, const struct iovec *, int);
static ssize_t (*real_sendmsg)(int, const struct msghdr *, int);
static ssize_t (*real_recvmsg)(int, struct msghdr *, int);
static int (*real_ssl_write)(void *, const void *, int);
static int (*real_ssl_read)(void *, void *, int);
static int (*real_ssl_get_fd)(const void *);
__attribute__((constructor))
static void init_syms(void) {
real_write = dlsym(RTLD_NEXT, "write");
real_read = dlsym(RTLD_NEXT, "read");
real_send = dlsym(RTLD_NEXT, "send");
real_recv = dlsym(RTLD_NEXT, "recv");
real_writev = dlsym(RTLD_NEXT, "writev");
real_readv = dlsym(RTLD_NEXT, "readv");
real_sendmsg = dlsym(RTLD_NEXT, "sendmsg");
real_recvmsg = dlsym(RTLD_NEXT, "recvmsg");
real_ssl_write = dlsym(RTLD_NEXT, "SSL_write");
real_ssl_read = dlsym(RTLD_NEXT, "SSL_read");
real_ssl_get_fd = dlsym(RTLD_NEXT, "SSL_get_fd");
const char *path = getenv("SSLHOOK_LOG");
if (!path) {
path = "/tmp/sslhook-write.log";
}
out = fopen(path, "w");
if (!out) {
out = stderr;
}
log_fd = fileno(out);
setvbuf(out, NULL, _IONBF, 0);
ready = 1;
fprintf(out, "hook loaded write=%p ssl_write=%p\n",
(void *)real_write, (void *)real_ssl_write);
}
static int peer_port(int fd) {
struct sockaddr_storage ss;
socklen_t len = sizeof(ss);
if (getpeername(fd, (struct sockaddr *)&ss, &len) != 0) {
return -1;
}
if (ss.ss_family == AF_INET) {
return ntohs(((struct sockaddr_in *)&ss)->sin_port);
}
if (ss.ss_family == AF_INET6) {
return ntohs(((struct sockaddr_in6 *)&ss)->sin6_port);
}
return -1;
}
static void dump(const char *tag, int fd, const void *buf, int num) {
if (!ready || !out || fd == log_fd || num <= 0 || num > 1024 * 1024) {
return;
}
int port = peer_port(fd);
if (port <= 0 || port == 443) {
return;
}
const unsigned char *p = buf;
/* Skip TLS records. */
if (num >= 3 && p[0] == 0x16 && p[1] == 0x03) {
return;
}
if (num >= 3 && p[0] == 0x17 && p[1] == 0x03) {
return;
}
pthread_mutex_lock(&log_mu);
fprintf(out, "\n==== %s fd=%d port=%d %d ====\n", tag, fd, port, num);
for (int i = 0; i < num; i++) {
fprintf(out, "%02x", p[i]);
}
fprintf(out, "\n");
pthread_mutex_unlock(&log_mu);
}
ssize_t write(int fd, const void *buf, size_t count) {
if (real_write == NULL) {
return syscall(SYS_write, fd, buf, count);
}
if (ready && out && fd != log_fd) {
static int nlogged;
if (nlogged < 40) {
fprintf(out, "write fd=%d port=%d n=%zu\n", fd, peer_port(fd), count);
nlogged++;
}
}
dump("WRITE", fd, buf, (int)count);
return real_write(fd, buf, count);
}
ssize_t read(int fd, void *buf, size_t count) {
if (real_read == NULL) {
return syscall(SYS_read, fd, buf, count);
}
ssize_t n = real_read(fd, buf, count);
if (n > 0) {
dump("READ", fd, buf, (int)n);
}
return n;
}
ssize_t send(int fd, const void *buf, size_t len, int flags) {
if (real_send == NULL) {
return syscall(SYS_sendto, fd, buf, len, flags, NULL, 0);
}
dump("SEND", fd, buf, (int)len);
return real_send(fd, buf, len, flags);
}
ssize_t recv(int fd, void *buf, size_t len, int flags) {
if (real_recv == NULL) {
return syscall(SYS_recvfrom, fd, buf, len, flags, NULL, 0);
}
ssize_t n = real_recv(fd, buf, len, flags);
if (n > 0) {
dump("RECV", fd, buf, (int)n);
}
return n;
}
ssize_t writev(int fd, const struct iovec *iov, int iovcnt) {
if (real_writev == NULL) {
return syscall(SYS_writev, fd, iov, iovcnt);
}
size_t total = 0;
for (int i = 0; i < iovcnt; i++) {
total += iov[i].iov_len;
}
if (total > 0 && total <= 1024 * 1024) {
unsigned char *buf = malloc(total);
if (buf) {
size_t off = 0;
for (int i = 0; i < iovcnt; i++) {
memcpy(buf + off, iov[i].iov_base, iov[i].iov_len);
off += iov[i].iov_len;
}
dump("WRITEV", fd, buf, (int)total);
free(buf);
}
}
return real_writev(fd, iov, iovcnt);
}
int SSL_write(void *ssl, const void *buf, int num) {
if (real_ssl_write == NULL) {
real_ssl_write = dlsym(RTLD_NEXT, "SSL_write");
}
int fd = real_ssl_get_fd ? real_ssl_get_fd(ssl) : -1;
dump("SSL_W", fd, buf, num);
return real_ssl_write(ssl, buf, num);
}
int SSL_read(void *ssl, void *buf, int num) {
if (real_ssl_read == NULL) {
real_ssl_read = dlsym(RTLD_NEXT, "SSL_read");
}
int n = real_ssl_read(ssl, buf, num);
if (n > 0) {
int fd = real_ssl_get_fd ? real_ssl_get_fd(ssl) : -1;
dump("SSL_R", fd, buf, n);
}
return n;
}
static void dump_msghdr(const char *tag, int fd, const struct msghdr *msg) {
if (!msg || !msg->msg_iov) {
return;
}
size_t total = 0;
for (size_t i = 0; i < (size_t)msg->msg_iovlen; i++) {
total += msg->msg_iov[i].iov_len;
}
if (total == 0 || total > 1024 * 1024) {
return;
}
unsigned char *buf = malloc(total);
if (!buf) {
return;
}
size_t off = 0;
for (size_t i = 0; i < (size_t)msg->msg_iovlen; i++) {
memcpy(buf + off, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
off += msg->msg_iov[i].iov_len;
}
dump(tag, fd, buf, (int)total);
free(buf);
}
ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
if (real_sendmsg == NULL) {
real_sendmsg = dlsym(RTLD_NEXT, "sendmsg");
}
if (ready && out && fd != log_fd) {
static int nlogged;
if (nlogged < 20) {
fprintf(out, "sendmsg fd=%d port=%d\n", fd, peer_port(fd));
nlogged++;
}
}
dump_msghdr("SENDMSG", fd, msg);
return real_sendmsg(fd, msg, flags);
}
ssize_t recvmsg(int fd, struct msghdr *msg, int flags) {
if (real_recvmsg == NULL) {
real_recvmsg = dlsym(RTLD_NEXT, "recvmsg");
}
ssize_t n = real_recvmsg(fd, msg, flags);
if (n > 0) {
dump_msghdr("RECVMSG", fd, msg);
}
return n;
}