Run file and checksec.

$ file fluff
fluff: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=2b14d9e5fb7a6bcac48b5304b5153fc679c3651c, not stripped
$ checksec fluff
[*] '/home/hwkim301/rop_emporium/fluff/fluff'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
    RUNPATH:    b'.'
    Stripped:   No

Load the binary into ghidra.

Here’s the main function.

undefined8 main(void)
{
  pwnme();
  return 0;
}

pwnme doesn’t have much.

void pwnme(void)
{
                      /* WARNING: Bad instruction - Truncating control flow here */
  halt_baddata();
}

There is a usefulFunction in the binary though.

void usefulFunction(void)
{
  print_file("nonexistent");
  return;
}

Below the disassembly of usefulFunction is the questionable_gadgets.

questionable_gadgets

Press d on the ?? to show the disassembly.

Here’s the result.

clean

There are assembly instructions that I’ve never ever seen in my life.

The first unfamiliar instruction is xlat.

Now let’s check for any useful functions in libfluff.so.

Load the shared library into ghidra.

Here’s pwnme.

void pwnme(void)
{
  undefined1 local_28 [32];
  
  setvbuf(_stdout,(char *)0x0,2,0);
  puts("fluff by ROP Emporium");
  puts("x86_64\n");
  memset(local_28,0,0x20);
  puts("You know changing these strings means I have to rewrite my solutions...");
  printf("> ");
  read(0,local_28,0x200);
  puts("Thank you!");
  return;
}

There’s also a print_file function.

void print_file(char *param_1)
{
  char local_38 [40];
  FILE *local_10;
  
  local_10 = (FILE *)0x0;
  local_10 = fopen(param_1,"r");
  if (local_10 == (FILE *)0x0) {
    printf("Failed to open file: %s\n",param_1);
                      /* WARNING: Subroutine does not return */
    exit(1);
  }
  fgets(local_38,0x21,local_10);
  puts(local_38);
  fclose(local_10);
  return;
}