CTF/Misc

PatriotCTF 2024 - Emoji Stack

xoheon 2024. 9. 23. 12:04

πŸ’‘ λ¬Έμ œλŠ” λ‹€μŒκ³Ό κ°™λ‹€


풀이

 

def emoji_stack_interpreter(program):
    # Initialize the stack (256 cells) and the pointer
    stack = [0] * 256
    pointer = 0
    output = []
    
    # Create a pointer for reading the program
    i = 0
    
    # Helper function to get the current value at the pointer
    def get_value():
        return stack[pointer]

    # Helper function to update the stack with modular arithmetic
    def set_value(value):
        stack[pointer] = value % 256

    while i < len(program):
        cmd = program[i]
        
        if cmd == ':point_right:':
            pointer = (pointer + 1) % 256  # Move right, wrap around if needed
        elif cmd == ':point_left:':
            pointer = (pointer - 1) % 256  # Move left, wrap around if needed
        elif cmd == ':thumbsup:':
            set_value(get_value() + 1)  # Increment the current cell
        elif cmd == ':thumbsdown:':
            set_value(get_value() - 1)  # Decrement the current cell
        elif cmd == ':speech_balloon:':
            output.append(chr(get_value()))  # Print the ASCII value of the current cell
        elif cmd == ':repeat:':
            # Repeat the previous instruction (next two characters represent the hex value)
            repeat_count = int(program[i+1:i+3], 16)
            previous_cmd = program[i-1]
            for _ in range(repeat_count):
                if previous_cmd == ':thumbsup:':
                    set_value(get_value() + 1)
                elif previous_cmd == ':thumbsdown:':
                    set_value(get_value() - 1)
                elif previous_cmd == ':point_right:':
                    pointer = (pointer + 1) % 256
                elif previous_cmd == ':point_left:':
                    pointer = (pointer - 1) % 256
            i += 2  # Skip the next two hex characters
        i += 1

    return ''.join(output)


# Read the content of the input file
file_path = 'input.txt'
with open(file_path, 'r') as file:
    program = file.read()

# Run the interpreter
flag = emoji_stack_interpreter(program)
print(flag)

 

1. . emoji_stack_interpreter ν•¨μˆ˜ μ •μ˜

 

μŠ€νƒ μ΄ˆκΈ°ν™”:

stack = [0] * 256: 256개의 μ…€λ‘œ κ΅¬μ„±λœ μŠ€νƒμ„ 0으둜 μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.

 

pointer = 0: μŠ€νƒ ν¬μΈν„°λŠ” μ²˜μŒμ— 첫 번째 셀을 κ°€λ¦¬ν‚΅λ‹ˆλ‹€.

 

output = []: κ²°κ³Ό λ¬Έμžμ—΄μ„ 담을 λ¦¬μŠ€νŠΈμž…λ‹ˆλ‹€.

 

get_value ν•¨μˆ˜: ν˜„μž¬ 포인터가 κ°€λ¦¬ν‚€λŠ” μ…€μ˜ 값을 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€.

 

set_value ν•¨μˆ˜: ν˜„μž¬ 셀에 값을 넣을 λ•Œ 256으둜 λ‚˜λˆˆ λ‚˜λ¨Έμ§€λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€. μ΄λŠ” μ…€ 값이 0~255 사이에 μžˆλ„λ‘ 보μž₯ν•©λ‹ˆλ‹€.

 

2. while 루프:

 

ν”„λ‘œκ·Έλž¨μ˜ 각 λͺ…령을 ν•œ κΈ€μžμ”© μ½μœΌλ©΄μ„œ μ²˜λ¦¬ν•©λ‹ˆλ‹€.

 

포인터 이동 (πŸ‘‰, πŸ‘ˆ):

πŸ‘‰: μŠ€νƒ 포인터λ₯Ό 였λ₯Έμͺ½μœΌλ‘œ μ΄λ™ν•©λ‹ˆλ‹€. pointer = (pointer + 1) % 256둜, 256을 λ„˜μ–΄κ°€λ©΄ λ‹€μ‹œ 처음으둜 λŒμ•„μ˜΅λ‹ˆλ‹€.

 

πŸ‘ˆ: μŠ€νƒ 포인터λ₯Ό μ™Όμͺ½μœΌλ‘œ μ΄λ™ν•©λ‹ˆλ‹€. pointer = (pointer - 1) % 256둜, 0μ—μ„œ μ™Όμͺ½μœΌλ‘œ κ°€λ©΄ λ§ˆμ§€λ§‰ μ…€λ‘œ μ΄λ™ν•©λ‹ˆλ‹€.

 

κ°’ 증가 및 κ°μ†Œ (πŸ‘, πŸ‘Ž):

πŸ‘: ν˜„μž¬ μ…€ 값을 1 μ¦κ°€μ‹œν‚΅λ‹ˆλ‹€.

πŸ‘Ž: ν˜„μž¬ μ…€ 값을 1 κ°μ†Œμ‹œν‚΅λ‹ˆλ‹€.

 

좜λ ₯ λͺ…λ Ή (πŸ’¬):

ν˜„μž¬ μ…€μ˜ 값을 ASCII 문자둜 λ³€ν™˜ν•΄ output λ¦¬μŠ€νŠΈμ— μΆ”κ°€ν•©λ‹ˆλ‹€. chr(get_value())λ₯Ό 톡해 ASCII λ³€ν™˜μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

 

반볡 처리 (πŸ”):

πŸ” λ‹€μŒμ— μ˜€λŠ” 두 자리 μˆ«μžλŠ” 16μ§„μˆ˜λ‘œ λͺ‡ 번 λ°˜λ³΅ν• μ§€ λ‚˜νƒ€λƒ…λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ πŸ”47은 직전 λͺ…령을 0x47(즉, 71번) λ°˜λ³΅ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

이 λ•Œ 직전 λͺ…λ Ή(πŸ‘, πŸ‘Ž, πŸ‘‰, πŸ‘ˆ)을 λ°˜λ³΅ν•΄μ„œ μ‹€ν–‰ν•©λ‹ˆλ‹€.

 

3. 파일 읽기:

 

input.txt νŒŒμΌμ„ 읽어 Emoji Stack ν”„λ‘œκ·Έλž¨ λ‚΄μš©μ„ κ°€μ Έμ˜΅λ‹ˆλ‹€.

 

4. 해석기 μ‹€ν–‰:

 

emoji_stack_interpreter(program) ν•¨μˆ˜μ— νŒŒμΌμ—μ„œ 읽은 ν”„λ‘œκ·Έλž¨μ„ μ „λ‹¬ν•˜μ—¬ μ‹€ν–‰ν•œ ν›„, 좜λ ₯κ°’(ν”Œλž˜κ·Έ)을 λ°˜ν™˜