MISC => 더 풀래구 줴눼뤠위퉈 

 

flagGenerator.zip
0.00MB

 

 

우선 nc 로 접속하면 아래와 같이 실행이 된다.
어떤 값을 입력하면 flag 값과 flag check 값이 출력이 된다.

여기서 입력값은 예시 처럼 {“0” : 53} 이런 식으로 json 타입으로 입력을 해야 한다는 것이다.

 

 

이번 문제는 친절하게 소스코드를 올려 주었기 때문에, 위 파일의 소스 코드를 열어 보면 다음과 같다.

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import json
import string

character_list = string.ascii_letters + string.digits + "_@"
len_character_list = len(character_list)


class FlagGenerator():
    def __init__(self, xor_key: str):
        self.config = dict()

        self.key = xor_key
        self.last_key_index = 0

    def __generate_flag_str(self) -> str:
        flag_str = ""
        mix = list(map(ord, "XXXXX_THIS_IS_SECRET_MIX_KEY_XXXXX"))

        for i, k in enumerate(self.key):
            mix_value = mix[i]

            if str(i) in self.config:
                mix_value ^= self.config[str(i)]

            c = character_list[(mix_value ^ k) % len_character_list]
            flag_str += c

        return flag_str

    def generate_flag(self) -> str:
        return self.__generate_flag_str()


if __name__ == "__main__":
    print("""
    [[ The Flag Generator | generate your own flag]]
    * You need to input your config, and It will generate your own flag with your config!
    * Config example : {"0": 53, "1": 35}
    """)

    real_flag = "XXXXX_THIS_IS_SECRET_FLAG_XXXXX"
    secret_key = list(map(character_list.index, real_flag))

    while True:
        user_input = input("Input your generator config > ")
        config = dict()

        try:
            config.update(json.loads(user_input))
        except:
            pass

        generator = FlagGenerator(secret_key)
        generator.config.update(config)

        flag = generator.generate_flag()
        correct = 0

        for i, c in enumerate(real_flag):
            if flag[i] != c:
                break
            correct += 1

        print("Your flag is HCAMP{{{}}}".format(flag))
        print("Flag Check : {}/{}".format(correct, len(real_flag)))
        print("")

 

 

위 소스 코드를 분석을 하면 다음과 같다.

  •  6  : character_list = ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_@’  다음과 같은 값이 들어간다.
  • 45 ~ 46  : secret_key 변수에는 map 함수를 통해 리스트 형식으로 저장을 하게 되는데, 이 코드의 의미는 다음 코드와 같다.
character_list = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_@'
real_flag = 'XXXXX_THIS_IS_SECRET_FLAG_XXXXX'
secret_key = []

for i in range(len(real_flag)):
	secret_key.append(character_list.index(real_flag[i]))
print(secret_key)

# Result
# [49, 49, 49, 49, 49, 62, 45, 33, 34, 44, 62, 34, 44, 62, 44, 30, 28, 43, 30, 45, 62, 31, 37, 26, 32, 62, 49, 49, 49, 49, 49]
  • 위 코드대로 해석하면 secret_key = [49, 49, 49, 49, 49, 62, 45, 33, 34, 44, 62, 34, 44, 62, 44, 30, 28, 43, 30, 45, 62, 31, 37, 26, 32, 62, 49, 49, 49, 49, 49] 값을 가지게 된다.
  •  53  : config 변수에 user가 입력한 값을 json 타입으로 저장한다.
  •  57  : FlagGenerator 클래스를 호출함과 동시에 secret_key를 key에 저장한다.
  •  60  : generate_flag 함수를 호출하여 flag 값을 얻어낸다. flag를 생성하는 조건은 다음과 같다.
    •  19  : 이 코드는 46번줄에서 했던 방식과 같은 방법이므로,
      mix = [88, 88, 88, 88, 88, 95, 84, 72, 73, 83, 95, 73, 83, 95, 83, 69, 67, 82, 69, 84, 95, 77, 73, 88, 95, 75, 69, 89, 95, 88, 88, 88, 88, 88]  라는 값이 들어간다.
    •  21 ~ 28  : 반복문을 통해 flag를 생성하게 되는데, user가 입력한 값인 config 변수에서 key 부분이 0 부터 flag의 길이 만큼의 숫자가 들어있는지 검사를 한다. 예를 들어 {“0” : 0, “1” : 0, “2” : 0} 이런식으로 입력을 했다면,  if문에서는 모든 조건이 만족하므로 25번줄의 ^ 연산자를 수행하지만, 만약 0,1,2 부분이 연속적이지 못하면 몇몇 부분은 조건에 만족하지 않아 ^ 연산을 하지 못하게 된다.
  •  63 ~ 66  : 이렇게 생성된 flag는 real_flag와 처음부터 한 자씩 비교하여 count 를 새게 되는데, 중간에 하나라도 다르면 반복문을 탈출 하게 된다.
    이 부분을 잘 생각해야 하는데, user가 입력한 config 값이 {“0” : 0} 이라고 가정하면, 위에 설명했듯이 첫번째 값만 flag를 생성하고 실제 flag와 비교한다. 만약 최종 count = 0 이면, 다시 {“0” : 1} 값을 넣어 count 값을 확인하고, 틀리면 {“0” : 2} …. 이렇게 하다보면 생성된 flag의 첫번째 글자가 실제 flag와 같아 질 때가 있을 것이다.
    두번째 글자를 맞추어야 하기 때문에 입력을 {“0” : 53. “1” : 0} 이런식으로 넣어서 실제 flag의 두번째 글자를 찾고… 이와같은 과정을 반복하면 flag를 얻을 수 있다.

 

위에서 말한 방법을 토대로 코드를 작성하면 아래와 같다.

from pwn import *
import string
import time

nc = remote('kshgroup.kr', 19191)
send_data = ''

for count in range(0,21):
        for i in range(0,125):
                string = '"'+str(count)+'":'+str(i)
                nc.sendline("{"+send_data+string+"}")
                nc.recvuntil('Your flag is')
                result = nc.recv().replace('Input your generator config >','').replace('\n','')

                flag = result[1:result.index('Flag')]
                check = result[result.index('Check')+8:result.index('/')]
                print(flag)
                
                if int(check) == count+1:
                        send_data += string+","
                        break

 

 

HCAMP{B33P_B33P@@_Fla9_Fl4g}