# guestbook

Noopnoop helped with the creation of this writeup.

Let's take a look at the binary:
```
$    file guestbook
guestbook: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=bc73592d4897267cd1097b0541dc571d051a7ca0, not stripped
$    pwn checksec guestbook
[*] '/Hackery/tuctf/guestbook/guestbook'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
```

So we can see that it is 32 bit elf, with a non executable stack and PIE enabled. Let's try running the binary:

```
$    ./guestbook
Please setup your guest book:
Name for guest: #0
>>>00000
Name for guest: #1
>>>11111
Name for guest: #2
>>>22222
Name for guest: #3
>>>33333
---------------------------
1: View name
2: Change name
3. Quit
>>2
Which entry do you want to change?
>>>1
Enter the name of the new guest.
>>>15935

---------------------------
1: View name
2: Change name
3. Quit
>>1
Which entry do you want to view?
>>>1
15935
---------------------------
1: View name
2: Change name
3. Quit
>>1
Which entry do you want to view?
>>>6
@RW(DRW@DRWXDRW�I[
`T�
    ���XDRW
---------------------------
1: View name
2: Change name
3. Quit
>>3
```

So it prompts us for four names, then provides us the ability to change or view the names. It appears that when we view the name of something past the four names we have, we get an infoleak. Let's take a look at the code in Ghidra:

## Reversing

Looking at the main function in Ghidra, we see this:

```

/* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */

undefined4 main(void)

{
  char *ptr;
  int iVar1;
  char changeNameInput [100];
  int changeIndex;
  int menuChoice;
  char *ptrArray [4];
  undefined *systemVar;
  int i;
  bool continue;
 
  setvbuf(stdout,(char *)0x0,2,0x14);
  puts("Please setup your guest book:");
  i = 0;
  while (i < 4) {
    printf("Name for guest: #%d\n>>>",i);
    ptr = (char *)malloc(0xf);
    __isoc99_scanf(&DAT_00010ac3,ptr);
    ptr[0xe] = 0;
    ptrArray[i] = ptr;
    i = i + 1;
  }
  continue = true;
LAB_000109b3:
  do {
    if (!continue) {
      return 0;
    }
    do {
      iVar1 = getchar();
      if ((char)iVar1 == '\n') break;
    } while ((char)iVar1 != -1);
    puts("---------------------------");
    puts("1: View name");
    puts("2: Change name");
    puts("3. Quit");
    printf(">>");
    menuChoice = 0;
    __isoc99_scanf(&DAT_00010a75,&menuChoice);
    if (menuChoice != 2) {
      if (menuChoice == 3) {
        continue = false;
      }
      else {
        if (menuChoice == 1) {
          readName((int)ptrArray);
        }
        else {
          puts("Not a valid option. Try again");
        }
      }
      goto LAB_000109b3;
    }
    printf("Which entry do you want to change?\n>>>");
    changeIndex = -1;
    __isoc99_scanf(&DAT_00010a75,&changeIndex);
    if (changeIndex < 0) {
      puts("Enter a valid number");
    }
    else {
      printf("Enter the name of the new guest.\n>>>");
      do {
        iVar1 = getchar();
        if ((char)iVar1 == '\n') break;
      } while ((char)iVar1 != -1);
      gets(changeNameInput);
      strcpy(ptrArray[changeIndex],changeNameInput);
    }
  } while( true );
}
```

Starting off, we can see it allocates four `0xf` byte chunks in the heap, and prompts us to scan in data (the four guest names). It also saves the pointers in the array  `ptrArray`. Proceeding that, we are dropped into a menu where we can either change a name, view a name, or exit. If we choose to view a name, the `readName` function is executed:

```
/* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */

void readName(int ptrArray)

{
  int index;
 
  printf("Which entry do you want to view?\n>>>");
  index = -1;
  __isoc99_scanf(&DAT_00010a75,&index);
  if (index < 0) {
    puts("Enter a valid number");
  }
  else {
    puts(*(char **)(ptrArray + index * 4));
  }
  return;
}
```

So we can see that it prompts us for an index to the array of pointers that it is passed, and it passes that pointer to `puts`. The only check is to make sure that the index it gets is greater than `0`, however there is no check to ensure that we don't print a pointer past the end of the array. This is an index check bug.

Looking at the code for editing a guest's name, we see it has the same index bug:

```
  __isoc99_scanf(&DAT_00010a75,&changeIndex);
    if (changeIndex < 0) {
      puts("Enter a valid number");
    }
```

In addition to that, we can see that there is another bug:

```
      gets(changeNameInput);
      strcpy(ptrArray[changeIndex],changeNameInput);
```

We can see that there is a call to `gets`, so we have a buffer overflow vulnerability. However before that happens, there is a `strcpy` call that uses a pointer which will be overwritten in the overflow (when we look at the stack, we see that it is between the start of our input and the return address). We will need an infoleak to leak a pointer which we can use in the overflow.

In addition to that, because PIE is enabled, the address of `system` (which is imported into the program) should change every time. We will need to get the address of `system` in order to execute a return to `system` attack. Also another thing to take note of, it saves the address of `system` in a stack variable (although for some reason, it isn't showing in the disassembly):

```
        00010857 89 45 ec        MOV        dword ptr [EBP + local_18],ptr
        0001085a 8b 83 e8        MOV        ptr,dword ptr [0xffffffe8 + EBX]=>->system       = 00013020
                 ff ff ff
        00010860 89 45 e8        MOV        dword ptr [EBP + systemVar],ptr=>system          = ??
```

## Exploitation

Our exploit will have two parts. The first is we will use the `readName` function to get an infoleak to both the heap and the libc. The second part will be using the `gets` call to overwrite the return address and get code execution:

#### Infoleak

Let's take a look at the layout of the memory in gdb:

```
gef➤  r
Starting program: /Hackery/pod/modules/ret_2_system/tu_guestbook/guestbook
Please setup your guest book:
Name for guest: #0
>>>15935728
Name for guest: #1
>>>75395128
Name for guest: #2
>>>95135728
Name for guest: #3
>>>35715928
---------------------------
1: View name
2: Change name
3. Quit
>>^C
Program received signal SIGINT, Interrupt.
0xf7fd3939 in __kernel_vsyscall ()
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────── registers ────
$eax   : 0xfffffe00
$ebx   : 0x0       
$ecx   : 0x56558180  →  "35715928"
$edx   : 0x400     
$esp   : 0xffffc998  →  0xffffca10  →  0xffffd070  →  0xffffd138  →  0x00000000
$ebp   : 0xffffca10  →  0xffffd070  →  0xffffd138  →  0x00000000
$esi   : 0xf7fb45c0  →  0xfbad2288
$edi   : 0x0       
$eip   : 0xf7fd3939  →  <__kernel_v