# Defcon Quals 2019 Speedrun 4

Let's take a look at the binary:

```
$    file speedrun-004
speedrun-004: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=3633fdca0065d9365b3f0c0237c7785c2c7ead8f, stripped
$    pwn checksec speedrun-004
[*] '/Hackery/defcon/speedrun/s4/speedrun-004'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
$ ./speedrun-004
i think i'm getting better at this coding thing.
how much do you have to say?
15935728
That's too much to say!.
see ya later slowpoke.
```

So it is a `64` bit statically linked binary with `NX`. When we run it, it just prompts us for some input via stdin.

## Reversing

Reversing out the binary with Ghidra, we find this function:

```
undefined8
FUN_00400c46(undefined8 uParm1,undefined8 uParm2,undefined8 uParm3,undefined8 uParm4,
            undefined8 uParm5,undefined8 uParm6)

{
  long lVar1;
 
  FUN_00410e30(PTR_DAT_006b97a0,0,2,0,uParm5,uParm6,uParm2);
  lVar1 = FUN_0040e840("DEBUG");
  if (lVar1 == 0) {
    FUN_004498e0(5);
  }
  betterCoding();
  funStuff();
  slowpoke();
  return 0;
}
```

Realistically the part we care about here, is that the `funStuff` function is called. The `betterCoding` and `slowpoke` functions essentially just print text. Looking at the `funStuff` function, we see this:

```

void funStuff(void)

{
  undefined inputSize [9];
  undefined local_d;
  uint size;
 
  print("how much do you have to say?");
  fgets(0,inputSize,9);
  local_d = 0;
  size = atoi(inputSize);
  if ((int)size < 1) {
    print("That\'s not much to say.");
  }
  else {
    if ((int)size < 0x102) {
      scanInput((ulong)size);
    }
    else {
      print("That\'s too much to say!.");
    }
  }
  return;
}
```
In this function it prompts us for an integer, and if it is between 1-257, it will run the `scanInput` function with the integer we gave it as input. Also the `fgets`, `atoi`, and `print` functions I reversed them by just seeing their arguments and what they did (and named them accordingly), I didn't actually confirm that they were the actual functions correspond to. Looking at `scanInput`, we can see a bug.

```
void scanInput(int iParm1)

{
  undefined input [256];
 
  input[0] = 0;
  print("Ok, what do you have to say for yourself?");
  fgets(0,input,(long)iParm1);
  FUN_0040ffb0("Interesting thought \"%s\", I\'ll take it into consideration.\n",input);
  return;
}
```

Here we can see that it is calling `fgets` on the char array `input` which allows us to scan in `size` bytes (the integer we specified earlier). Since we can specify a size up to `0x101` bytes and it is a `0x100` byte space, we have a one byte overflow. Since there is no stack canary and nothing else between `input` and the stack frame, we will have a one byte overflow of the saved base pointer. We will be doing a stack pivot attack.

## Stack Pivot Exploit

Before we talk about this, let's talk about stack frames:

```
+------------+
| stack data |
|      v1    |
|      v2    |   
|    input   |
+------------+
|  base ptr  |
|  insr ptr  |
+------------+
```

The `stack data` represents the various variables that are kept on the stack (for `scanInput` it would be the `v1`, `v2`, and `input` variables). After that you have two saved values for the `base ptr` for the stack and `insr ptr` for the instructions. Thing is when a `call` instruction is made, these two values are placed in the call stack. That way when the function is done and it returns, it can take the saved base ptr and figure out where the stack is, and take the saved instruction pointer and figure out what code to execute.

The thing is, the saved instruction pointer is stored on top of the saved stack. We can see that here in gdb:

```
gef➤  info frame
Stack level 0, frame at 0x7ffe9fd84120:
 rip = 0x400baf; saved rip = 0x400c44
 called by frame at 0x7ffe9fd84140
 Arglist at 0x7ffe9fd83ff8, args:
 Locals at 0x7ffe9fd83ff8, Previous frame's sp is 0x7ffe9fd84120
 Saved registers:
  rbp at 0x7ffe9fd84110, rip at 0x7ffe9fd84118
gef➤  x/2g 0x7ffe9fd84110
0x7ffe9fd84110: 0x7ffe9fd84130  0x400c44
gef➤  x/2i 0x400c44
   0x400c44:  leave  
   0x400c45:  ret  
```

We can see that the saved base pointer is `0x7ffe9fd84110`, which immediately following that is `0x400c44` which is the return instruction. This will be executed as soon as the function returns. However we can see that what it does is runs the `leave` and `ret` instructions. When the second `ret` instruction is executed, it will execute the second qword value on the stack (since there have been no variables allocated on the stack, the first qword is the saved base pointer, and the second is the saved instruction pointer). Thus since we get to overwrite the least significant byte of the saved base pointer, we can decide what pointer gets executed with the second return. We can see that the second return happens right after `scanInput` gets called:

```
        00400c3f e8 2f ff        CALL       scanInput                                        undefined scanInput()
                 ff ff
                             LAB_00400c44                                    XREF[2]:     00400c21(j), 00400c38(j)  
        00400c44 c9              LEAVE
        00400c45 c3              RET
```

Now our input is directly above the base and instruction pointer. Depending on the iteration of the program (since the stack addresses are randomized every time the program runs), we can get the second return instruction to execute a rop chain of ours we inputted on the stack by overwriting the least significant byte with a particular value. Since we don't have an infoleak, I just went with `0x00` (a null byte). I append a ret slide (similar to a nop sled) to the front of the rop chain, that way if execution lands anywhere in there it will just execute return instructions until it starts executing our rop chain. Also when I say ret slide, I mean pointers to the ret instruction, not the ret instructions themselves. Of course doing it this way won't work 100% of the time, however I did get it to work somewhat frequently (like (1/3)-(1/2) of the time). For the ROP Chain it was a pretty standard one to make a syscall to execve, checkout this writeup for more details: https://github.com/guyinatuxedo/ctf/tree/master/defconquals2019/speedrun/s1 (or the static rop chain module)

Here is a quick look at how the memory gets corrupted:

```
────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fff383d4ba0│+0x0000: 0x[PII_REDACTED]000000   ← $rsp
0x00007fff383d4ba8│+0x0008: 0x[PII_REDACTED]000000
0x00007fff383d4bb0│+0x0010: 0x[PII_REDACTED]000000   ← $rax, $rsi
0x00007fff383d4bb8│+0x0018: 0x[PII_REDACTED]00007c ("|"?)
0x00007fff383d4bc0│+0x0020: 0x0000005b0000006e ("n"?)
0x00007fff383d4bc8│+0x0028: 0x00007fff383d4b50  →  0x[PII_REDACTED]000029 (")"?)
0x00007fff383d4bd0│+0x0030: 0