Codegate2018 boom

By ccoma | February 18, 2018

Codegate2018 Boom 출제자 Write Up

안녕하세요. 이번 Codegate2018 예선에 boommiro를 출제한 ccoma입니다.
이번 글에서는 boom의 풀이에 대해 간단히 다루어보려고 합니다.


문제에 접속하면, 서버 접속 주소와 함께 boom 이라는 바이너리를 제공받습니다.

boomRUST 언어로 구현 된 바이너리입니다.

실행을 시키면 입력을 기다리고, 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 여야 한다.

  • 각각 func2func7을 호출한다.


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를 얻을 수 있습니다.



문제 풀어주신 모든 분들 수고 많으셨습니다!

comments powered by Disqus