본문 바로가기

드림핵

[드림핵 워게임] amocafe

<문제>

 

<풀이>

1. 문제 사이트와 코드 살펴보기

문제의 사이트에 접속해보면 처음에 위와 같은 화면이 뜬다. 아모의 최애 메뉴(1_c_3_c_0__ff_3e)가 암호화된 문자열로 주어지고, menu number를 입력할 수 있는 입력창을 확인할 수 있다.

 

	<p class="bold">
      "My favorite menu is <code>{{ menu }}</code> 🥤"
      <form action="/" method="post">
        <input name="menu_input" maxlength="20" placeholder="menu number" type="text" />
        <button>order</button>
      </form>
    </p>

해당 부분에 대한 코드를 templates/index.html 파일에서 확인해보면 암호화된 문자열은 {menu} 라는 파라미터를 통해 전달받고 있는 것을 볼 수 있다.

 

입력창에 아무 숫자나 입력해보았다.

 

try again... 이라는 결과가 뜬다.

 

    # POST
    if request.method == "POST":
        input_str =  request.form.get("menu_input", "")
        if input_str == str(org):
            return render_template('index.html', menu=menu_str, flag=FLAG)
        return render_template('index.html', menu=menu_str, flag='try again...')

해당하는 부분의 코드를 app.py에서 살펴보면 입력값 "1234"를 input_str로 받아서 그 값이 str(org)와 같으면 FLAG를 출력하고 같지 않으면 try again...을 출력하는 것을 확인할 수 있다.

그리고 여기에서 menu 파라미터에 전달되는 1_c_3_c_0__ff_3e 값이 menu_str 변수에 저장되어있는 값인 것도 확인할 수 있다.

 

org에 어떤 값이 들어있고, menu_str은 어떻게 만들어진 것인지 분석할 필요가 있다.

 

 

2. 코드 심층 분석

    menu_str = ''
    org = FLAG[10:29]
    org = int(org)
    st = ['' for i in range(16)]

    for i in range (0, 16):
        res = (org >> (4 * i)) & 0xf
        if 0 < res < 12:
            if ~res & 0xf == 0x4:
                st[16-i-1] = '_'
            else:
                st[16-i-1] = str(res)
        else:
            st[16-i-1] = format(res, 'x')
    menu_str = menu_str.join(st)

org와 menu_str에 대한 코드를 app.py의 index() 함수에서 확인할 수 있다.

org에는 FLAG의 일부를 추출한 값이 들어간다.

 

그리고 그 값이 알고리즘을 거쳐 암호화되고,

암호화된 문자열이 menu_str에 들어간다.

 

암호화 알고리즘을 분석해서 역으로 복호화하면 org의 값을 알 수 있다.

그렇게 알아낸 org 값을 사이트의 입력창에 입력하면 FLAG가 출력될 것이다.

 

3. 익스플로잇

str="1_c_3_c_0__ff_3e" #menu
n=0
s=0

for i in range(0, 16): #decrypt
    if str[16-i-1] == "_":
        n=11
    elif str[16-i-1] == "c":
        n=12
    elif str[16-i-1] == "d":
        n=13
    elif str[16-i-1] == "e":
        n=14
    elif str[16-i-1] == "f":
        n=15
    else:
        n=int(str[16-i-1])
    n=n << 4 * i

    s += n

print(s) #org

아직 인코딩, 디코딩에 익숙하지 않아서 시간이 좀 걸리긴 했지만,

차근차근 알고리즘을 분석해나가며 결국 위와 같은 익스플로잇 코드를 짤 수 있었다.

 

4. FLAG 얻기

익스플로잇 코드를 돌려 출력된 값을 사이트에 입력하자 FLAG가 출력되었다.