int main ()
{
#ifdef usestubs
  set_debug_traps();
  breakpoint();
#endif

  malloc_stub ();

  /* Initialize ascii_string.  */
  init_string (ascii_string,
               120,
               7, 8, 12,
               10, 13, 9,
               11, 120, 17);
  fill_run (ascii_string, 7, 26, 65);
  fill_run (ascii_string, 33, 26, 97);
  fill_run (ascii_string, 59, 10, 48);

  /* Initialize iso_8859_1_string.  */
  init_string (iso_8859_1_string,
               120,
               7, 8, 12,
               10, 13, 9,
               11, 162, 17);
  fill_run (iso_8859_1_string, 7, 26, 65);
  fill_run (iso_8859_1_string, 33, 26, 97);
  fill_run (iso_8859_1_string, 59, 10, 48);

  /* Initialize ebcdic_us_string.  */
  init_string (ebcdic_us_string,
               167,
               47, 22, 12,
               37, 13, 5,
               11, 74, 17);
  /* In EBCDIC, the upper-case letters are broken into three separate runs.  */
  fill_run (ebcdic_us_string, 7, 9, 193);
  fill_run (ebcdic_us_string, 16, 9, 209);
  fill_run (ebcdic_us_string, 25, 8, 226);
  /* The lower-case letters are, too.  */
  fill_run (ebcdic_us_string, 33, 9, 129);
  fill_run (ebcdic_us_string, 42, 9, 145);
  fill_run (ebcdic_us_string, 51, 8, 162);
  /* The digits, at least, are contiguous.  */
  fill_run (ebcdic_us_string, 59, 10, 240);

  /* Initialize ibm1047_string.  */
  init_string (ibm1047_string,
               167,
               47, 22, 12,
               37, 13, 5,
               11, 74, 17);
  /* In EBCDIC, the upper-case letters are broken into three separate runs.  */
  fill_run (ibm1047_string, 7, 9, 193);
  fill_run (ibm1047_string, 16, 9, 209);
  fill_run (ibm1047_string, 25, 8, 226);
  /* The lower-case letters are, too.  */
  fill_run (ibm1047_string, 33, 9, 129);
  fill_run (ibm1047_string, 42, 9, 145);
  fill_run (ibm1047_string, 51, 8, 162);
  /* The digits, at least, are contiguous.  */
  fill_run (ibm1047_string, 59, 10, 240);

  init_utf32 ();

  myvar = utf_32_string[7];

  return 0;            /* all strings initialized */
}
void gain_code_exec(pid_t remote_pid) {
   malloc_stub();

   ptrace_detach(remote_pid);
   exit(1);
 
   int status;

   // Find remote function adresses for malloc, free, __libc_dlopen_mode
   unsigned long remote_malloc_addr = find_remote_function("libc", find_libc_function("malloc"), remote_pid);
   unsigned long remote_free_addr = find_remote_function("libc", find_libc_function("free"), remote_pid);
   unsigned long remote_dlopen_addr = find_remote_function("libc", find_libc_function("__libc_dlopen_mode"), remote_pid);
   
   // Initialize global regs structs variables
   memset(&_regs_backup, 0, sizeof(struct user_regs_struct));
   memset(&_regs_fiddle, 0, sizeof(struct user_regs_struct));
   ptrace_getregs(remote_pid, &_regs_backup);
   reset_regs_fiddle();

   // Get Addr to write our initial stub to:
   unsigned long free_space_addr = find_free_space_addr(remote_pid);
   
   // Set RIP to addr start (2 byte long start instruction)
   _regs_fiddle.rip = free_space_addr + 2;
   
   // TODO TMP
   // Setup parameters in registers (see malloc_stub definition)
   _regs_fiddle.rbx = 1073741824; // exactly one GB
   _regs_fiddle.rax = remote_malloc_addr;
   
   // Upload registers
   printf("Uploading payload regs\n");
   ptrace_setregs(remote_pid, &_regs_fiddle);
   
   // Figure out stub size
   size_t stub_size = (intptr_t)malloc_stub_end - (intptr_t)malloc_stub;
   
   // Create buffer holdig our stub
   printf("Crafting payload stub\n");
   char* stub_code = malloc(stub_size * sizeof(char));
   memset(stub_code, 0, stub_size * sizeof(char));
   memcpy(stub_code, malloc_stub, stub_size);

   // Backup everything that we'll overwrite in target location
   printf("Backing up data\n");
   char* backup = malloc(stub_size * sizeof(char));
   read_data(remote_pid, free_space_addr, backup, stub_size);
   
   // Write our code to target location
   printf("Uploading payload\n");
   write_data(remote_pid, free_space_addr, stub_code, stub_size);
   
   // Continue execution and wait for int3
   printf("Code injection successfull, executing\n"); 
   ptrace_cont(remote_pid);
   sleep(1);
   printf("Pid returned ... probably\n");
   
   // Reupload old data
   printf("Reuploading old data\n");
   write_data(remote_pid, free_space_addr, backup, stub_size);
   ptrace_setregs(remote_pid, &_regs_backup);
   printf("Reset execution flow, continuing execution");
   
   ptrace_cont(remote_pid);
   
   free(backup);
   free(stub_code);
   
   printf("TMP; HALTING FOR 30 seconds\n");
   sleep(30);
}