# Csaw 2015 Wyvern

Goal of this challenge is to get the flag, not pop a shell.

Let's take a look at the binary:

```
$    file wyvern
wyvern: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=45f9b5b50d013fe43405dc5c7fe651c91a7a7ee8, not stripped
$    ./wyvern
+-----------------------+
|    Welcome Hero       |
+-----------------------+

[!] Quest: there is a dragon prowling the domain.
    brute strength and magic is our only hope. Test your skill.

Enter the dragon's secret: 15935728

[-] You have failed. The dragon's power, speed and intelligence was greater.
```

So we are dealing with a `64` bit binary, that prompts us for input via stdin. It looks like a normal crackme which scans in data, and checks it.

## Reversing

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

```
undefined8 main(void)

{
  int dragonBattle;
  basic_string local_148 [8];
  basic_string local_140 [24];
  allocator<char> local_128 [8];
  basic_string<char,std--char_traits<char>,std--allocator<char>> local_120 [8];
  allocator input [268];
 
  operator<<<std--char_traits<char>>((basic_ostream *)cout,"+-----------------------+\n");
  operator<<<std--char_traits<char>>((basic_ostream *)cout,"|    Welcome Hero       |\n");
  operator<<<std--char_traits<char>>((basic_ostream *)cout,"+-----------------------+\n\n");
  operator<<<std--char_traits<char>>
            ((basic_ostream *)cout,"[!] Quest: there is a dragon prowling the domain.\n");
  operator<<<std--char_traits<char>>
            ((basic_ostream *)cout,
             "\tbrute strength and magic is our only hope. Test your skill.\n\n");
  operator<<<std--char_traits<char>>((basic_ostream *)cout,"Enter the dragon\'s secret: ");
  fgets((char *)input,0x101,stdin);
  allocator();
                    /* try { // try from 0040e217 to 0040e230 has its CatchHandler @ 0040e2ee */
  basic_string((char *)local_120,input);
  ~allocator(local_128);
                    /* try { // try from 0040e242 to 0040e254 has its CatchHandler @ 0040e30e */
  basic_string(local_140);
                    /* try { // try from 0040e25a to 0040e265 has its CatchHandler @ 0040e322 */
  dragonBattle = start_quest((basic_string)0xc0);
                    /* try { // try from 0040e27f to 0040e2c1 has its CatchHandler @ 0040e30e */
  ~basic_string((basic_string<char,std--char_traits<char>,std--allocator<char>> *)local_140);
  if (dragonBattle == 0x1337) {
    basic_string(local_148);
                    /* try { // try from 0040e2c7 to 0040e2d2 has its CatchHandler @ 0040e347 */
    reward_strength((basic_string)0xb8);
                    /* try { // try from 0040e2d8 to 0040e2e3 has its CatchHandler @ 0040e30e */
    ~basic_string((basic_string<char,std--char_traits<char>,std--allocator<char>> *)local_148);
  }
  else {
                    /* try { // try from 0040e36c to 0040e37e has its CatchHandler @ 0040e30e */
    operator<<<std--char_traits<char>>
              ((basic_ostream *)cout,
               "\n[-] You have failed. The dragon\'s power, speed and intelligence was greater.\n");
  }
  ~basic_string(local_120);
  return 0;
}
```

So we can see that it prompts us for input here:
```
  fgets((char *)input,0x101,stdin);
```

Looking through the code, we can see that it really doesn't do much input checking. It just passes our input to `start_quest`, and checks to see if it's output is `0x1337` (which we will need to figure out how to make that happen to solve this challenge). Also the disassembly shows that our input isn't passed, however that is wrong. We can see that in gdb our input is passed:

```
Breakpoint 1, 0x[PII_REDACTED]40e261 in main ()
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x0               
$rbx   : 0x0               
$rcx   : 0xa[PII_REDACTED]3935  ("5935728\n"?)
$rdx   : 0x0               
$rsp   : 0x00007fffffffdd90  →  0x[PII_REDACTED]000000
$rbp   : 0x00007fffffffdf50  →  0x[PII_REDACTED]40e5b0  →  <__libc_csu_init+0> push r15
$rsi   : 0x00007fffffffde38  →  0x[PII_REDACTED]6236a8  →  "15935728"
$rdi   : 0x00007fffffffde18  →  0x[PII_REDACTED]6236a8  →  "15935728"
$rip   : 0x[PII_REDACTED]40e261  →  <main+321> call 0x404350 <_Z11start_questSs>
$r8    : 0x[PII_REDACTED]6236a8  →  "15935728"
$r9    : 0x00007ffff7a7ff40  →  0x00007ffff7a7ff40  →  [loop detected]
$r10   : 0x6               
$r11   : 0x00007ffff7ebd150  →  <std::basic_string<char,+0> push rbx
$r12   : 0x[PII_REDACTED]4013bb  →  <_start+0> xor ebp, ebp
$r13   : 0x00007fffffffe030  →  0x[PII_REDACTED]000001
$r14   : 0x0               
$r15   : 0x0               
$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 ────
0x00007fffffffdd90│+0x0000: 0x[PII_REDACTED]000000     ← $rsp
0x00007fffffffdd98│+0x0008: 0x[PII_REDACTED]000000
0x00007fffffffdda0│+0x0010: 0x[PII_REDACTED]000000
0x00007fffffffdda8│+0x0018: 0x[PII_REDACTED]000000
0x00007fffffffddb0│+0x0020: 0x[PII_REDACTED]000000
0x00007fffffffddb8│+0x0028: 0x00007fffffffde30  →  0x[PII_REDACTED]000000
0x00007fffffffddc0│+0x0030: 0x00007fffffffde40  →  "15935728"
0x00007fffffffddc8│+0x0038: 0x00007fffffffde40  →  "15935728"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x40e250 <main+304>       call   0x400f20 <_ZNSsC1ERKSs@plt>
     0x40e255 <main+309>       jmp    0x40e25a <main+314>
     0x40e25a <main+314>       lea    rdi, [rbp-0x138]
 →   0x40e261 <main+321>       call   0x404350 <_Z11start_questSs>
   ↳    0x404350 <start_quest(std::string)+0> push   rbp
        0x404351 <start_quest(std::string)+1> mov    rbp, rsp
        0x404354 <start_quest(std::string)+4> push   r15
        0x404356 <start_quest(std::string)+6> push   r14
        0x404358 <start_quest(std::string)+8> push   rbx
        0x404359 <start_quest(std::string)+9> sub    rsp, 0x78
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
_Z11start_questSs (
   $rdi = 0x00007fffffffde18 → 0x[PII_REDACTED]6236a8 → "15935728",
   $rsi = 0x00007fffffffde38 → 0x[PII_REDACTED]6236a8 → "15935728"
)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────