Skip to content

Latest commit

 

History

History

labyrinth

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

Labyrinth (easy)

This challenge involves exploiting a simple buffer overflow and then redirecting execution to a different function.

First we check the protections the binary has, using checksec

    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
    RUNPATH:  b'./glibc/'

Pretty much nothing, there's no canary and no ASLR.

Loading the binary into Ghidra, I analyzed the main function.

undefined8 main(void)

{
  int iVar1;
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined8 local_20;
  char *local_18;
  ulong local_10;
  
  setup();
  banner();
  local_38 = 0;
  local_30 = 0;
  local_28 = 0;
  local_20 = 0;
  fwrite("\nSelect door: \n\n",1,0x10,stdout);
  for (local_10 = 1; local_10 < 0x65; local_10 = local_10 + 1) {
    if (local_10 < 10) {
      fprintf(stdout,"Door: 00%d ",local_10);
    }
    else if (local_10 < 100) {
      fprintf(stdout,"Door: 0%d ",local_10);
    }
    else {
      fprintf(stdout,"Door: %d ",local_10);
    }
    if ((local_10 % 10 == 0) && (local_10 != 0)) {
      putchar(10);
    }
  }
  fwrite(&DAT_0040248f,1,4,stdout);
  local_18 = (char *)malloc(0x10);
  fgets(local_18,5,stdin);
  iVar1 = strncmp(local_18,"69",2);
  if (iVar1 != 0) {
    iVar1 = strncmp(local_18,"069",3);
    if (iVar1 != 0) goto LAB_004015da;
  }
  fwrite("\nYou are heading to open the door but you suddenly see something on the wall:\n\n\"Fly li ke a bird and be free!\"\n\nWould you like to change the door you chose?\n\n>> "
         ,1,0xa0,stdout);
  fgets((char *)&local_38,0x44,stdin);
LAB_004015da:
  fprintf(stdout,"\n%s[-] YOU FAILED TO ESCAPE!\n\n",&DAT_00402541);
  return 0;
}

First, 69 should be provided as a door number, in order to get into the vulnerable path of execution.

Then fgets will read 0x44 bytes into local_38. We see at the top of the function that is has 6 variables on the stack starting from local_38, each is 8 bytes large.

Then we can overwrite the RBP of the calling function and then the return address.

Browsing the list of functions in Ghidra, I found the escape_strategy function, which gives us the flag.

As a final trick, stack alignment was an issue, therefore a ROP gadgets needed to be added to the payload, in order to align the stack pointer to 16 bytes again. To fix alignment a simple ret ROP gadget can be placed. This will just pop the element from the stack and set the program counter to it.

To find the ROP gadget I will use the pwntools functions.

So our payload that gets put on the stack will be:

[48 - padding] + [8 - RBP overwrite] + [8 - ret gadget] + [8 - win function address]

Running solve.py will give us the flag.