반응형
Description
이게 Python....?
Blitz CTF 문제였다.
Write-up
Step1) 문제 파일 압축을 풀어보면 총 3개의 파일이 존재한다. main.txt와 hard2rev.txt에는 바이트 코드 형식으로 작성되어 있다.
(❓바이트 코드 : 고급 언어로 작성된 소스 코드를 가상머신이 이해할 수 있는 중간 코드로 컴파일한 것을 말한다.)
// main.txt
4 0 LOAD_CONST 1 (** FLAG censored **)
2 STORE_FAST 0 (v1)
5 4 LOAD_GLOBAL 0 (list)
6 LOAD_FAST 0 (v1)
8 LOAD_METHOD 1 (encode)
10 CALL_METHOD 0
12 CALL_FUNCTION 1
14 STORE_FAST 0 (v1)
6 16 LOAD_GLOBAL 2 (range)
18 LOAD_CONST 2 (0)
20 LOAD_GLOBAL 3 (len)
22 LOAD_FAST 0 (v1)
24 CALL_FUNCTION 1
26 CALL_FUNCTION 2
28 GET_ITER
>> 30 FOR_ITER 20 (to 52)
32 STORE_FAST 1 (i)
7 34 LOAD_FAST 0 (v1)
36 LOAD_FAST 1 (i)
38 DUP_TOP_TWO
40 BINARY_SUBSCR
42 LOAD_FAST 1 (i)
44 INPLACE_XOR
46 ROT_THREE
48 STORE_SUBSCR
50 JUMP_ABSOLUTE 30
8 >> 52 LOAD_GLOBAL 4 (hard2rev)
54 LOAD_FAST 0 (v1)
56 CALL_FUNCTION 1
58 STORE_FAST 0 (v1)
9 60 LOAD_GLOBAL 5 (print)
62 LOAD_FAST 0 (v1)
64 CALL_FUNCTION 1
66 POP_TOP
68 LOAD_CONST 0 (None)
70 RETURN_VALUE
// hard2rev.txt
12 0 LOAD_GLOBAL 0 (range)
2 LOAD_GLOBAL 1 (len)
4 LOAD_FAST 0 (v1)
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 GET_ITER
>> 12 FOR_ITER 50 (to 64)
14 STORE_FAST 1 (j)
13 16 LOAD_FAST 0 (v1)
18 LOAD_FAST 1 (j)
20 BINARY_SUBSCR
22 LOAD_CONST 1 (36)
24 BINARY_ADD
26 LOAD_FAST 0 (v1)
28 LOAD_FAST 1 (j)
30 STORE_SUBSCR
14 32 LOAD_GLOBAL 0 (range)
34 LOAD_FAST 1 (j)
36 LOAD_CONST 2 (2)
38 BINARY_FLOOR_DIVIDE
40 CALL_FUNCTION 1
42 GET_ITER
>> 44 FOR_ITER 16 (to 62)
46 STORE_FAST 2 (x)
15 48 LOAD_GLOBAL 2 (list)
50 LOAD_GLOBAL 3 (reversed)
52 LOAD_FAST 0 (v1)
54 CALL_FUNCTION 1
56 CALL_FUNCTION 1
58 STORE_FAST 0 (v1)
60 JUMP_ABSOLUTE 44
>> 62 JUMP_ABSOLUTE 12
16 >> 64 LOAD_FAST 0 (v1)
66 RETURN_VALUE
// output.txt
[140, 109, 157, 112, 179, 126, 140, 110, 179, 144, 121, 123, 189, 147, 155, 108, 199, 153, 155, 103, 185, 138, 91, 106]
Step2) 파이썬 바이트 코드를 역어셈블리해보면 아래와 같다.
# main.txt
v1 = "** FLAG censored **"
v1 = list(v1.encode())
for i in range(len(v1)):
v1[i] ^= i # 각 바이트에 인덱스 값을 XOR
v1 = hard2rev(v1)
print(v1)
# hard2rev.txt
def hard2rev(v1):
for j in range(len(v1)):
v1[j] = v1[j] + 36
for x in range(j // 2):
v1 = list(reversed(v1)) # 리스트를 뒤집음
return v1
Step3) 위의 코드를 참고하여 output.txt에 적힌 숫자 리스트를 이용하여 역으로 복호화하는 코드를 작성했다. 이것을 통해 최종 FLAG 값을 얻을 수 있다.
# reverse_flag.py
# 1. hard2rev2 되돌리기
def reverse_hard2rev(v1):
for j in reversed(range(len(v1))):
for _ in reversed(range(j //2)):
v1 = list(reversed(v1))
v1[j] -= 36
return v1
v1 = [140, 109, 157, 112, 179, 126, 140, 110, 179, 144, 121, 123, 189, 147, 155, 108, 199, 153, 155, 103, 185, 138, 91, 106]
# 1. hard2rev2 되돌리기
v1 = reverse_hard2rev(v1)
# 2. xor 되돌리기
for i in range(len(v1)):
v1[i] ^= i
# 3. ASCII 문자로 변환
flag = ''.join(chr(c) for c in v1)
print("\nFLAG =", flag)
Flag
반응형