# defcamp 2015 quals r100

Let's take a look at the binary:

```
$    file r100
r100: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.24, BuildID[sha1]=0f464824cc8ee321ef9a80a799c70b1b6aec8168, stripped
$    pwn checksec r100
[*] '/Hackery/pod/modules/angr/defcamp_r100/r100'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
$    ./r100
Enter the [CREDENTIAL_REDACTED]
Incorrect password!
```

So we can see we are dealing with a `64` bit binary, that when we run it, it prompts us for input via `stdin`. When we take a look at the binary in Ghidra, we see this function at `0x4007e8`:

```
undefined8 promptPassword(void)

{
  long lVar1;
  int check;
  char *bytesRead;
  undefined8 passedCheck;
  long in_FS_OFFSET;
  char input [264];
  long canary;
 
  lVar1 = *(long *)(in_FS_OFFSET + 0x28);
  printf("Enter the password: ");
  bytesRead = fgets(input,0xff,stdin);
  if (bytesRead == (char *)0x0) {
    passedCheck = 0;
  }
  else {
    check = checkInput(input);
    if (check == 0) {
      puts("Nice!");
      passedCheck = 0;
    }
    else {
      puts("Incorrect password!");
      passedCheck = 1;
    }
  }
  if (lVar1 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return passedCheck;
}
```

So we can see it first calls `printf` to prompt us for a password. It will then scan in at most `0xff` bytes into `input`. Provided that the `fgets` call actually scanned any bytes in, it will run `input` through the `checkInput` function. If it returns `0` then we solved the challenge. Looking at the `checkInput` function we see this:

```
undefined8 checkInput(long input)

{
  int i;
  long local_28 [4];
 
  i = 0;
  while( true ) {
    if (0xb < i) {
      return 0;
    }
    if ((int)*(char *)((long)((i / 3) * 2) + local_28[(long)(i % 3)]) -
        (int)*(char *)(input + (long)i) != 1) break;
    i = i + 1;
  }
  return 1;
}
```

So we can see here, the code enters into a `while (true)` loop. Each iteration it will take our input and evaluates it. If it passes the check, it will then move on to the next iteration. If there are more than `0xc` iterations of the loop, the function will return `0` meaning that we solved the challenge. If it fails one of the iteration checks, it will return `1` meaning that our input isn't valid.

So we are dealing with a crackme which is a challenge that scans in a piece of data, and evaluates it, and we need to figure out what that data is. We will use Angr to solve this. For Angr we need to know three things. The first is what input we have control over (here it is `0xff` bytes or less via stdin). The second is an instruction address that if it is executed, that means our input was successful (in other words an instruction address along the code path we want to hit). For this I choose `0x4007a1` in `checkInput` where it sets `EAX` (the return value) equal to `0x0`:

```
                             LAB_0040079b                                    XREF[1]:     0040072b(j)  
        0040079b 83 7d dc 0b     CMP        dword ptr [RBP + i],0xb
        0040079f 7e 8c           JLE        LAB_0040072d
        004007a1 b8 00 00        MOV        EAX,0x0
                 00 00
```

That instruction address should only be called when we have the correct input, so it is a good candidate. Now the last piece we need is an instruction address that when it is called, means that our input is not correct. For this I choose `0x400790` which is along the code path if the if then check in `checkInput` fails (specifically when it moves `1` into `EAX` so the return value specifies a failure):

```
        0040078b 83 f8 01        CMP        EAX,0x1
        0040078e 74 07           JZ         LAB_00400797
        00400790 b8 01 00        MOV        EAX,0x1
                 00 00
```

With that, we have everything that we need to make our Angr script:

```
# Import Angr
import angr

# Establish the Angr Project
target = angr.Project('r100')

# Specify the desired address which means we have the correct input
desired_adr = 0x4007a1

# Specify the address which if it executes means we don't have the correct input
wrong_adr = 0x400790

# Establish the entry state
entry_state = target.factory.entry_state(args=["./fairlight"])

# Establish the simulation
simulation = target.factory.simulation_manager(entry_state)

# Start the simulation
simulation.explore(find = desired_adr, avoid = wrong_adr)

solution = simulation.found[0].posix.dumps(0)
print solution
```

When we run it:
```
$    python rev.py
WARNING | 2019-07-21 18:55:53,628 | angr.analyses.disassembly_utils | Your version of capstone does not support MIPS instruction groups.
Code_Talkers�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
$    ./r100
Enter the password: Code_Talkers
Nice!
```

Just like that, we solved the challenge!