# Hack.lu 2014 Oreo

Let's take a look at the binary and libc:

```
$    pwn checksec oreo
[*] '/Hackery/pod/modules/house_of_spirit/hacklu14_oreo/oreo'
    Arch:     i386-32-little
    RELRO:    No RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
$    file oreo
oreo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.26, BuildID[sha1]=f591eececd05c63140b9d658578aea6c24450f8b, stripped
$    ./libc-2.24.so
GNU C Library (Ubuntu GLIBC 2.24-9ubuntu2.2) stable release version 2.24, by Roland McGrath et al.
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 6.3.0 20170406.
Available extensions:
    crypt add-on version 2.1 by Michael Glad and others
    GNU Libidn by Simon Josefsson
    Native POSIX Threads Library by Ulrich Drepper et al
    BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
$    ./oreo
Welcome to the OREO Original Rifle Ecommerce Online System!

     ,______________________________________
    |_________________,----------._ [____]  -,__  __....-----=====
                   (_(||||||||||||)___________/                   |
                      `----------'   OREO [ ))"-,                   |
                                           ""    `,  _,--....___    |
                                                   `/           """"
    
What would you like to do?

1. Add new rifle
2. Show added rifles
3. Order selected rifles
4. Leave a Message with your Order
5. Show current stats
6. Exit!
Action:
```

So we can see that we are dealing with a `32` bit binary, with a Stack Canary and NX. The libc version we got was `libc-2.24.so`. When we run the binary, we are prompted with a menu.

## Reversing

We can see the function at `0x0804898d` acts as our menu function:

```

void menu(void)

{
  int iVar1;
  undefined4 choice;
  int in_GS_OFFSET;
 
  iVar1 = *(int *)(in_GS_OFFSET + 0x14);
  puts("What would you like to do?\n");
  printf("%u. Add new rifle\n",1);
  printf("%u. Show added rifles\n",2);
  printf("%u. Order selected rifles\n",3);
  printf("%u. Leave a Message with your Order\n",4);
  printf("%u. Show current stats\n",5);
  printf("%u. Exit!\n",6);
LAB_08048a25:
  choice = promptInt();
  switch(choice) {
  case 1:
    addRifles();
    goto LAB_08048a25;
  case 2:
    showRifles();
    goto LAB_08048a25;
  case 3:
    orderRifles();
    goto LAB_08048a25;
  case 4:
    leaveMessage();
    goto LAB_08048a25;
  case 5:
    showStats();
    goto LAB_08048a25;
  case 6:
    break;
  }
  if (iVar1 != *(int *)(in_GS_OFFSET + 0x14)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}
```

Next up we have the `addRifles` function:

```
void addRifles(void)

{
  undefined4 uVar1;
  int in_GS_OFFSET;
  int canary;
 
  uVar1 = ptr;
  canary = *(int *)(in_GS_OFFSET + 0x14);
  ptr = (char *)malloc(0x38);
  if (ptr == (char *)0x0) {
    puts("Something terrible happened!");
  }
  else {
    *(undefined4 *)(ptr + 0x34) = uVar1;
    printf("Rifle name: ");
    fgets(ptr + 0x19,0x38,stdin);
    nullTerminate(ptr + 0x19);
    printf("Rifle description: ");
    fgets(ptr,0x38,stdin);
    nullTerminate(ptr);
    riflesCount = riflesCount + 1;
  }
  if (canary != *(int *)(in_GS_OFFSET + 0x14)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}
```

So we can see a bit here about how the rifles are stored. They are not stored in an array of heap pointers, but rather a linked list. The head of the linked list is stored in the bss variable `ptr` at the address `0x804a288`. New rifles are inserted at the head of the linked list. An actual rifle object has this structure:

```
Size of heap chunk, 0x38
0x00: Rifle Description
0x19: Rilfe Name
0x34: Ptr to next rifle
```

We can see that we have two writes. The first is `0x38` bytes of data at `0x19` offset, and the second is `0x38` bytes from the start of the chunk. Both of these will give us an overflow, at least to the next pointer of the chunk. The first write will actually allow us to overflow outside of our heap chunk. Next up we have `showRifles`:

```
void showRifles(void)

{
  int in_GS_OFFSET;
  int currentPtr;
  int canary;
 
  canary = *(int *)(in_GS_OFFSET + 0x14);
  printf("Rifle to be ordered:\n%s\n","===================================");
  currentPtr = ptr;
  while (currentPtr != 0) {
    printf("Name: %s\n",currentPtr + 0x19);
    printf("Description: %s\n",currentPtr);
    puts("===================================");
    currentPtr = *(int *)(currentPtr + 0x34);
  }
  if (canary != *(int *)(in_GS_OFFSET + 0x14)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}
```

We can see here, this function essentially loops through our linked list and prints the name and description of all of the rifles. Next up we have the `orderRifles` function:

```
void orderRifles(void)

{
  int in_GS_OFFSET;
  void *currentPtr;
  int canary;
  void *newPtr;
 
  canary = *(int *)(in_GS_OFFSET + 0x14);
  currentPtr = ptr;
  if (riflesCount == 0) {
    puts("No rifles to be ordered!");
  }
  else {
    while (currentPtr != (void *)0x0) {
      newPtr = *(void **)((int)currentPtr + 0x34);
      free(currentPtr);
      currentPtr = newPtr;
    }
    ptr = (void *)0x0;
    orders = orders + 1;
    puts("Okay order submitted!");
  }
  if (canary != *(int *)(in_GS_OFFSET + 0x14)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}
```

This function essentially loops through our linked list, and frees all of the heap chunks. It then zeroes out `ptr` and increments the bss variable `orders` stored at `0x0804a2a0`:

```
void leaveMessage(void)

{
  int in_GS_OFFSET;
  int canary;
 
  canary = *(int *)(in_GS_OFFSET + 0x14);
  printf("Enter any notice you\'d like to submit with your order: ");
  fgets(message,0x80,stdin);
  nullTerminate(message);
  if (canary != *(int *)(in_GS_OFFSET + 0x14)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}
```

For this function, we can see that it allows us to scan `0x80` bytes worth of data into the char array pointed to by the bss ptr `message`, located at `0x804a2a8`. We can see confirm this in gdb:

```
gef➤  r
Starting program: /Hackery/pod/modules/house_of_spirit/hacklu14_oreo/oreo
Welcome to the OREO Original Rifle Ecommerce Online System!

     ,______________________________________
    |_________________,----------._ [____]  -,__  __....-----=====
                   (_(||||||||||||)___________/                   |
                      `----------'   OREO [ ))"-