Skip to content

Instantly share code, notes, and snippets.

@jaypeche
Created November 2, 2024 20:43
Show Gist options
  • Save jaypeche/6168d75f149adee8b478c70a7a2a2a07 to your computer and use it in GitHub Desktop.
Save jaypeche/6168d75f149adee8b478c70a7a2a2a07 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <clamav.h>
#include <sys/fanotify.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <libnotify/notify.h>
#define QUARANTINE_DIR "/tmp"
#define MONITOR_DIR "/path/to/monitor"
void notify_user(const char *message) {
notify_init("Virus Alert");
NotifyNotification *notification = notify_notification_new("Virus Detected", message, NULL);
notify_notification_show(notification, NULL);
g_object_unref(G_OBJECT(notification));
notify_uninit();
}
void move_to_quarantine(const char *filepath) {
char command[512];
snprintf(command, sizeof(command), "mv %s %s", filepath, QUARANTINE_DIR);
system(command);
}
int main() {
struct cl_engine *engine;
const char *virname;
unsigned long int scanned;
int ret;
struct cl_scan_options options;
struct fanotify_event_metadata *metadata;
int fanotify_fd, file_fd;
char buffer[4096];
// Initialize ClamAV
if (cl_init(CL_INIT_DEFAULT) != CL_SUCCESS) {
fprintf(stderr, "Failed to initialize ClamAV\n");
return 1;
}
engine = cl_engine_new();
if (!engine) {
fprintf(stderr, "Failed to create ClamAV engine\n");
return 1;
}
if (cl_load(cl_retdbdir(), engine, NULL, CL_DB_STDOPT) != CL_SUCCESS) {
fprintf(stderr, "Failed to load ClamAV database\n");
cl_engine_free(engine);
return 1;
}
if (cl_engine_compile(engine) != CL_SUCCESS) {
fprintf(stderr, "Failed to compile ClamAV engine\n");
cl_engine_free(engine);
return 1;
}
// Initialize fanotify
fanotify_fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK, O_RDONLY | O_LARGEFILE);
if (fanotify_fd == -1) {
perror("fanotify_init");
cl_engine_free(engine);
return 1;
}
if (fanotify_mark(fanotify_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, FAN_OPEN_PERM | FAN_EVENT_ON_CHILD, AT_FDCWD, MONITOR_DIR) == -1) {
perror("fanotify_mark");
close(fanotify_fd);
cl_engine_free(engine);
return 1;
}
// Monitor events
while (1) {
ssize_t len = read(fanotify_fd, buffer, sizeof(buffer));
if (len == -1 && errno != EAGAIN) {
perror("read");
break;
}
metadata = (struct fanotify_event_metadata *)buffer;
while (FAN_EVENT_OK(metadata, len)) {
if (metadata->mask & FAN_OPEN_PERM) {
file_fd = open(metadata->fd, O_RDONLY);
if (file_fd == -1) {
perror("open");
close(metadata->fd);
continue;
}
ret = cl_scandesc(file_fd, &virname, &scanned, engine, &options);
if (ret == CL_VIRUS) {
char message[256];
snprintf(message, sizeof(message), "Virus detected: %s", virname);
notify_user(message);
move_to_quarantine(metadata->fd);
}
close(file_fd);
}
close(metadata->fd);
metadata = FAN_EVENT_NEXT(metadata, len);
}
}
close(fanotify_fd);
cl_engine_free(engine);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment