[DreamHack] [Pwnable] 나랏말싸미 악용하기

image.png

image.png

나랏말싸미… 듕귁에달아…

리버싱부터 시작하겠다.

main 부터 보면,

image.png

image.png

Flag를 출력해주는 부분이 있고, 사용 방법 등 기본 역할을 하는 부분을 확인할 수 있다.

저기서 Game::run 함수 부분을 확인해보겠다.

image.png

image.png

image.png

나랏말싸미 악용하기에서는 입력으로 map을 줄 수 있다.

따라서, run에서 사용할 수 있는 취약점을 찾아야한다.

arr1 이 스택이고, arr[10000]이 스택 카운터라는 것을 알 수 있다.

분석해보면, 해당 vm의 동작 방식은 다음과 같다.

초성 case 값 행동
0 stack.pop()
1 stack.push([현재 칸의 글자의 종성값])
6 덧셈 연산. 현재 칸의 글자에 종성이 있을 경우: stack[-1] += 종성 / 종성이 없을 경우: stack[-2] = stack[-1] + stack[-2]; stack.pop()
7 뺄셈 연산. 덧셈 연산과 동일한 방식으로 동작.
8 곱셈 연산. 덧셈 연산과 동일한 방식으로 동작.
9 나눗셈 연산. 덧셈 연산과 동일한 방식으로 동작.
10 나머지 연산. 덧셈 연산과 동일한 방식으로 동작.
11 No-op.
12 Load 연산. value = map[stack[-1]][stack[-2]] 의 종성; stack.pop(); stack.pop(); stack.push(value);
13 Save 연산. map[stack[-2]][stack[-3]]의 종성 = stack[-1]; stack.pop(); stack.pop(); stack.pop();
15 Conditional branch 연산. stack[-1] >= stack[-2] 을 만족하지 못했을 때 원래 향할 방향의 반대로 이동.
16 Conditional branch 연산. stack[-1] == stack[-2] 을 만족하지 못했을 때 원래 향할 방향의 반대로 이동.
17 exit([현재 칸의 글자의 종성값])
18 stack.push(input[input_ptr++])

모음이 ㅗ, ㅜ, ㅓ, ㅏ일 경우 각각 상, 하, 좌, 우에 있는 칸으로 움직인다.