By ccoma | February 18, 2018
Codegate2018 Boom 출제자 Write Up
안녕하세요.
이번 Codegate2018 예선에 boom
과 miro
를 출제한 ccoma
입니다.
이번 글에서는 boom
의 풀이에 대해 간단히 다루어보려고 합니다.
문제에 접속하면, 서버 접속 주소와 함께 boom
이라는 바이너리를 제공받습니다.
boom
은 RUST
언어로 구현 된 바이너리입니다.
실행을 시키면 입력을 기다리고, aa
를 입력하니 You need 5 more blocks
라는 문구를 출력 하고 프로그램이 종료됩니다.
즉 5개의 block을 모아야 한다는 사실을 알 수 있습니다.
어떤 값을 입력해야 하는지 확인하기 위해 IDA
로 바이너리를 열면 아래와 같은 함수를 확인할 수 있습니다.
func1
~ func7
까지의 함수에서는 값을 입력 받고, 해당 값을 연산한 후 그 결과에 따라 특정 파일을 읽거나 func8
혹은 func9
를 호출 합니다.
또한 함수 종료 시 LinkedList
에 숫자를 저장하고 각각 다른 함수를 호출합니다.
각 함수를 간단히 분석하면 다음과 같습니다.
func1
문장을 입력 받으며, 입력하는 문장이
Know what? It's a new day~
,It's cold outside..
,We need little break!
중 하나와 일치해야 한다.각각
func2
,func3
,func5
을 호출한다.
func2
숫자 7개를 입력 받으며, 해당 숫자를 연산 한 값을 인덱스로 사용한다.
f7*zq5$ase0t6ui#^yd2owgb_n8pu4!k&vc@lrj19mx3h
문자열에서 인덱스에 해당하는 문자열을 추출 해 그 값이carame1
,w33kend
,pand0ra
와 일치해야 한다.각각
func4
,func5
,func7
을 호출한다.
func3
R L T B 중 6개의 문자를 입력 받으며, 해당 값에 따라 2차원 배열에 저장되어 있는 값의 위치를 변경한다.
배열에 저장되어 있는 숫자가 오름차순으로 정렬 되면
func6
을 호출한다.
func4
숫자 4개를 입력받으며, 숫자를 바탕으로 배열의 해당 위치를 기준으로 상, 하, 좌, 우에 있는 값이 반전된다.
배열에 저장되어 있는 숫자가 모두 0이 되거나 모두 1이 되도록 변경해야 한다.
모두 0일 경우에는
func6
을, 모두 1일 경우에는func3
을 호출한다.
func5
숫자 한개를 입력 받아
func12
를 호출한다.
func12
를 수행 한 결과 값이 107일 경우func4
를 호출한다.
func6
문자열을 입력 받으며, 입력 한 문자열을 한 글자 씩 연산 한 결과가
H_vocGfsg4p_xicwcrwexg4r
혹은G_veqijcGvi_qcL4rcGl4a44
여야 한다.각각
func2
와func7
을 호출한다.
func7
* 25개의 숫자를 입력 받음. * 5 * 5의 마방진을 만드는 함수이며, 입력한 25개의 숫자가 함수 내에서 만들어진 마방진과 순서가 일치하면func5
를 호출 함.
func8
*func1
~func7
함수 실행 중, 잘못된 값이 입력됬을 경우 호출되는 함수. *func11
을 호출하며,BOOOOOOMMM!!!
을 출력하고 프로그램을 종료.
func9
*func1
~func7
함수 실행 중, 잘못된 값이 입력됬을 경우 호출되는 함수. * 따로 호출하는 함수 없이 바로BOOOOOOMMM!!!
을 출력하고 프로그램을 종료.
func10
*func2
에서 입력 받은 숫자를 연산하기 위해 호출하는 함수.
func11
*func8
에서 호출하는 함수. *func1
~func7
을 실행하며 저장 한 숫자를 비교하고, 해당 숫자가 일치할 경우 읽었던 문자열을 연산 후 이를Enter This!
와 함께 출력 해 줌. * 즉,func1
~func7
까지의 함수 중 특정 함수를 특정 순서에 알맞게 실행 했는지 확인하고, 일치한다면FLAG
를 출력.
func12
*func5
에서 호출하는 함수. * 입력 된 숫자가 홀수일 경우3n+1
을, 짝수일 경우에는n/2
를 수행하고 한번 수행할 때마다 그 길이를 저장 * 만약 숫자가 1이 된다면 길이를 반환.
func13
* 파일의 내용을 읽는 함수.
즉, FLAG
를 얻기 위해선 func11
에서 요구하는 특정 순서로 특정 함수를 실행해야 하며, 함수 방문 후에는 잘못된 값을 입력 해 func8
을 호출해 func11
을 실행해야 합니다.
func11
를 분석 해 보면, 비교하는 숫자는 17
, 28
, 11
, 54
입니다.
해당 숫자는 각각 func1
, func2
, func7
, func5
가 호출되었을 때 저장하는 값입니다.
따라서 FLAG
를 얻기 위해서는 func1
, func2
, func7
, func5
를 호출하도록 값을 입력하고, 마지막에는 잘못된 값을 입력 해 func8
을 통해 func11
을 호출해야 합니다.
FLAG
를 얻기 위해 입력해야 하는 값은 아래와 같습니다.
- Know what? It’s a new day~
- 72 93 23 92 50 86 93
- 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9
- 31
- 1 2 3 4 (
func8
을 호출하기 위한 잘못된 값)
그런데 실제 서버에서는 약 5초의 시간 제한이 있으므로 아래와 같이 코드를 구현 해 FLAG
를 얻을 수 있습니다.
import socket
import sys
import re
import time
HOST = "boom.codegate.kr"
PORT = 8008
ADDR = (HOST, PORT)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(ADDR)
payload = ["Know what? It's a new day~\n", "72 93 23 92 50 86 93\n", "17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9\n", "31\n", "1 2 3 4\n"]
data = s.recv(1024)
print data
for i in range(0,5):
s.send (payload[i])
print payload[i]
data = s.recv(1024)
print data
time.sleep(1)
실행 결과 아래와 같이 FLAG
를 얻을 수 있습니다.
문제 풀어주신 모든 분들 수고 많으셨습니다!