[writeup by @bonaff]
**CTF:** 0x00CTF
**Team:** spritzers (from [SPRITZ Research Group](http://spritz.math.unipd.it/))
**Task:** Reverse / challenge-000 (guessme)
**Points:** 50
>Hi there. Can you find the right key that unlocks the flag?>Platform: 64 bit Linux (developed on Ubuntu)
For this challenge we are given an executable. Running `file` on it gives us the following information:
```textguessme: 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.32, BuildID[sha1]=92b1d84ee22b7c92dc80fac971bdc7f6cd0e3672, stripped ```
Running it:
```$ ./guessmeEnter a key: fooFAIL```
This program as you can see is quite simple:1. It asks for a key;2. If the key is correct it will print the flag.
Decompiling the main function, we can clearly see where it checks if the password is correct or no:
```cinput_key_size = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length(&input_key);  if ( input_key_size == sub_401402(&buffer) )  {    std::operator<<<std::char_traits<char>>(&std::cout, "FAIL\n");    v5 = 1;  }else  {for ( i = 0;          i < (unsigned __int64)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length(&v14);          ++i )    {      v6 = *(char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](&v14, i)         - 97;      if ( v6 == *(_DWORD *)sub_4012D8(&v13, i) )      {        std::operator<<<std::char_traits<char>>(&std::cout, "FAIL\n");        v5 = 2;        goto FAIL;      }    }```
Initially it checks if the key we inserted is of the right length (returned by `sub_401402(&buffer)`).
`buffer` contains our key, and it is generated by this code:
```csub_4011FA(&len, a2, a3);sub_401232((__int64)&buffer, 14LL, (__int64)&len;;sub_401216(&len;;*(_DWORD *)get_buffer_item(&buffer, 13LL) = 233;*(_DWORD *)get_buffer_item(&buffer, 12LL) = 144;len = 11;sub_4010DF(&buffer, &len;;sub_4012F8(&v11, &buffer);while ( 1 ){  sub_401338(&len, &buffer);  if ( !(unsigned __int8)sub_40136C(&v11, &len) )    break;  v3 = (_DWORD *)sub_4013B2(&v11);  *v3 %= 26;  sub_401394(&v11);}```
Since I'm quite lazy, I preferred to run the program, set a break point once our buffer is ready, and then dump it.
First, let's find out how long the key is. Below is the code that performs the check:```.text:0000000000400F51                 lea     rax, [rbp+input_key].text:0000000000400F55                 mov     rdi, rax.text:0000000000400F58                 call    __ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6lengthEv ; std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length(void).text:0000000000400F5D                 mov     rbx, rax.text:0000000000400F60                 lea     rax, [rbp+buffer].text:0000000000400F64                 mov     rdi, rax.text:0000000000400F67                 call    sub_401402.text:0000000000400F6C                 cmp     rbx, rax.text:0000000000400F6F                 setnz   al.text:0000000000400F72                 test    al, al.text:0000000000400F74                 jnz     short loc_400F8F```
`sub_401402` is the function that returns the expected length. Furthermore, it accepts the buffer that contains the password, so let's set a break point and look for what we want:
``` gdb-peda$ b *0x400f67Breakpoint 3 at 0x400f67gdb-peda$ rStarting program [..]Enter a key: aaaaaaaaaaaaaBreakpoint 3, 0x0000000000400f67 in ?? ()gdb-peda$ i r rdirdi            0x7fffffffde30   0x7fffffffde30```
rdi contains the address of the password. 
```gdb-peda$ x/20wx *0x7fffffffde300x615e70:   0x00000000  0x00000001  0x00000001  0x000000020x615e80:   0x00000003  0x00000005  0x00000008  0x0000000d0x615e90:   0x00000015  0x00000008  0x00000003  0x0000000b0x615ea0:   0x0000000e  0x00000019  0x00000411  0x000000000x615eb0:   0x65746e45  0x20612072  0x3a79656b  0x00000020```
And, for the length...
```gdb-peda$ ngdb-peda$ i r eax rax            0xe    0xe```
So...
```python#!/usr/bin/env python3k = [0x0,0x1,0x1,0x2,0x3,0x5,0x8,0xd,0x15,0x8,0x3,0xb,0xe,0x19]print(''.join([chr(i+97) for i in k]))```
```$ python guessme_key.pyabbcdfinvidloz$ ./guessmeEnter a key: abbcdfinvidlozGood key!The flag is: 0x00CTF{abbcdfinvidloz}