# Securityfest 2019 fairlight

Let's take a look at the binary:

```
$    file fairlight
fairlight: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.24, BuildID[sha1]=382cac0a89b47b48f6e24cdad066e1ac605bd3e5, not stripped
$    ./fairlight
useage: ./keygen code
$    ./fairlight 15935728
NOPE - ACCESS DENIED!
```

So we can see that we are dealing with a `64` bit binary. When we run it, we see that it takes in input through an argument. It appears to be a crackme that scans in input, evaluates it, and if it's write we get the flag. When we take a look at the `main` function in Ghidra, we see this:

```
undefined8 main(int argc,long argv)

{
  size_t inputLen;
  long lVar1;
  undefined8 *puVar2;
  long in_FS_OFFSET;
  undefined8 victory;
  undefined8 local_1b0 [50];
  long canary;
 
  canary = *(long *)(in_FS_OFFSET + 0x28);
  victory = 0;
  lVar1 = 0x31;
  puVar2 = local_1b0;
  while (lVar1 != 0) {
    lVar1 = lVar1 + -1;
    *puVar2 = 0;
    puVar2 = puVar2 + 1;
  }
  if (argc < 2) {
    puts("useage: ./keygen code");
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  inputLen = strlen(*(char **)(argv + 8));
  if (inputLen != 0xe) {
    denied_access();
  }
  strncpy(code,*(char **)(argv + 8),0x28);
  check_0();
  check_1();
  check_2();
  check_3();
  check_4();
  check_5();
  check_6();
  check_7();
  check_8();
  check_9();
  check_10();
  check_11();
  check_12();
  check_13();
  sprintf((char *)&victory,success,code);
  printf("%s",&victory);
  if (canary != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}
```

So we can see that it only takes a single argument (other than the binary's name). It then checks if the length of our input is `0xe` characters (if not it runs `denied_access`). Proceeding that it copies our input to the bss variable `code` located at `0x6030b8`. After that it runs a series of `check` functions that reference our input stored in `code`, to evaluate it to see if it is correct.

So there are two ways I can see us solve this (although there are more). The first is that we go through and reverse all of the `check` functions to see what it actually expects (would probably use Z3 to help with this). The second is we just throw Angr at it. Angr is a binary analysis framework that can do a lot (such as code flow analysis and symbolic execution). We can use it as a symbolic execution engine (which figures out what inputs will execute what parts of the program) to figure out how to solve this challenge.

To use Angr here, we will need three things. The first is what input we have, and how it gets passed to the binary. This we already know, which is `0xe` (`14`) byte char characters passed in as a single argument. The second is the instruction address that we want Angr to reach. While it performs its analysis, it's goal will be to reach this function. For this I chose the `printf("%s",&victory);` call `0x401a6e` since if we hit that code path, it means we passed the check:

```
        00401a6e b8 00 00        MOV        inputLen,0x0
                 00 00
        00401a73 e8 88 eb        CALL       printf                                           int printf(char * __format, ...)
                 ff ff
        00401a78 b8 00 00        MOV        inputLen,0x0
                 00 00
```

Moving on, the last thing we need is an instruction address that if it is executed, then Angr knows that it's input isn't correct. For this, we can see that in all of the `check` functions if the check isn't passed it runs the `denied_access` function:

```
void check_0(void)

{
  rand();
  rand();
  if ((int)code[0] * ((int)code[11] + (int)(char)(code[9] ^ code[5])) + -0xab8 != (int)code[13]) {
    denied_access();
  }
  return;
}
```

So for this address I choose the start of `denied_access` at `0x40074d`. This instruction is part of the code path that is executed when our input is incorrect, so this address would be a good candidate to use:

```
                             **************************************************************
                             *                          FUNCTION                          *
                             **************************************************************
                             undefined denied_access()
             undefined         AL:1           <RETURN>
                             denied_access                                   XREF[17]:    check_0:004008a6(c),
                                                                                          check_1:004009e2(c),
                                                                                          check_2:00400b1f(c),
                                                                                          check_3:00400c5c(c),
                                                                                          check_4:00400d96(c),
                                                                                          check_5:00400ed0(c),
                                                                                          check_6:0040100d(c),
                                                                                          check_7:00401147(c),
                                                                                          check_8:00401284(c),
                                                                                          check_9:004013be(c),
                                                                                          check_10:004014fb(c),
                                                                                          check_11:00401650(c),
                                                                                          check_12:004017a7(c),
                                                                                          check_13:004018fe(c),
                                                                                          main:00401990(c), 00401b60,
                                                                                          00401c68(*)  
        0040074d 55              PUSH       RBP
        0040074e 48 89 e5        MOV        RBP,RSP
        00400751 be a0 30        MOV        ESI=>failure,failure                             = "NOPE - ACCESS DENIED!\n"
                 60 00
```

You can install Angr with pip:
```
$    sudo pip install angr
```

With that we have everything we need to write the Angr Script:

```
# Import angr and claripy
import angr
import claripy

# Establish the angr
target = angr.Project('./fairlight', load_options={"auto_load_libs": False})

# Establish our input as an array of 0xe bytes
inp = claripy.BVS("inp", 0xe*8)

# Establish the entry state, with our input passed in as an argument
entry_state = target.factory.entry_state(args