#    plaidctf 2019 cpp

Let's take a look at the binary, and the libc version:
```
$    file cpp
cpp: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=9ccb6196788d9ba1e[PII_REDACTED]a62549f3bcce8, stripped
$    pwn checksec cpp
[*] '/Hackery/pod/modules/tcache/plaid19_cpp/cpp'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
$    ./libc-2.27.so
GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27.
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 7.3.0.
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
$    ./cpp
1. Add
2. Remove
3. View
4. Exit
Choice:
```

So we can see that we are dealing with a `64` bit binary, with all of the standard binary mitigations. We can also see that the libc version we are dealing with is `libc-2.27` (corresponds to Ubuntu `18.04`). When we run the binary, we can see that we are prompted with a menu to add chunks, remove chunks, view chunks, and exit.

## Reversing

When we start reversing this program, we see that it was written in C++. As such it is a bit of a pain to reverse, so a lot of the reversing was done in gdb (and I didn't fully reverse out everything). First off we see that it prompts us with for our menu option with the promptMenu function in the:

```
      menuOption = promptMenu();
      menuOptionCpy1 = (int)menuOption;
      minus2 = menuOptionCpy1 + -2;
      removeCheck = minus2 == 0;
      if (!removeCheck) break;
```

Time to go through and reverse the rest of the functions.

### Add Option

Looking through the code for the Add option, we see that it prompts us for values for name and buf:

```
      operator<<<std--char_traits<char>>((basic_ostream *)cout,"name: ");
      operator>><char,std--char_traits<char>,std--allocator<char>>
                ((basic_istream *)cin,(basic_string *)&local_f8);
      operator<<<std--char_traits<char>>((basic_ostream *)cout,"buf: ");
```

After that it creates strings for the corresponding values which are stored in the heap. When we look at the data structure for the strings, we can see that it is a pointer to the name accompanied with the length of the string (in this case the name is `sasori` and buf is `deidara`):

```
gef➤  r
Starting program: /Hackery/pod/modules/tcache/plaid19_cpp/cpp
1. Add
2. Remove
3. View
4. Exit
Choice: 1
name: sasori
buf: deidara
Done!
1. Add
2. Remove
3. View
4. Exit
Choice: ^C
Program received signal SIGINT, Interrupt.
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────── registers ────
$rax   : 0xfffffffffffffe00
$rbx   : 0x00007ffff782ea00  →  0x00000000fbad2288
$rcx   : 0x00007ffff7553081  →  0x5777fffff0003d48 ("H="?)
$rdx   : 0x400             
$rsp   : 0x00007fffffffdcb8  →  0x00007ffff74d0148  →  <_IO_file_underflow+296> test rax, rax
$rbp   : 0xd68             
$rsi   : 0x[PII_REDACTED]76a280  →  0x0a[PII_REDACTED]6564 ("deidara"?)
$rdi   : 0x0               
$rip   : 0x00007ffff7553081  →  0x5777fffff0003d48 ("H="?)
$r8    : 0x00007ffff78308c0  →  0x[PII_REDACTED]000000
$r9    : 0x00007ffff7fd8080  →  0x00007ffff7fd8080  →  [loop detected]
$r10   : 0xa               
$r11   : 0x246             
$r12   : 0x00007ffff782a760  →  0x[PII_REDACTED]000000
$r13   : 0x00007ffff782b2a0  →  0x[PII_REDACTED]000000
$r14   : 0x00007ffff782b2a0  →  0x[PII_REDACTED]000000
$r15   : 0x00007fffffffdde0  →  0x000069726f736173 ("sasori"?)
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
───────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffdcb8│+0x0000: 0x00007ffff74d0148  →  <_IO_file_underflow+296> test rax, rax     ← $rsp
0x00007fffffffdcc0│+0x0008: 0x00007ffff782ea00  →  0x00000000fbad2288
0x00007fffffffdcc8│+0x0010: 0x00007ffff782b2a0  →  0x[PII_REDACTED]000000
0x00007fffffffdcd0│+0x0018: 0x00007fffffffdd5b  →  0xdd30c000007fff00
0x00007fffffffdcd8│+0x0020: 0x00007ffff7dd30c0  →  0x00007ffff7dc87b0  →  0x00007ffff7b04aa0  →  <std::ctype<char>::~ctype()+0> mov rax, QWORD PTR [rip+0x2ca0c9]        # 0x7ffff7dceb70
0x00007fffffffdce0│+0x0028: 0x00007fffffffdd94  →  0x2777c30000007fff
0x00007fffffffdce8│+0x0030: 0x00007ffff74d13f2  →  <_IO_default_uflow+50> cmp eax, 0xffffffff
0x00007fffffffdcf0│+0x0038: 0x00007fffffffdd30  →  0x00007fffffffdd80  →  0x00007ffff7dd30c0  →  0x00007ffff7dc87b0  →  0x00007ffff7b04aa0  →  <std::ctype<char>::~ctype()+0> mov rax, QWORD PTR [rip+0x2ca0c9]        # 0x7ffff7dceb70
─────────────────────────────────────────────────────────────── code:x86:64 ────
   0x7ffff7553075 <read+5>         add    BYTE PTR cs:[rbx+0x75c08500], cl
   0x7ffff755307c <read+12>        adc    esi, DWORD PTR [rcx]
   0x7ffff755307e <read+14>        ror    BYTE PTR [rdi], 0x5
 → 0x7ffff7553081 <read+17>        cmp    rax, 0xfffffffffffff000
   0x7ffff7553087 <read+23>        ja     0x7ffff75530e0 <__GI___libc_read+112>
   0x7ffff7553089 <read+25>        repz   ret
   0x7ffff755308b <read+27>        nop    DWORD PTR [rax+rax*1+0x0]
   0x7ffff7553090 <read+32>        push   r12
   0x7ffff7553092 <read+34>        push   rbp
─────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "cpp", stopped, reason: SIGINT
───────────────────────────────────────────────────────────────────── trace ────
[#0] 0x7ffff7553081 → __GI___libc_read(fd=0x0, buf=0x55555576a280, nbytes=0x400)
[#1] 0x7ffff74d0148 → _IO_new_file_underflow(fp=0x7ffff782ea00 <_IO_2_1_stdin_>)
[#2] 0x7ffff74d13f2 → __GI__IO_default_uflow(fp=0x7ffff782ea00 <_IO_2_1_stdin_>)
[#3] 0x7ffff7b3989d → __gnu_cxx::stdio_sync_filebuf<char, std::char_traits<char> >::underflow()()
[#4] 0x7ffff7b4763a → std::istream::sentry::sentry(std::istream&, bool)()
[#5] 0x7ffff7b478ae → std::istream::operator>>(int&)()
[#6] 0x555555555dfe → mov rcx, QWORD PTR [rsp+0x8]
[#7] 0x[PII_REDACTED]d2 → cmp eax, 0x2
[#8] 0x7ffff7464b97 → __libc_start_main(main=0x[PII_REDACTED]90, argc=0x1, argv=0x7fffffffdfa8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdf98)
[#9] 0x[PII_REDACTED]ea → hlt
────────────────────────────────────────────────────────────────────────────────
0x00007ffff7553081 in __GI___libc_read (fd=0x0, buf=0x55555576a280, nbytes=0x400) at ../sysdeps/unix/sysv/linux/read.c:27
27    ../sysdeps/unix/sysv/linux/read.c: No such file or directory.
gef➤  search-pattern sasori
[+] Searching 'sasori' in memory
[+] In '[heap]'(0x[PII_REDACTED]00-0x[PII_REDACTED]00), permission=rw-
  0x55555576a6d0 - 0x55555576a6d6  →   "sasori"